• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdenetwork API Reference
  • KDE Home
  • Contact Us
 

kopete/kopete

  • sources
  • kde-4.12
  • kdenetwork
  • kopete
  • kopete
  • chatwindow
kopetechatwindow.cpp
Go to the documentation of this file.
1 /*
2  kopetechatwindow.cpp - Chat Window
3 
4  Copyright (c) 2008 by Benson Tsai <btsai@vrwarp.com>
5  Copyright (c) 2007 by Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net>
6  Copyright (c) 2002-2006 by Olivier Goffart <ogoffart@kde.org>
7  Copyright (c) 2003-2004 by Richard Smith <kde@metafoo.co.uk>
8  Copyright (C) 2002 by James Grant
9  Copyright (c) 2002 by Stefan Gehn <metz@gehn.net>
10  Copyright (c) 2002-2004 by Martijn Klingens <klingens@kde.org>
11 
12  Kopete (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org>
13 
14  *************************************************************************
15  * *
16  * This program is free software; you can redistribute it and/or modify *
17  * it under the terms of the GNU General Public License as published by *
18  * the Free Software Foundation; either version 2 of the License, or *
19  * (at your option) any later version. *
20  * *
21  *************************************************************************
22 */
23 
24 #include <QtCore/QTextStream>
25 #include <QtCore/QTimer>
26 #include <QtGui/QDockWidget>
27 #include <QtGui/QFrame>
28 #include <QtGui/QLabel>
29 #include <QtGui/QLayout>
30 #include <QtGui/QMenu>
31 #include <QtGui/QPixmap>
32 #include <QtGui/QCloseEvent>
33 #include <QtGui/QVBoxLayout>
34 
35 #ifdef CHRONO
36 #include <QTime>
37 #endif
38 
39 #include <kactioncollection.h>
40 #include <kcursor.h>
41 #include <klocale.h>
42 #include <kmenubar.h>
43 #include <kconfig.h>
44 #include <kmenu.h>
45 #include <kicon.h>
46 #include <kiconloader.h>
47 #include <kdebug.h>
48 #include <kwindowsystem.h>
49 #include <ktemporaryfile.h>
50 #include <kedittoolbar.h>
51 #include <kstatusbar.h>
52 #include <kpushbutton.h>
53 #include <ktabwidget.h>
54 #include <kdialog.h>
55 #include <kstringhandler.h>
56 #include <ksqueezedtextlabel.h>
57 #include <kstandardshortcut.h>
58 #include <kglobalsettings.h>
59 #include <kcolorscheme.h>
60 #include <khbox.h>
61 #include <kvbox.h>
62 #include <ktoolbar.h>
63 #include <kstandardaction.h>
64 #include <ktoggleaction.h>
65 #include <kactionmenu.h>
66 #include <ktoolbarspaceraction.h>
67 
68 #include "chatmessagepart.h"
69 #include "chattexteditpart.h"
70 #include "chatview.h"
71 #include "kopeteapplication.h"
72 #include "kopetebehaviorsettings.h"
73 #include "kopetechatwindow.h"
74 #include "kopeteemoticonaction.h"
75 #include "kopetegroup.h"
76 #include "kopetechatsession.h"
77 #include "kopetemetacontact.h"
78 #include "kopetepluginmanager.h"
79 #include "kopeteprotocol.h"
80 #include "kopetestdaction.h"
81 #include "kopeteviewmanager.h"
82 #include "chatmemberslistview.h"
83 #include "chatsessionmemberslistmodel.h"
84 
85 #include <qtoolbutton.h>
86 #include <kxmlguifactory.h>
87 #include <KTabBar>
88 
89 typedef QMap<Kopete::Account*,KopeteChatWindow*> AccountMap;
90 typedef QMap<Kopete::Group*,KopeteChatWindow*> GroupMap;
91 typedef QMap<Kopete::MetaContact*,KopeteChatWindow*> MetaContactMap;
92 typedef QList<KopeteChatWindow*> WindowList;
93 
94 using Kopete::ChatSessionMembersListModel;
95 
96 namespace
97 {
98  AccountMap accountMap;
99  GroupMap groupMap;
100  MetaContactMap mcMap;
101  WindowList windows;
102 }
103 
104 KopeteChatWindow *KopeteChatWindow::window( Kopete::ChatSession *manager )
105 {
106  bool windowCreated = false;
107  KopeteChatWindow *myWindow = 0;
108 
109  //Take the first and the first? What else?
110  Kopete::Group *group = 0L;
111  Kopete::ContactPtrList members = manager->members();
112  Kopete::MetaContact *metaContact = members.first()->metaContact();
113 
114  if ( metaContact )
115  {
116  Kopete::GroupList gList = metaContact->groups();
117  group = gList.first();
118  }
119 
120  switch( Kopete::BehaviorSettings::self()->chatWindowGroupPolicy() )
121  {
122  //Open chats from the same protocol in the same window
123  case Kopete::BehaviorSettings::EnumChatWindowGroupPolicy::GroupByAccount:
124  if( accountMap.contains( manager->account() ) )
125  myWindow = accountMap[ manager->account() ];
126  else
127  windowCreated = true;
128  break;
129 
130  //Open chats from the same group in the same window
131  case Kopete::BehaviorSettings::EnumChatWindowGroupPolicy::GroupByGroup:
132  if( group && groupMap.contains( group ) )
133  myWindow = groupMap[ group ];
134  else
135  windowCreated = true;
136  break;
137 
138  //Open chats from the same metacontact in the same window
139  case Kopete::BehaviorSettings::EnumChatWindowGroupPolicy::GroupByMetaContact:
140  if( mcMap.contains( metaContact ) )
141  myWindow = mcMap[ metaContact ];
142  else
143  windowCreated = true;
144  break;
145 
146  //Open all chats in the same window
147  case Kopete::BehaviorSettings::EnumChatWindowGroupPolicy::GroupAll:
148  if( windows.isEmpty() )
149  windowCreated = true;
150  else
151  {
152  //Here we are finding the window with the most tabs and
153  //putting it there. Need this for the cases where config changes
154  //midstream
155 
156  int viewCount = -1;
157  WindowList::iterator it;
158  for ( it = windows.begin(); it != windows.end(); ++it )
159  {
160  if( (*it)->chatViewCount() > viewCount )
161  {
162  myWindow = (*it);
163  viewCount = (*it)->chatViewCount();
164  }
165  }
166  }
167  break;
168 
169  //Open every chat in a new window
170  case Kopete::BehaviorSettings::EnumChatWindowGroupPolicy::OpenNewWindow:
171  default:
172  windowCreated = true;
173  break;
174  }
175 
176  if ( windowCreated )
177  {
178  myWindow = new KopeteChatWindow( manager->form() );
179 
180  if ( !accountMap.contains( manager->account() ) )
181  accountMap.insert( manager->account(), myWindow );
182 
183  if ( !mcMap.contains( metaContact ) )
184  mcMap.insert( metaContact, myWindow );
185 
186  if ( group && !groupMap.contains( group ) )
187  groupMap.insert( group, myWindow );
188  }
189 
190 // kDebug( 14010 ) << "Open Windows: " << windows.count();
191 
192  return myWindow;
193 }
194 
195 KopeteChatWindow::KopeteChatWindow( Kopete::ChatSession::Form form, QWidget *parent )
196  : KXmlGuiWindow( parent ), initialForm( form )
197 {
198 #ifdef CHRONO
199  QTime chrono;chrono.start();
200 #endif
201  m_activeView = 0L;
202  m_popupView = 0L;
203  backgroundFile = 0L;
204  updateBg = true;
205  m_tabBar = 0L;
206 
207  m_participantsWidget = new QDockWidget(i18n("Participants"), this);
208  m_participantsWidget->setAllowedAreas(Qt::RightDockWidgetArea | Qt::LeftDockWidgetArea);
209  m_participantsWidget->setFeatures(QDockWidget::DockWidgetClosable);
210  m_participantsWidget->setTitleBarWidget(0L);
211  m_participantsWidget->setObjectName("Participants"); //object name is required for automatic position and settings save.
212 
213  ChatSessionMembersListModel *members_model = new ChatSessionMembersListModel(this);
214 
215  connect(this, SIGNAL(chatSessionChanged(Kopete::ChatSession*)), members_model, SLOT(setChatSession(Kopete::ChatSession*)));
216 
217  ChatMembersListView *chatmembers = new ChatMembersListView(m_participantsWidget);
218  chatmembers->setModel(members_model);
219  chatmembers->setWordWrap(true);
220  m_participantsWidget->setWidget(chatmembers);
221  initActions();
222 
223  addDockWidget(Qt::RightDockWidgetArea, m_participantsWidget);
224 
225  KVBox *vBox = new KVBox( this );
226  vBox->setLineWidth( 0 );
227  vBox->setSpacing( 0 );
228  vBox->setFrameStyle( QFrame::NoFrame );
229  // set default window size. This could be removed by fixing the size hints of the contents
230  if ( initialForm == Kopete::ChatSession::Chatroom ) {
231  resize( 650, 400 );
232  } else {
233  m_participantsWidget->hide();
234  resize( 400, 400 );
235  }
236  setCentralWidget( vBox );
237 
238  mainArea = new QFrame( vBox );
239  mainArea->setLineWidth( 0 );
240  mainArea->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
241  mainLayout = new QVBoxLayout( mainArea );
242  mainLayout->setContentsMargins(0, 4, 0, 0);
243 
244  if ( Kopete::BehaviorSettings::self()->chatWindowShowSendButton() )
245  {
246  //Send Button
247  m_button_send = new KPushButton( i18nc("@action:button", "Send"), statusBar() );
248  m_button_send->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
249  m_button_send->setEnabled( false );
250  m_button_send->setFont( statusBar()->font() );
251  m_button_send->setFixedHeight( statusBar()->sizeHint().height() );
252  connect( m_button_send, SIGNAL(clicked()), this, SLOT(slotSendMessage()) );
253  statusBar()->addPermanentWidget( m_button_send, 0 );
254  }
255  else
256  m_button_send = 0L;
257 
258  m_status_text = new KSqueezedTextLabel( i18nc("@info:status","Ready."), statusBar() );
259  m_status_text->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
260  m_status_text->setFont( statusBar()->font() );
261  m_status_text->setFixedHeight( statusBar()->sizeHint().height() );
262  statusBar()->addWidget( m_status_text, 1 );
263 
264  windows.append( this );
265  windowListChanged();
266 
267  m_alwaysShowTabs = KGlobal::config()->group( "ChatWindowSettings" ).
268  readEntry( QLatin1String("AlwaysShowTabs"), false );
269 // kDebug( 14010 ) << "Open Windows: " << windows.count();
270 
271  setupGUI( static_cast<StandardWindowOptions>(ToolBar | Keys | StatusBar | Save | Create) , "kopetechatwindow.rc" );
272 
273  //has to be done after the setupGUI, in order to have the toolbar set up to restore window settings.
274  readOptions();
275 #ifdef CHRONO
276  kDebug()<<"TIME: "<<chrono.elapsed();
277 #endif
278 }
279 
280 KopeteChatWindow::~KopeteChatWindow()
281 {
282  kDebug( 14010 ) ;
283 
284  emit( closing( this ) );
285 
286  for( AccountMap::Iterator it = accountMap.begin(); it != accountMap.end(); )
287  {
288  if( it.value() == this )
289  it=accountMap.erase( it );
290  else
291  ++it;
292  }
293 
294  for( GroupMap::Iterator it = groupMap.begin(); it != groupMap.end(); )
295  {
296  if( it.value() == this )
297  it=groupMap.erase( it );
298  else
299  ++it;
300  }
301 
302  for( MetaContactMap::Iterator it = mcMap.begin(); it != mcMap.end(); )
303  {
304  if( it.value() == this )
305  it=mcMap.erase( it );
306  else
307  ++it;
308  }
309 
310  windows.removeAt( windows.indexOf( this ) );
311  windowListChanged();
312 
313 // kDebug( 14010 ) << "Open Windows: " << windows.count();
314 
315  saveOptions();
316 
317  delete backgroundFile;
318  delete anim;
319  delete animIcon;
320 }
321 
322 void KopeteChatWindow::windowListChanged()
323 {
324  // update all windows' Move Tab to Window action
325  for ( WindowList::iterator it = windows.begin(); it != windows.end(); ++it )
326  (*it)->checkDetachEnable();
327 }
328 
329 void KopeteChatWindow::slotTabContextMenu( QWidget *tab, const QPoint &pos )
330 {
331  m_popupView = static_cast<ChatView*>( tab );
332 
333  KMenu popup;
334  popup.addTitle( KStringHandler::rsqueeze( m_popupView->caption() ) );
335  popup.addAction( actionContactMenu );
336  popup.addSeparator();
337  popup.addAction( actionTabPlacementMenu );
338  popup.addAction( tabDetach );
339  popup.addAction( actionDetachMenu );
340  popup.addAction( tabCloseAllOthers );
341  popup.addAction( tabClose );
342  popup.exec( pos );
343 
344  m_popupView = 0;
345 }
346 
347 ChatView *KopeteChatWindow::activeView()
348 {
349  return m_activeView;
350 }
351 
352 void KopeteChatWindow::updateSendKeySequence()
353 {
354  if ( !sendMessage || !m_activeView )
355  return;
356 
357  m_activeView->editPart()->textEdit()->setSendKeySequenceList( sendMessage->shortcuts() );
358 }
359 
360 void KopeteChatWindow::initActions(void)
361 {
362  KActionCollection *coll = actionCollection();
363 
364  createStandardStatusBarAction();
365 
366  chatSend = new KAction( KIcon("mail-send"), i18n( "&Send Message" ), coll );
367  //Recuperate the qAction for later
368  sendMessage = coll->addAction( "chat_send", chatSend );
369  //Set up change signal in case the user changer the shortcut later
370  connect( sendMessage, SIGNAL(changed()), SLOT(updateSendKeySequence()) );
371 
372  connect( chatSend, SIGNAL(triggered(bool)), SLOT(slotSendMessage()) );
373  //Default to 'Return' and 'Enter' for sending messages
374  //'Return' is the key in the main part of the keyboard
375  //'Enter' is on the Numpad
376  KShortcut chatSendShortcut( QKeySequence((int)Qt::Key_Return), QKeySequence((int)Qt::Key_Enter) );
377  chatSend->setShortcut( chatSendShortcut );
378  chatSend->setEnabled( false );
379 
380  chatSendFile = new KAction( KIcon("mail-attachment"), i18n( "Send File..." ), coll );
381  coll->addAction( "chat_send_file", chatSendFile );
382  connect( chatSendFile, SIGNAL(triggered(bool)), SLOT(slotSendFile()) );
383  chatSendFile->setEnabled( false );
384 
385  KStandardAction::save ( this, SLOT(slotChatSave()), coll );
386  KStandardAction::print ( this, SLOT(slotChatPrint()), coll );
387  KAction* quitAction = KStandardAction::quit ( this, SLOT(close()), coll );
388  quitAction->setText( i18n("Close All Chats") );
389 
390  tabClose = KStandardAction::close ( this, SLOT(slotChatClosed()), coll );
391  coll->addAction( "tabs_close", tabClose );
392 
393  tabActive=new KAction( i18n( "&Activate Next Active Tab" ), coll );
394  coll->addAction( "tabs_active", tabActive );
395 // tabActive->setShortcut( KStandardShortcut::tabNext() );
396  tabActive->setEnabled( false );
397  connect( tabActive, SIGNAL(triggered(bool)), this, SLOT(slotNextActiveTab()) );
398 
399  tabRight=new KAction( i18n( "&Activate Next Tab" ), coll );
400  coll->addAction( "tabs_right", tabRight );
401  tabRight->setShortcut( KStandardShortcut::tabNext() );
402  tabRight->setEnabled( false );
403  connect( tabRight, SIGNAL(triggered(bool)), this, SLOT(slotNextTab()) );
404 
405  tabLeft=new KAction( i18n( "&Activate Previous Tab" ), coll );
406  coll->addAction( "tabs_left", tabLeft );
407  tabLeft->setShortcut( KStandardShortcut::tabPrev() );
408  tabLeft->setEnabled( false );
409  connect( tabLeft, SIGNAL(triggered(bool)), this, SLOT(slotPreviousTab()) );
410 
411  // This action exists mostly so that the shortcut is configurable.
412  // The actual "slot" is the eventFilter.
413  nickComplete = new KAction( i18n( "Nic&k Completion" ), coll );
414  coll->addAction( "nick_complete", nickComplete );
415  nickComplete->setShortcut( QKeySequence( Qt::Key_Tab ) );
416 
417  tabDetach = new KAction( KIcon("tab-detach"), i18n( "&Detach Chat" ), coll );
418  coll->addAction( "tabs_detach", tabDetach );
419  tabDetach->setEnabled( false );
420  connect( tabDetach, SIGNAL(triggered(bool)), this, SLOT(slotDetachChat()));
421 
422  tabCloseAllOthers = new KAction( KIcon("tab-close"), i18n( "Close &All But This Tab" ), coll );
423  coll->addAction( "tabs_close_others", tabCloseAllOthers );
424  tabCloseAllOthers->setEnabled( true );
425  connect( tabCloseAllOthers, SIGNAL(triggered(bool)), this, SLOT(slotCloseAllOtherTabs()));
426 
427  actionDetachMenu = new KActionMenu( KIcon("tab-detach"), i18n( "&Move Tab to Window" ), coll );
428  coll->addAction( "tabs_detachmove", actionDetachMenu );
429  actionDetachMenu->setDelayed( false );
430 
431  connect ( actionDetachMenu->menu(), SIGNAL(aboutToShow()), this, SLOT(slotPrepareDetachMenu()) );
432  connect ( actionDetachMenu->menu(), SIGNAL(triggered(QAction*)), this, SLOT(slotDetachChat(QAction*)) );
433 
434  actionTabPlacementMenu = new KActionMenu( i18n( "&Tab Placement" ), coll );
435  coll->addAction( "tabs_placement", actionTabPlacementMenu );
436  connect ( actionTabPlacementMenu->menu(), SIGNAL(aboutToShow()), this, SLOT(slotPreparePlacementMenu()) );
437  connect ( actionTabPlacementMenu->menu(), SIGNAL(triggered(QAction*)), this, SLOT(slotPlaceTabs(QAction*)) );
438 
439  tabDetach->setShortcut( QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_B) );
440 
441  KStandardAction::cut( this, SLOT(slotCut()), coll);
442  KStandardAction::copy( this, SLOT(slotCopy()), coll);
443  KStandardAction::paste( this, SLOT(slotPaste()), coll);
444 
445  KAction* action;
446 
447  historyUp = new KAction( i18n( "Previous History" ), coll );
448  coll->addAction( "history_up", historyUp );
449  historyUp->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_Up) );
450  connect( historyUp, SIGNAL(triggered(bool)), this, SLOT(slotHistoryUp()) );
451 
452  historyDown = new KAction( i18n( "Next History" ), coll );
453  coll->addAction( "history_down", historyDown );
454  historyDown->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_Down) );
455  connect( historyDown, SIGNAL(triggered(bool)), this, SLOT(slotHistoryDown()) );
456 
457  action = KStandardAction::prior( this, SLOT(slotPageUp()), coll );
458  coll->addAction( "scroll_up", action );
459  action = KStandardAction::next( this, SLOT(slotPageDown()), coll );
460  coll->addAction( "scroll_down", action );
461 
462  KStandardAction::showMenubar( menuBar(), SLOT(setVisible(bool)), coll );
463 
464  toggleAutoSpellCheck = new KToggleAction( i18n( "Automatic Spell Checking" ), coll );
465  coll->addAction( "enable_auto_spell_check", toggleAutoSpellCheck );
466  toggleAutoSpellCheck->setChecked( true );
467  connect( toggleAutoSpellCheck, SIGNAL(triggered(bool)), this, SLOT(toggleAutoSpellChecking()) );
468 
469  QAction *toggleParticipantsAction = m_participantsWidget->toggleViewAction( );
470  toggleParticipantsAction->setText( i18n( "Show Participants" ) );
471  toggleParticipantsAction->setIconText(i18n( "Participants" ));
472  toggleParticipantsAction->setIcon(KIcon( "system-users" ) );
473  coll->addAction ( "show_participants_widget", toggleParticipantsAction );
474 
475  actionSmileyMenu = new KopeteEmoticonAction( coll );
476  coll->addAction( "format_smiley", actionSmileyMenu );
477  actionSmileyMenu->setDelayed( false );
478  connect(actionSmileyMenu, SIGNAL(activated(QString)), this, SLOT(slotSmileyActivated(QString)));
479 
480  actionContactMenu = new KActionMenu(i18n("Co&ntacts"), coll );
481  coll->addAction( "contacts_menu", actionContactMenu );
482  actionContactMenu->setDelayed( false );
483  connect ( actionContactMenu->menu(), SIGNAL(aboutToShow()), this, SLOT(slotPrepareContactMenu()) );
484 
485  KopeteStdAction::preferences( coll , "settings_prefs" );
486 
487  KToolBarSpacerAction * spacer = new KToolBarSpacerAction( coll );
488  coll->addAction( "spacer", spacer );
489 
490  //The Sending movie
491  normalIcon = QPixmap( BarIcon( QLatin1String( "kopete" ) ) );
492 
493  // we can't set the tool bar as parent, if we do, it will be deleted when we configure toolbars
494  anim = new QLabel( QString::null, 0L ); //krazy:exclude=nullstrassign for old broken gcc
495  anim->setObjectName( QLatin1String("kde toolbar widget") );
496  anim->setMargin(5);
497  anim->setPixmap( normalIcon );
498 
499  animIcon = KIconLoader::global()->loadMovie( QLatin1String( "newmessage" ), KIconLoader::Toolbar);
500  if ( animIcon )
501  animIcon->setPaused(true);
502 
503  KAction *animAction = new KAction( i18n("Toolbar Animation"), coll );
504  coll->addAction( "toolbar_animation", animAction );
505  animAction->setDefaultWidget( anim );
506 
507  //toolBar()->insertWidget( 99, anim->width(), anim );
508  //toolBar()->alignItemRight( 99 );
509 }
510 
511 /*
512 const QString KopeteChatWindow::fileContents( const QString &path ) const
513 {
514  QString contents;
515  QFile file( path );
516  if ( file.open( QIODevice::ReadOnly ) )
517  {
518  QTextStream stream( &file );
519  contents = stream.readAll();
520  file.close();
521  }
522 
523  return contents;
524 }
525 */
526 void KopeteChatWindow::slotStopAnimation( ChatView* view )
527 {
528  if( view == m_activeView )
529  {
530  anim->setPixmap( normalIcon );
531  if( animIcon && animIcon->state() == QMovie::Running )
532  animIcon->setPaused( true );
533  }
534 }
535 
536 void KopeteChatWindow::slotUpdateSendEnabled()
537 {
538  if ( !m_activeView ) return;
539 
540  bool enabled = m_activeView->canSend();
541  chatSend->setEnabled( enabled );
542  if(m_button_send)
543  m_button_send->setEnabled( enabled );
544 }
545 
546 void KopeteChatWindow::updateChatSendFileAction()
547 {
548  if ( !m_activeView )
549  return;
550 
551  chatSendFile->setEnabled( m_activeView->canSendFile() );
552 }
553 
554 void KopeteChatWindow::toggleAutoSpellChecking()
555 {
556  if ( !m_activeView )
557  return;
558 
559  bool currentSetting = m_activeView->editPart()->checkSpellingEnabled();
560  m_activeView->editPart()->setCheckSpellingEnabled( !currentSetting );
561  updateSpellCheckAction();
562 }
563 
564 void KopeteChatWindow::updateSpellCheckAction()
565 {
566  if ( !m_activeView )
567  return;
568 
569  bool currentSetting = m_activeView->editPart()->checkSpellingEnabled();
570  toggleAutoSpellCheck->setChecked( currentSetting );
571 }
572 
573 void KopeteChatWindow::enableSpellCheckAction(bool enable)
574 {
575  toggleAutoSpellCheck->setChecked( enable );
576 }
577 
578 void KopeteChatWindow::updateActions()
579 {
580  updateSpellCheckAction();
581  updateChatSendFileAction();
582 }
583 
584 void KopeteChatWindow::slotHistoryUp()
585 {
586  if( m_activeView )
587  m_activeView->editPart()->historyUp();
588 }
589 
590 void KopeteChatWindow::slotHistoryDown()
591 {
592  if( m_activeView )
593  m_activeView->editPart()->historyDown();
594 }
595 
596 void KopeteChatWindow::slotPageUp()
597 {
598  if( m_activeView )
599  m_activeView->messagePart()->pageUp();
600 }
601 
602 void KopeteChatWindow::slotPageDown()
603 {
604  if( m_activeView )
605  m_activeView->messagePart()->pageDown();
606 }
607 
608 void KopeteChatWindow::slotCut()
609 {
610  m_activeView->cut();
611 }
612 
613 void KopeteChatWindow::slotCopy()
614 {
615  m_activeView->copy();
616 }
617 
618 void KopeteChatWindow::slotPaste()
619 {
620  m_activeView->paste();
621 }
622 
623 void KopeteChatWindow::slotResetFontAndColor()
624 {
625  m_activeView->resetFontAndColor();
626 }
627 
628 void KopeteChatWindow::setStatus(const QString &text)
629 {
630  m_status_text->setText(text);
631 }
632 
633 void KopeteChatWindow::testCanDecode(const QDragMoveEvent *event, bool &accept)
634 {
635  if ( m_tabBar && qobject_cast<KTabBar*>(m_tabBar->childAt( event->pos() )) && chatViewList[static_cast<KTabBar*>(m_tabBar->childAt( event->pos()))->selectTab( event->pos() )]->isDragEventAccepted( event )) {
636  accept = true;
637  } else {
638  accept = false;
639  }
640 }
641 
642 void KopeteChatWindow::receivedDropEvent( QWidget *w, QDropEvent *e )
643 {
644  m_tabBar->setCurrentWidget( w );
645  activeView()->dropEvent( e );
646 }
647 
648 void KopeteChatWindow::createTabBar()
649 {
650  if( !m_tabBar )
651  {
652  KConfigGroup cg( KGlobal::config(), QLatin1String("ChatWindowSettings") );
653 
654  m_tabBar = new KTabWidget( mainArea );
655  m_tabBar->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
656  m_tabBar->setTabsClosable(cg.readEntry( QLatin1String("HoverClose"), true ));
657  m_tabBar->setMovable(true);
658  m_tabBar->setAutomaticResizeTabs(true);
659  connect( m_tabBar, SIGNAL(closeRequest(QWidget*)), this, SLOT(slotCloseChat(QWidget*)) );
660 
661  m_UpdateChatLabel = cg.readEntry( QLatin1String("ShowContactName"), true );
662 
663  QToolButton* m_rightWidget = new QToolButton( m_tabBar );
664  connect( m_rightWidget, SIGNAL(clicked()), this, SLOT(slotChatClosed()) );
665  m_rightWidget->setIcon( SmallIcon( "tab-close" ) );
666  m_rightWidget->adjustSize();
667  m_rightWidget->setToolTip( i18nc("@info:tooltip","Close the current tab") );
668  m_tabBar->setCornerWidget( m_rightWidget, Qt::TopRightCorner );
669 
670  mainLayout->addWidget( m_tabBar );
671  m_tabBar->show();
672 
673  for( ChatViewList::iterator it = chatViewList.begin(); it != chatViewList.end(); ++it )
674  addTab( *it );
675 
676  connect ( m_tabBar, SIGNAL(testCanDecode(const QDragMoveEvent*,bool&)), this, SLOT(testCanDecode(const QDragMoveEvent*,bool&)) );
677  connect ( m_tabBar, SIGNAL(receivedDropEvent(QWidget*,QDropEvent*)), this, SLOT(receivedDropEvent(QWidget*,QDropEvent*)) );
678  connect ( m_tabBar, SIGNAL(currentChanged(QWidget*)), this, SLOT(setActiveView(QWidget*)) );
679  connect ( m_tabBar, SIGNAL(contextMenu(QWidget*,QPoint)), this, SLOT(slotTabContextMenu(QWidget*,QPoint)) );
680 
681  if( m_activeView )
682  m_tabBar->setCurrentWidget( m_activeView );
683  else
684  setActiveView( chatViewList.first() );
685 
686  int tabPosition = cg.readEntry( QLatin1String("Tab Placement") , 0 );
687 
688  QAction action(this);
689  action.setData(tabPosition);
690  slotPlaceTabs( &action );
691  }
692 }
693 
694 void KopeteChatWindow::slotCloseChat( QWidget *chatView )
695 {
696  static_cast<ChatView*>( chatView )->closeView();
697  //FIXME: check if we need to remove from the chatViewList
698 }
699 
700 void KopeteChatWindow::addTab( ChatView *view )
701 {
702  QList<Kopete::Contact*> chatMembers=view->msgManager()->members();
703  Kopete::Contact *c=0L;
704  foreach( Kopete::Contact *contact , chatMembers )
705  {
706  if(!c || c->onlineStatus() < contact->onlineStatus())
707  c=contact;
708  }
709  QIcon pluginIcon = c ? view->msgManager()->contactOnlineStatus( c ).iconFor( c) :
710  KIcon( view->msgManager()->protocol()->pluginIcon() );
711 
712  view->setParent( m_tabBar );
713  view->setWindowFlags( 0 );
714  view->move( QPoint() );
715  //view->show();
716 
717  m_tabBar->addTab( view, pluginIcon, "");
718  view->setVisible(view == m_activeView);
719  connect( view, SIGNAL(updateStatusIcon(ChatView*)), this, SLOT(slotUpdateCaptionIcons(ChatView*)) );
720 
721  if (m_UpdateChatLabel) {
722  connect( view, SIGNAL(captionChanged(bool)), this, SLOT(updateChatLabel()) );
723  view->setCaption( view->caption(), false );
724  }
725 
726 }
727 
728 void KopeteChatWindow::setPrimaryChatView( ChatView *view )
729 {
730  //TODO figure out what else we have to save here besides the font
731  //reparent clears a lot of stuff out
732  view->setParent( mainArea );
733  view->setWindowFlags( 0 );
734  view->move( QPoint() );
735  view->show();
736 
737  mainLayout->addWidget( view );
738  setActiveView( view );
739 }
740 
741 void KopeteChatWindow::deleteTabBar()
742 {
743  if( m_tabBar )
744  {
745  disconnect ( m_tabBar, SIGNAL(currentChanged(QWidget*)), this, SLOT(setActiveView(QWidget*)) );
746  disconnect ( m_tabBar, SIGNAL(contextMenu(QWidget*,QPoint)), this, SLOT(slotTabContextMenu(QWidget*,QPoint)) );
747 
748  if( !chatViewList.isEmpty() )
749  setPrimaryChatView( chatViewList.first() );
750 
751  m_tabBar->deleteLater();
752  m_tabBar = 0L;
753  }
754 }
755 
756 void KopeteChatWindow::attachChatView( ChatView* newView )
757 {
758  chatViewList.append( newView );
759 
760  if ( !m_alwaysShowTabs && chatViewList.count() == 1 )
761  setPrimaryChatView( newView );
762  else
763  {
764  if ( !m_tabBar )
765  createTabBar();
766  else
767  addTab( newView );
768  newView->setActive( false );
769  }
770 
771  newView->setMainWindow( this );
772  newView->editWidget()->installEventFilter( this );
773 
774  KCursor::setAutoHideCursor( newView->editWidget(), true, true );
775  connect( newView, SIGNAL(captionChanged(bool)), this, SLOT(slotSetCaption(bool)) );
776  connect( newView, SIGNAL(messageSuccess(ChatView*)), this, SLOT(slotStopAnimation(ChatView*)) );
777  connect( newView, SIGNAL(updateStatusIcon(ChatView*)), this, SLOT(slotUpdateCaptionIcons(ChatView*)) );
778 
779  if (m_UpdateChatLabel) {
780  connect( newView, SIGNAL(updateChatState(ChatView*,int)), this, SLOT(updateChatState(ChatView*,int)) );
781  }
782 
783  updateActions();
784  checkDetachEnable();
785  connect( newView, SIGNAL(autoSpellCheckEnabled(ChatView*,bool)),
786  this, SLOT(slotAutoSpellCheckEnabled(ChatView*,bool)) );
787 }
788 
789 void KopeteChatWindow::checkDetachEnable()
790 {
791  bool haveTabs = (chatViewList.count() > 1);
792  tabCloseAllOthers->setEnabled( haveTabs );
793  tabDetach->setEnabled( haveTabs );
794  tabLeft->setEnabled( haveTabs );
795  tabRight->setEnabled( haveTabs );
796  tabActive->setEnabled( haveTabs );
797  actionTabPlacementMenu->setEnabled( m_tabBar != 0 );
798 
799  bool otherWindows = (windows.count() > 1);
800  actionDetachMenu->setEnabled( otherWindows );
801 }
802 
803 void KopeteChatWindow::detachChatView( ChatView *view )
804 {
805  chatViewList.removeAt( chatViewList.indexOf( view ) );
806 
807  disconnect( view, SIGNAL(captionChanged(bool)), this, SLOT(slotSetCaption(bool)) );
808  disconnect( view, SIGNAL(updateStatusIcon(ChatView*)), this, SLOT(slotUpdateCaptionIcons(ChatView*)) );
809  disconnect( view, SIGNAL(updateChatState(ChatView*,int)), this, SLOT(updateChatState(ChatView*,int)) );
810  view->editWidget()->removeEventFilter( this );
811 
812  if( m_tabBar )
813  {
814  int curPage = m_tabBar->currentIndex();
815  QWidget *page = m_tabBar->currentWidget();
816 
817  // if the current view is to be detached, switch to a different one
818  if( page == view )
819  {
820  if( curPage > 0 )
821  m_tabBar->setCurrentIndex( curPage - 1 );
822  else
823  m_tabBar->setCurrentIndex( curPage + 1 );
824  }
825 
826  m_tabBar->removePage( view );
827 
828  if( m_tabBar->currentWidget() )
829  setActiveView( static_cast<ChatView*>(m_tabBar->currentWidget()) );
830  }
831 
832  if( m_activeView == view )
833  m_activeView = 0;
834 
835  if( chatViewList.isEmpty() )
836  close();
837  else if( !m_alwaysShowTabs && chatViewList.count() == 1)
838  deleteTabBar();
839 
840  checkDetachEnable();
841 }
842 
843 void KopeteChatWindow::slotDetachChat( QAction *action )
844 {
845  KopeteChatWindow *newWindow = 0L;
846  ChatView *detachedView;
847 
848  if( m_popupView )
849  detachedView = m_popupView;
850  else
851  detachedView = m_activeView;
852 
853  if( !detachedView )
854  return;
855 
856  //if we don't do this, we might crash
857 // createGUI(0L);
858  guiFactory()->removeClient(detachedView->msgManager());
859 
860  if( !action )
861  {
862  newWindow = new KopeteChatWindow( detachedView->msgManager()->form() );
863  newWindow->setObjectName( QLatin1String("KopeteChatWindow") );
864  }
865  else
866  newWindow = windows.at( action->data().toInt() );
867 
868  newWindow->show();
869  newWindow->raise();
870 
871  detachChatView( detachedView );
872  newWindow->attachChatView( detachedView );
873 }
874 
875 void KopeteChatWindow::slotCloseAllOtherTabs()
876 {
877  ChatView *detachedView;
878 
879  if( m_popupView )
880  detachedView = m_popupView;
881  else
882  detachedView = m_activeView;
883 
884  foreach(ChatView *view, chatViewList) {
885  if (view != detachedView)
886  view->closeView();
887  }
888 }
889 
890 void KopeteChatWindow::slotPreviousTab()
891 {
892  int curPage = m_tabBar->currentIndex();
893  if( curPage > 0 )
894  m_tabBar->setCurrentIndex( curPage - 1 );
895  else
896  m_tabBar->setCurrentIndex( m_tabBar->count() - 1 );
897 }
898 
899 void KopeteChatWindow::slotNextTab()
900 {
901  int curPage = m_tabBar->currentIndex();
902  if( curPage == ( m_tabBar->count() - 1 ) )
903  m_tabBar->setCurrentIndex( 0 );
904  else
905  m_tabBar->setCurrentIndex( curPage + 1 );
906 }
907 
908 void KopeteChatWindow::slotNextActiveTab()
909 {
910  int curPage = m_tabBar->currentIndex();
911  for(int i=(curPage+1) % m_tabBar->count(); i!=curPage; i = (i+1) % m_tabBar->count())
912  {
913  ChatView *v = static_cast<ChatView*>(m_tabBar->widget(i)); //We assume we only have ChatView's
914  if(v->tabState()==ChatView::Highlighted || v->tabState()==ChatView::Message)
915  {
916  m_tabBar->setCurrentIndex( i );
917  break;
918  }
919  }
920 }
921 
922 void KopeteChatWindow::slotSetCaption( bool active )
923 {
924  if( active && m_activeView )
925  {
926  setCaption( m_activeView->caption(), false );
927  }
928 }
929 
930 void KopeteChatWindow::updateBackground( const QPixmap &pm )
931 {
932  if( updateBg )
933  {
934  updateBg = false;
935  delete backgroundFile;
936 
937  backgroundFile = new KTemporaryFile();
938  backgroundFile->setSuffix(".bmp");
939  backgroundFile->open();
940  pm.save( backgroundFile, "BMP" );
941  QTimer::singleShot( 100, this, SLOT(slotEnableUpdateBg()) );
942  }
943 }
944 
945 void KopeteChatWindow::setActiveView( QWidget *widget )
946 {
947  ChatView *view = static_cast<ChatView*>(widget);
948 
949  if( m_activeView == view )
950  return;
951 
952  if(m_activeView)
953  {
954  disconnect( m_activeView->editWidget(), SIGNAL(checkSpellingChanged(bool)), this, SLOT(enableSpellCheckAction(bool)) );
955  disconnect( m_activeView, SIGNAL(canSendChanged(bool)), this, SLOT(slotUpdateSendEnabled()) );
956  disconnect( m_activeView, SIGNAL(canAcceptFilesChanged()), this, SLOT(updateChatSendFileAction()) );
957  guiFactory()->removeClient(m_activeView->msgManager());
958  m_activeView->saveChatSettings();
959  }
960 
961  if ( view != 0 )
962  guiFactory()->addClient(view->msgManager());
963 // createGUI( view->editPart() );
964 
965  if( m_activeView )
966  m_activeView->setActive( false );
967 
968  m_activeView = view;
969 
970  if ( view == 0 )
971  return;
972 
973  if( chatViewList.indexOf( view ) == -1)
974  attachChatView( view );
975 
976  connect( m_activeView->editWidget(), SIGNAL(checkSpellingChanged(bool)), this, SLOT(enableSpellCheckAction(bool)) );
977  connect( m_activeView, SIGNAL(canSendChanged(bool)), this, SLOT(slotUpdateSendEnabled()) );
978  connect( m_activeView, SIGNAL(canAcceptFilesChanged()), this, SLOT(updateChatSendFileAction()) );
979 
980  //Tell it it is active
981  m_activeView->setActive( true );
982 
983  //Update icons to match
984  slotUpdateCaptionIcons( m_activeView );
985 
986  if ( m_activeView->sendInProgress() && animIcon )
987  {
988  anim->setMovie( animIcon );
989  animIcon->setPaused(false);
990  }
991  else
992  {
993  anim->setPixmap( normalIcon );
994  if( animIcon )
995  animIcon->setPaused(true);
996  }
997 
998  if ( m_alwaysShowTabs || chatViewList.count() > 1 )
999  {
1000  if( !m_tabBar )
1001  createTabBar();
1002 
1003  m_tabBar->setCurrentWidget( m_activeView );
1004  }
1005 
1006  setCaption( m_activeView->caption() );
1007  setStatus( m_activeView->statusText() );
1008  m_activeView->setFocus();
1009  updateActions();
1010  slotUpdateSendEnabled();
1011  m_activeView->loadChatSettings();
1012  updateSendKeySequence();
1013 
1014  emit chatSessionChanged(m_activeView->msgManager());
1015 }
1016 
1017 void KopeteChatWindow::slotUpdateCaptionIcons( ChatView *view )
1018 {
1019  if ( !view )
1020  return; //(pas de charité)
1021 
1022  QList<Kopete::Contact*> chatMembers=view->msgManager()->members();
1023  Kopete::Contact *c=0L;
1024  foreach ( Kopete::Contact *contact , chatMembers )
1025  {
1026  if(!c || c->onlineStatus() < contact->onlineStatus())
1027  c=contact;
1028  }
1029 
1030  if ( view == m_activeView )
1031  {
1032  setWindowIcon( c ? view->msgManager()->contactOnlineStatus( c ).iconFor( c ) :
1033  KIcon(view->msgManager()->protocol()->pluginIcon()));
1034  }
1035 
1036  if ( m_tabBar )
1037  m_tabBar->setTabIcon(m_tabBar->indexOf( view ), c ? view->msgManager()->contactOnlineStatus( c ).iconFor( c ) :
1038  KIcon( view->msgManager()->protocol()->pluginIcon() ) );
1039 }
1040 
1041 void KopeteChatWindow::slotChatClosed()
1042 {
1043  if( m_popupView )
1044  m_popupView->closeView();
1045  else
1046  m_activeView->closeView();
1047 }
1048 
1049 void KopeteChatWindow::slotPrepareDetachMenu(void)
1050 {
1051  QMenu *detachMenu = actionDetachMenu->menu();
1052  detachMenu->clear();
1053 
1054  QAction *action;
1055  for ( int id = 0; id < windows.count(); id++ )
1056  {
1057  KopeteChatWindow *win = windows.at( id );
1058  if( win != this )
1059  {
1060  action = detachMenu->addAction( win->windowIcon(), win->windowTitle() );
1061  action->setData( id );
1062  }
1063  }
1064 }
1065 
1066 void KopeteChatWindow::slotSendMessage()
1067 {
1068  if ( m_activeView && m_activeView->canSend() )
1069  {
1070  if( animIcon )
1071  {
1072  anim->setMovie( animIcon );
1073  animIcon->setPaused(false);
1074  }
1075  m_activeView->sendMessage();
1076  }
1077 }
1078 
1079 void KopeteChatWindow::slotSendFile()
1080 {
1081  if ( m_activeView )
1082  m_activeView->sendFile();
1083 }
1084 
1085 void KopeteChatWindow::slotPrepareContactMenu(void)
1086 {
1087  KMenu *contactsMenu = actionContactMenu->menu();
1088  contactsMenu->clear();
1089 
1090  Kopete::ContactPtrList m_them;
1091 
1092  if( m_popupView )
1093  m_them = m_popupView->msgManager()->members();
1094  else
1095  m_them = m_activeView->msgManager()->members();
1096 
1097  //TODO: don't display a menu with one contact in it, display that
1098  // contact's menu instead. Will require changing text and icon of
1099  // 'Contacts' action, or something cleverer.
1100  uint contactCount = 0;
1101 
1102  foreach(Kopete::Contact *contact, m_them)
1103  {
1104  KMenu *p = contact->popupMenu();
1105  connect ( actionContactMenu->menu(), SIGNAL(aboutToHide()),
1106  p, SLOT(deleteLater()) );
1107 
1108  p->setIcon( contact->onlineStatus().iconFor( contact ) );
1109  if( contact->metaContact() )
1110  p->setTitle( contact->metaContact()->displayName() );
1111  else
1112  p->setTitle( contact->contactId() );
1113 
1114  contactsMenu->addMenu( p );
1115 
1116  //FIXME: This number should be a config option
1117  if( ++contactCount == 15 && contact != m_them.last() )
1118  {
1119  KActionMenu *moreMenu = new KActionMenu( KIcon("folder-open"), i18n("More..."), this);
1120  connect ( actionContactMenu->menu(), SIGNAL(aboutToHide()),
1121  moreMenu, SLOT(deleteLater()) );
1122  contactsMenu->addAction( moreMenu );
1123  contactsMenu = moreMenu->menu();
1124  contactCount = 0;
1125  }
1126  }
1127 }
1128 
1129 void KopeteChatWindow::slotPreparePlacementMenu()
1130 {
1131  QMenu *placementMenu = actionTabPlacementMenu->menu();
1132  placementMenu->clear();
1133 
1134  QAction *action;
1135  action = placementMenu->addAction( i18n("Top") );
1136  action->setData( 0 );
1137 
1138  action = placementMenu->addAction( i18n("Bottom") );
1139  action->setData( 1 );
1140 
1141  action = placementMenu->addAction( i18n("Left") );
1142  action->setData( 2 );
1143 
1144  action = placementMenu->addAction( i18n("Right") );
1145  action->setData( 3 );
1146 }
1147 
1148 void KopeteChatWindow::slotPlaceTabs( QAction *action )
1149 {
1150  int placement = action->data().toInt();
1151 
1152  if( m_tabBar )
1153  {
1154  switch( placement )
1155  {
1156  case 1 : m_tabBar->setTabPosition( QTabWidget::South ); break;
1157  case 2 : m_tabBar->setTabPosition( QTabWidget::West ); break;
1158  case 3 : m_tabBar->setTabPosition( QTabWidget::East ); break;
1159  default: m_tabBar->setTabPosition( QTabWidget::North );
1160  }
1161  saveOptions();
1162  }
1163 }
1164 
1165 void KopeteChatWindow::readOptions()
1166 {
1167  // load and apply config file settings affecting the appearance of the UI
1168 // kDebug(14010) ;
1169  applyMainWindowSettings( KGlobal::config()->group( ( initialForm == Kopete::ChatSession::Chatroom ? QLatin1String( "KopeteChatWindowGroupMode" ) : QLatin1String( "KopeteChatWindowIndividualMode" ) ) ) );
1170  //config->setGroup( QLatin1String("ChatWindowSettings") );
1171 }
1172 
1173 void KopeteChatWindow::saveOptions()
1174 {
1175 // kDebug(14010) ;
1176 
1177  KConfigGroup kopeteChatWindowMainWinSettings( KGlobal::config(), ( initialForm == Kopete::ChatSession::Chatroom ? QLatin1String( "KopeteChatWindowGroupMode" ) : QLatin1String( "KopeteChatWindowIndividualMode" ) ) );
1178 
1179  // saves menubar,toolbar and statusbar setting
1180  saveMainWindowSettings( kopeteChatWindowMainWinSettings );
1181  if ( m_tabBar ) {
1182  KConfigGroup chatWindowSettings( KGlobal::config(), QLatin1String("ChatWindowSettings") );
1183  chatWindowSettings.writeEntry ( QLatin1String("Tab Placement"), (int)m_tabBar->tabPosition() );
1184  chatWindowSettings.sync();
1185  }
1186  kopeteChatWindowMainWinSettings.sync();
1187 }
1188 
1189 void KopeteChatWindow::slotChatSave()
1190 {
1191 // kDebug(14010) << "KopeteChatWindow::slotChatSave()";
1192  if( isActiveWindow() && m_activeView )
1193  m_activeView->messagePart()->save();
1194 }
1195 
1196 void KopeteChatWindow::changeEvent( QEvent *e )
1197 {
1198  if( e->type() == QEvent::ActivationChange && isActiveWindow() && m_activeView )
1199  m_activeView->setActive( true );
1200 }
1201 
1202 void KopeteChatWindow::slotChatPrint()
1203 {
1204  m_activeView->messagePart()->print();
1205 }
1206 
1207 
1208 void KopeteChatWindow::slotSmileyActivated(const QString &sm)
1209 {
1210  if ( !sm.isNull() )
1211  m_activeView->addText( ' ' + sm + ' ' );
1212  //we are adding space around the emoticon becasue our parser only display emoticons not in a word.
1213 }
1214 
1215 void KopeteChatWindow::slotAutoSpellCheckEnabled( ChatView* view, bool isEnabled )
1216 {
1217  if ( view != m_activeView )
1218  return;
1219 
1220  toggleAutoSpellCheck->setChecked( isEnabled );
1221  m_activeView->editPart()->setCheckSpellingEnabled( isEnabled );
1222 }
1223 
1224 bool KopeteChatWindow::queryClose()
1225 {
1226 #ifdef CHRONO
1227  QTime chrono;chrono.start();
1228 #endif
1229  bool canClose = true;
1230 
1231 // kDebug( 14010 ) << " Windows left open:";
1232 // for( QPtrListIterator<ChatView> it( chatViewList ); it; ++it)
1233 // kDebug( 14010 ) << " " << *it << " (" << (*it)->caption() << ")";
1234  setUpdatesEnabled(false);//hide the crazyness from users
1235  while (!chatViewList.isEmpty())
1236  {
1237 
1238  ChatView *view = chatViewList.takeFirst();
1239 
1240  // FIXME: This should only check if it *can* close
1241  // and not start closing if the close can be aborted halfway, it would
1242  // leave us with half the chats open and half of them closed. - Martijn
1243 
1244  // if the view is closed, it is removed from chatViewList for us
1245  if ( !view->closeView() )
1246  {
1247  kDebug() << "Closing view failed!";
1248  canClose = false;
1249  }
1250  }
1251  setUpdatesEnabled(true);
1252 #ifdef CHRONO
1253  kDebug()<<"TIME: "<<chrono.elapsed();
1254 #endif
1255  return canClose;
1256 }
1257 
1258 bool KopeteChatWindow::queryExit()
1259 {
1260  KopeteApplication *app = static_cast<KopeteApplication *>( kapp );
1261  if ( app->sessionSaving()
1262  || app->isShuttingDown() /* only set if KopeteApplication::quitKopete() or
1263  KopeteApplication::commitData() called */
1264  || !Kopete::BehaviorSettings::self()->showSystemTray() /* also close if our tray icon is hidden! */
1265  || isHidden() )
1266  {
1267  Kopete::PluginManager::self()->shutdown();
1268  return true;
1269  }
1270  else
1271  return false;
1272 }
1273 
1274 void KopeteChatWindow::closeEvent( QCloseEvent * e )
1275 {
1276  // if there's a system tray applet and we are not shutting down then just do what needs to be done if a
1277  // window is closed.
1278  KopeteApplication *app = static_cast<KopeteApplication *>( kapp );
1279  if ( Kopete::BehaviorSettings::self()->showSystemTray() && !app->isShuttingDown() && !app->sessionSaving() ) {
1280 // hide();
1281  // BEGIN of code borrowed from KMainWindow::closeEvent
1282  // Save settings if auto-save is enabled, and settings have changed
1283  if ( settingsDirty() && autoSaveSettings() )
1284  saveAutoSaveSettings();
1285 
1286  if ( queryClose() ) {
1287  e->accept();
1288  }
1289  else {
1290  e->ignore();
1291  }
1292  // END of code borrowed from KMainWindow::closeEvent
1293  }
1294  else
1295  KXmlGuiWindow::closeEvent( e );
1296 }
1297 
1298 
1299 void KopeteChatWindow::updateChatState( ChatView* cv, int newState )
1300 {
1301  Q_UNUSED(cv);
1302 
1303  if ( m_tabBar )
1304  {
1305  KColorScheme scheme(QPalette::Active, KColorScheme::Window);
1306  switch( newState )
1307  {
1308  case ChatView::Highlighted:
1309  m_tabBar->setTabTextColor( m_tabBar->indexOf(cv), scheme.foreground(KColorScheme::LinkText).color());
1310  break;
1311  case ChatView::Message:
1312  m_tabBar->setTabTextColor( m_tabBar->indexOf(cv), scheme.foreground(KColorScheme::ActiveText).color());
1313  break;
1314  case ChatView::Changed:
1315  m_tabBar->setTabTextColor( m_tabBar->indexOf(cv), scheme.foreground(KColorScheme::NeutralText).color());
1316  break;
1317  case ChatView::Typing:
1318  m_tabBar->setTabTextColor( m_tabBar->indexOf(cv), scheme.foreground(KColorScheme::PositiveText).color());
1319  break;
1320  case ChatView::Normal:
1321  default:
1322  m_tabBar->setTabTextColor( m_tabBar->indexOf(cv), scheme.foreground(KColorScheme::NormalText).color() );
1323  break;
1324  }
1325  }
1326 }
1327 
1328 void KopeteChatWindow::updateChatTooltip( ChatView* cv )
1329 {
1330  if ( m_tabBar )
1331  m_tabBar->setTabToolTip( m_tabBar->indexOf( cv ), QString::fromLatin1("<qt>%1</qt>").arg( cv->caption() ) );
1332 }
1333 
1334 void KopeteChatWindow::updateChatLabel()
1335 {
1336  ChatView* chat = dynamic_cast<ChatView*>( sender() );
1337  if ( !chat || !m_tabBar )
1338  return;
1339 
1340  if ( m_tabBar )
1341  {
1342  m_tabBar->setTabText( m_tabBar->indexOf( chat ), chat->caption() );
1343  if ( m_tabBar->count() < 2 || m_tabBar->currentWidget() == chat )
1344  setCaption( chat->caption() );
1345  }
1346 }
1347 
1348 void KopeteChatWindow::resizeEvent( QResizeEvent *e )
1349 {
1350  KXmlGuiWindow::resizeEvent( e );
1351  if ( m_activeView && m_activeView->messagePart() )
1352  m_activeView->messagePart()->keepScrolledDown();
1353 }
1354 
1355 bool KopeteChatWindow::eventFilter( QObject *obj, QEvent *event )
1356 {
1357  if ( m_activeView && obj == m_activeView->editWidget() && event->type() == QEvent::KeyPress ) {
1358  QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
1359  if (nickComplete->shortcut().primary() == QKeySequence(keyEvent->key())) {
1360  m_activeView->nickComplete();
1361  return true;
1362  }
1363  }
1364  return KXmlGuiWindow::eventFilter(obj, event);
1365 }
1366 
1367 #include "kopetechatwindow.moc"
1368 
1369 // vim: set noet ts=4 sts=4 sw=4:
KopeteChatWindow::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *event)
Definition: kopetechatwindow.cpp:1355
ChatView
Definition: chatview.h:62
KPushButton
KopeteChatWindow::chatSessionChanged
void chatSessionChanged(Kopete::ChatSession *newSession)
ChatView::setCaption
void setCaption(const QString &text, bool modified)
Sets the text to be displayed on tab label and window caption.
Definition: chatview.cpp:673
ChatView::caption
QString & caption() const
Definition: chatview.cpp:668
KVBox
KopeteChatWindow::chatViewList
ChatViewList chatViewList
Definition: kopetechatwindow.h:111
ChatView::closeView
virtual bool closeView(bool force=false)
Definition: chatview.cpp:345
KopeteChatWindow::closing
void closing(KopeteChatWindow *)
KopeteChatWindow::chatViewCount
int chatViewCount()
Returns the number of chat views attached to this window.
Definition: kopetechatwindow.h:93
MetaContactMap
QMap< Kopete::MetaContact *, KopeteChatWindow * > MetaContactMap
Definition: kopetechatwindow.cpp:91
KopeteChatWindow::backgroundFile
KTemporaryFile * backgroundFile
Definition: kopetechatwindow.h:110
KopeteChatWindow::resizeEvent
virtual void resizeEvent(QResizeEvent *e)
Definition: kopetechatwindow.cpp:1348
ChatView::tabState
KopeteTabState tabState() const
Retrieves the tab state.
Definition: chatview.cpp:390
ChatView::dropEvent
virtual void dropEvent(QDropEvent *)
Definition: chatview.cpp:979
kopeteapplication.h
KopeteChatWindow::detachChatView
void detachChatView(ChatView *chat)
Detach a chat view from this window.
Definition: kopetechatwindow.cpp:803
AccountMap
QMap< Kopete::Account *, KopeteChatWindow * > AccountMap
Definition: kopetechatwindow.cpp:89
kopetechatwindow.h
QWidget
manager
virtual Kopete::ChatSession * manager(Kopete::Contact::CanCreateFlags)
Definition: chatwindowconfig.cpp:94
KopeteChatWindow::queryExit
virtual bool queryExit()
Definition: kopetechatwindow.cpp:1258
KopeteEmoticonAction
Definition: kopeteemoticonaction.h:28
KopeteChatWindow::slotSmileyActivated
void slotSmileyActivated(const QString &)
Definition: kopetechatwindow.cpp:1208
KopeteChatWindow::updateBackground
void updateBackground(const QPixmap &pm)
Definition: kopetechatwindow.cpp:930
ChatView::Normal
Definition: chatview.h:70
chatview.h
ChatView::editWidget
KTextEdit * editWidget()
Definition: chatview.cpp:187
ChatView::Highlighted
Definition: chatview.h:70
QObject
ChatView::setActive
void setActive(bool value)
Tells this view it is the active view.
Definition: chatview.cpp:887
KopeteChatWindow::queryClose
virtual bool queryClose()
Reimplemented from KXmlGuiWindow - asks each ChatView in the window if it is ok to close the window...
Definition: kopetechatwindow.cpp:1224
KopeteChatWindow::changeEvent
virtual void changeEvent(QEvent *e)
Definition: kopetechatwindow.cpp:1196
chatmemberslistview.h
Kopete::Items::MetaContact
Definition: kopeteitembase.h:57
chattexteditpart.h
Kopete::Items::Group
Definition: kopeteitembase.h:57
KXmlGuiWindow
ChatMembersListView
Definition: chatmemberslistview.h:36
KopeteChatWindow::window
static KopeteChatWindow * window(Kopete::ChatSession *manager)
Find the appropriate window for a ChatView of the given protocol to dock into.
Definition: kopetechatwindow.cpp:104
KopeteChatWindow::~KopeteChatWindow
~KopeteChatWindow()
Definition: kopetechatwindow.cpp:280
KopeteChatWindow::closeEvent
virtual void closeEvent(QCloseEvent *e)
Definition: kopetechatwindow.cpp:1274
WindowList
QList< KopeteChatWindow * > WindowList
Definition: kopetechatwindow.cpp:92
chatmessagepart.h
ChatView::Typing
Definition: chatview.h:70
KopeteApplication::isShuttingDown
bool isShuttingDown() const
Method to return whether or not we're shutting down or not at this point.
Definition: kopeteapplication.h:51
GroupMap
QMap< Kopete::Group *, KopeteChatWindow * > GroupMap
Definition: kopetechatwindow.cpp:90
KActionMenu
KopeteApplication
Definition: kopeteapplication.h:39
ChatView::setMainWindow
void setMainWindow(KopeteChatWindow *parent)
Changes the pointer to the chat window.
Definition: chatview.cpp:417
KopeteChatWindow::activeView
ChatView * activeView()
Returns the chatview in the currently active tab, or the only chat view if chatViewCount() == 1...
Definition: kopetechatwindow.cpp:347
KAction
QLabel
KopeteChatWindow::attachChatView
void attachChatView(ChatView *chat)
Attach an unattached chatview to this window.
Definition: kopetechatwindow.cpp:756
KopeteChatWindow::setActiveView
void setActiveView(QWidget *active)
Definition: kopetechatwindow.cpp:945
ChatView::Message
Definition: chatview.h:70
KopeteChatWindow::setStatus
void setStatus(const QString &)
Definition: kopetechatwindow.cpp:628
KopeteChatWindow
Definition: kopetechatwindow.h:61
kopeteemoticonaction.h
Kopete::ContactPtrList
QList< Contact * > ContactPtrList
Definition: kopetechatwindow.h:55
ChatView::Changed
Definition: chatview.h:70
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:53:40 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kopete/kopete

Skip menu "kopete/kopete"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdenetwork API Reference

Skip menu "kdenetwork API Reference"
  • kget
  • kopete
  •   kopete
  •   libkopete
  • krdc
  • krfb

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal