38
48
//----------------------------------------------------------------------------
39
49
TabDlg::TabDlg(PsiCon *psiCon)
51
if ( option.brushedMetal )
52
setAttribute(Qt::WA_MacMetalStyle);
43
//this->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
45
tabMenu = new QPopupMenu( this );
46
connect( tabMenu, SIGNAL( aboutToShow() ), SLOT( buildTabMenu() ) );
48
tabs = new KTabWidget (this);
50
closeCross = new QPushButton(this);
51
//closeCross->setText("x");
52
closeCross->setIconSet(IconsetFactory::icon("psi/closetab").iconSet());
54
if (option.usePerTabCloseButton)
55
tabs->setHoverCloseButton(true);
58
tabs->setHoverCloseButton(false);
59
tabs->setCornerWidget( closeCross );
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* ) ) );
55
tabMenu = new QMenu( this );
57
tabs = new PsiTabWidget (this);
58
tabs->setCloseIcon(IconsetFactory::icon("psi/closetab").icon());
59
//tabs->setCloseIcon(IconsetFactory::icon("psi/closetab").iconSet());
60
connect (tabs, SIGNAL( mouseDoubleClickTab( QWidget* ) ), SLOT( detachChat( QWidget* ) ) );
61
connect (tabs, SIGNAL(aboutToShowMenu(QMenu *)), SLOT(tab_aboutToShowMenu(QMenu *)));
62
connect (tabs, SIGNAL(tabContextMenu(int,QPoint,QContextMenuEvent*)), SLOT(showTabMenu(int,QPoint,QContextMenuEvent*)));
64
//connect (tabs, SIGNAL( testCanDecode(const QDragMoveEvent*, bool&) ), SLOT( tabTestCanDecode(const QDragMoveEvent*, bool&) ) );
65
//connect (tabs, SIGNAL( receivedDropEvent( QDropEvent* ) ), SLOT( tabReceivedDropEvent( QDropEvent* ) ) );
66
//connect (tabs, SIGNAL( receivedDropEvent( QWidget*, QDropEvent* ) ), SLOT( tabReceivedDropEvent( QWidget*, QDropEvent* ) ) );
67
//connect (tabs, SIGNAL( initiateDrag( QWidget* ) ), SLOT( startDrag( QWidget* ) ) );
68
//connect (tabs, SIGNAL( closeRequest( QWidget* ) ), SLOT( closeChat( QWidget* ) ) );
74
71
QVBoxLayout *vert1 = new QVBoxLayout( this, 1);
76
73
chats.setAutoDelete( FALSE );
77
74
X11WM_CLASS("chat");
79
connect( closeCross, SIGNAL( clicked() ), SLOT( closeChat() ) );
76
connect( tabs, SIGNAL( closeButtonClicked() ), SLOT( closeChat() ) );
80
77
connect( tabs, SIGNAL( currentChanged( QWidget* ) ), SLOT( tabSelected( QWidget* ) ) );
82
79
setAcceptDrops(TRUE);
89
83
resize(option.sizeTabDlg);
85
act_close = new QAction(this);
87
connect(act_close,SIGNAL(activated()), SLOT(closeChat()));
88
act_prev = new QAction(this);
90
connect(act_prev,SIGNAL(activated()), SLOT(previousTab()));
91
act_next = new QAction(this);
93
connect(act_next,SIGNAL(activated()), SLOT(nextTab()));
104
Q_DECLARE_METATYPE ( TabDlg* );
107
void TabDlg::setShortcuts()
109
//act_close->setShortcuts(ShortcutManager::instance()->shortcuts("common.close"));
110
act_prev->setShortcuts(ShortcutManager::instance()->shortcuts("chat.previous-tab"));
111
act_next->setShortcuts(ShortcutManager::instance()->shortcuts("chat.next-tab"));
97
114
void TabDlg::resizeEvent(QResizeEvent *e)
99
116
if(option.keepSizes)
100
117
option.sizeTabDlg = e->size();
103
void TabDlg::buildTabMenu()
120
void TabDlg::showTabMenu(int tab, QPoint pos, QContextMenuEvent * event)
105
122
tabMenu->clear();
106
tabMenu->insertItem( tr("Detach Current Tab"), this, SLOT( detachChat() ) );
107
tabMenu->insertItem( tr("Close Current Tab"), this, SLOT( closeChat() ) );
109
QPopupMenu* sendTo = new QPopupMenu(tabMenu);
125
QAction *d = tabMenu->addAction(tr("Detach Tab"));
126
QAction *c = tabMenu->addAction(tr("Close Tab"));
128
QMenu* sendTo = new QMenu(tabMenu);
129
sendTo->setTitle(tr("Send Tab to"));
130
QMap<QAction*, TabDlg*> sentTos;
131
for (uint i = 0; i < psi->getTabSets()->count(); ++i)
133
TabDlg* tabSet= psi->getTabSets()->at(i);
134
QAction *act = sendTo->addAction( tabSet->getName());
135
if (tabSet == this) act->setEnabled(false);
136
sentTos[act] = tabSet;
138
tabMenu->addMenu(sendTo);
140
QAction *act = tabMenu->exec(pos);
143
closeChat(getTab(tab));
144
} else if (act == d) {
145
detachChat(getTab(tab));
147
TabDlg* target = sentTos[act];
148
if (target) queuedSendChatTo(getTab(tab), target);
153
void TabDlg::tab_aboutToShowMenu(QMenu *menu)
155
menu->addSeparator ();
156
menu->addAction( tr("Detach Current Tab"), this, SLOT( detachChat() ) );
157
menu->addAction( tr("Close Current Tab"), this, SLOT( closeChat() ) );
159
QMenu* sendTo = new QMenu(menu);
160
sendTo->setTitle(tr("Send Current Tab to"));
161
int tabdlgmetatype = qRegisterMetaType<TabDlg*>("TabDlg*");
110
162
for (uint i = 0; i < psi->getTabSets()->count(); ++i)
112
164
TabDlg* tabSet= psi->getTabSets()->at(i);
113
sendTo->insertItem( tabSet->getName(), this, SLOT( sendChatTo( tabSet ) ) );
165
QAction *act = sendTo->addAction( tabSet->getName());
166
act->setData(QVariant(tabdlgmetatype, &tabSet));
167
if (tabSet == this) act->setEnabled(false);
115
tabMenu->insertItem( tr("Sent Current Tab to"), sendTo);
169
connect(sendTo, SIGNAL(triggered(QAction*)), SLOT(menu_sendChatTo(QAction*)));
170
menu->addMenu(sendTo);
173
void TabDlg::menu_sendChatTo(QAction *act)
175
queuedSendChatTo(tabs->currentPage(), act->data().value<TabDlg*>());
118
178
void TabDlg::sendChatTo(QWidget* chatw, TabDlg* otherTabs)
124
184
otherTabs->addChat(chat);
187
void TabDlg::queuedSendChatTo(QWidget* chat, TabDlg *dest)
189
qRegisterMetaType<TabDlg*>("TabDlg*");
190
QMetaObject::invokeMethod(this, "sendChatTo", Qt::QueuedConnection, Q_ARG(QWidget*, chat), Q_ARG(TabDlg*, dest));
193
void TabDlg::optionsUpdate()
127
198
void TabDlg::setLooks()
129
200
//set the widget icon
131
setIcon(IconsetFactory::icon("psi/start-chat"));
202
setWindowIcon(IconsetFactory::icon("psi/start-chat").icon());
133
204
tabs->setTabPosition(QTabWidget::Top);
134
205
if (option.putTabsAtBottom)
135
206
tabs->setTabPosition(QTabWidget::Bottom);
137
#if QT_VERSION >= 0x030300
138
setWindowOpacity(double(option.chatOpacity)/100);
208
setWindowOpacity(double(qMax(MINIMUM_OPACITY,PsiOptions::instance()->getOption("options.ui.chat.opacity").toInt()))/100);
142
211
QString TabDlg::getName()
167
237
void TabDlg::addChat(ChatDlg* chat)
169
239
chats.append(chat);
170
tabs->addTab(chat, chat->getDisplayNick());
171
tabs->setTabIconSet(chat, IconsetFactory::icon("psi/start-chat"));
240
QString tablabel = chat->getDisplayNick();
241
tablabel.replace("&", "&&");
242
tabs->addTab(chat, tablabel);
243
//tabs->setTabIconSet(chat, IconsetFactory::icon("psi/start-chat").icon());
173
tabs->showPage(chat);
245
//tabs->showPage(chat);
174
246
connect ( chat, SIGNAL( captionChanged( ChatDlg*) ), SLOT( updateTab( ChatDlg* ) ) );
175
connect ( chat, SIGNAL( contactIsComposing(ChatDlg*, bool) ), SLOT( setTabComposing( ChatDlg*, bool) ) );
247
connect ( chat, SIGNAL( contactStateChanged( XMPP::ChatState ) ), SLOT( setTabState( XMPP::ChatState ) ) );
176
248
connect ( chat, SIGNAL( unreadMessageUpdate(ChatDlg*, int) ), SLOT( setTabHasMessages(ChatDlg*, int) ) );
280
* Removes the chat from the tabset, 'closing' it if specified.
281
* The method is used without closing tabs when transferring from one
283
* \param chat Chat to remove.
284
* \param doclose Whether the chat is 'closed' while removing it.
203
286
void TabDlg::closeChat(ChatDlg* chat, bool doclose=true)
288
if (doclose && !chat->readyToHide()) {
206
292
disconnect ( chat, SIGNAL( captionChanged( ChatDlg*) ), this, SLOT( updateTab( ChatDlg* ) ) );
207
disconnect ( chat, SIGNAL( contactIsComposing(ChatDlg*, bool) ), this, SLOT( setTabComposing( ChatDlg*, bool) ) );
293
disconnect ( chat, SIGNAL( contactStateChanged( XMPP::ChatState ) ), this, SLOT( setTabState( XMPP::ChatState ) ) );
208
294
disconnect ( chat, SIGNAL( unreadMessageUpdate(ChatDlg*, int) ), this, SLOT( setTabHasMessages(ChatDlg*, int) ) );
209
295
tabs->removePage(chat);
210
296
tabIsComposing.erase(chat);
211
297
tabHasMessages.erase(chat);
212
298
chats.remove(chat);
213
299
chat->reparent(0,QPoint());
300
if (doclose && chat->testAttribute(Qt::WA_DeleteOnClose))
216
302
if (tabs->count()>0)
284
371
//we do not delete it here, let the PsiCon do that, they create, they destroy.
375
ChatDlg *TabDlg::getTab(int i)
377
return ((ChatDlg*)tabs->page(i));
287
381
ChatDlg* TabDlg::getChatPointer(QString fullJid)
289
383
for (int i=0; i < tabs->count() ; i++)
291
if (((ChatDlg*)tabs->page(i))->jid().full()==fullJid)
385
if (getTab(i)->jid().full()==fullJid)
293
return (ChatDlg*)(tabs->page(i));
316
410
label=prefix+chat->getDisplayNick();
411
label.replace("&", "&&");
317
412
tabs->setTabLabel( chat, label );
318
413
//now set text colour based upon whether there are new messages/composing etc
319
415
if (tabIsComposing[chat])
320
tabs->setTabColor( chat, Qt::darkGreen );
416
tabs->setTabTextColor( chat, Qt::darkGreen );
321
417
else if (tabHasMessages[chat])
323
tabs->setTabColor( chat, Qt::red );
419
tabs->setTabTextColor( chat, Qt::red );
420
if (PsiOptions::instance()->getOption("options.ui.flash-windows").toBool())
327
tabs->setTabColor( chat, Qt::black );
424
tabs->setTabTextColor( chat, Qt::black );
331
void TabDlg::setTabComposing(ChatDlg* chat, bool composing)
428
void TabDlg::setTabState( XMPP::ChatState state )
333
tabIsComposing[chat]=composing;
430
ChatDlg* chat = (ChatDlg*) sender();
431
if ( state == XMPP::StateComposing )
432
tabIsComposing[chat] = true;
434
tabIsComposing[chat] = false;
356
457
tabs->setCurrentPage( page );
359
void TabDlg::tabTestCanDecode(const QDragMoveEvent* e, bool &b){
362
if ( QTextDrag::canDecode(e) && QTextDrag::decode(e, jid, type) && type=="psichatwindow" )
372
void TabDlg::tabReceivedDropEvent(QDropEvent* e){
376
if ( QTextDrag::decode(e, jid, type) && type=="psichatwindow" ) {
377
chat=psi->getChatInTabs(jid);
380
TabDlg *dlg=psi->getManagingTabs(chat);
381
dlg->sendChatTo(chat, this);
386
void TabDlg::tabReceivedDropEvent(QWidget* w, QDropEvent* e){
388
tabReceivedDropEvent(e);
392
void TabDlg::startDrag(QWidget* w)
394
QDragObject *d = new QTextDrag( ((ChatDlg*)w)->jid().full(), this );
395
((QTextDrag*)d)->setSubtype("psichatwindow");
400
460
void TabDlg::keyPressEvent(QKeyEvent *e)
402
if (e->key() == Key_Escape)
406
else if ( e->key() == Key_W && (e->state() & ControlButton) )
410
else if ( e->key() == Key_PageUp && (e->state() & ControlButton) )
462
if (e->key() == Qt::Key_Escape)
466
else if ( e->key() == Qt::Key_W && (e->modifiers() & Qt::ControlModifier) )
470
else if ( e->key() == Qt::Key_PageUp && (e->modifiers() & Qt::ControlModifier) )
414
else if ( e->key() == Key_PageDown && (e->state() & ControlButton) )
474
else if ( e->key() == Qt::Key_PageDown && (e->modifiers() & Qt::ControlModifier) )
483
void TabDlg::dragEnterEvent(QDragEnterEvent *event)
485
if ( event->mimeData()->hasFormat("psiTabDrag") ) {
486
event->setDropAction(Qt::MoveAction);
491
void TabDlg::dropEvent(QDropEvent *event)
494
if (event->mimeData()->hasFormat("psiTabDrag")) {
495
data = event->mimeData()->data("psiTabDrag");
499
int remoteTab = data.toInt();
500
event->acceptProposedAction();
501
//the event's been and gone, now do something about it
502
PsiTabBar* source = dynamic_cast<PsiTabBar*> (event->source());
505
PsiTabWidget* barParent = source->psiTabWidget();
506
QWidget* widget = barParent->widget(remoteTab);
507
ChatDlg* chat=dynamic_cast<ChatDlg*>(widget);
508
TabDlg *dlg=psi->getManagingTabs(chat);
511
dlg->queuedSendChatTo(chat, this);