1 /***************************************************************************
2 * Copyright (C) 2004 by Hideki Ikemoto , (c) 2004 by 421 *
3 * ikemo@users.sourceforge.jp *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 ***************************************************************************/
11 /* Basic class of Tab widget, Tab bar, and Dock widget. */
13 #include "tabwidgetbase.h"
15 #include "kita_misc.h"
16 #include "parsemisc.h"
17 #include "signalcollection.h"
18 #include "datmanager.h"
20 #include <klibloader.h>
21 #include <kpopupmenu.h>
23 #include <kstdaccel.h>
26 #include <kkeydialog.h>
27 #include <kparts/dockmainwindow.h>
28 #include <kparts/factory.h>
29 #include <kdeversion.h>
32 #include <kstandarddirs.h>
34 #include <qapplication.h>
35 #include <qmessagebox.h>
37 #include <qfontmetrics.h>
40 /*--------------------------------------------------------------*/
43 KitaTabWidgetBase::KitaTabWidgetBase( QWidget* parent, const char* name, WFlags f )
44 : KTabWidget( parent, name, f )
49 /* setup part manager */
50 m_manager = new KParts::PartManager( parent, this, "KitaPartManager" );
51 m_manager->addManagedTopLevelWidget( parent );
55 KitaTabWidgetBase::~KitaTabWidgetBase()
58 if ( m_manager && !( m_manager->parts() ->isEmpty() ) ) {
60 while ( ( part = m_manager->parts() ->getFirst() ) != NULL ) {
61 m_manager->removePart( part );
62 removePage( part->widget() );
66 if ( m_manager ) delete m_manager;
69 /* remove widgets which don't belong to parts */
70 QWidget* view = currentPage();
71 while ( count() > 0 && view ) {
79 void KitaTabWidgetBase::slotCurrentChanged( QWidget * w )
81 if ( m_manager == NULL ) return ;
82 if ( w == NULL ) return ;
86 KParts::Part* part = findPartFromWidget( w );
88 m_manager->setActivePart( part );
93 /* show url with part. */ /* public slot */
94 void KitaTabWidgetBase::slotShowPart( const KURL& url, const QString& libName, const QString& mimetype )
96 if ( m_manager == NULL ) return ;
98 KLibFactory *factory = KLibLoader::self() ->factory( libName );
100 QMessageBox::critical( parentWidget(), i18n( " Load Error" ),
101 QString( i18n( "can't load %1." ) ).arg( libName ) );
105 if ( factory->inherits( "KParts::Factory" ) ) {
107 = static_cast< KParts::Factory* >( factory ) ->createPart( this );
108 m_manager->addPart( part );
109 addTab( part->widget(), url.url() );
110 showPage( part->widget() );
111 setTabToolTip( currentPage(), url.url() );
113 KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( part );
115 KParts::URLArgs arg( false, 0, 0, mimetype );
116 ext->setURLArgs( arg );
119 static_cast<KParts::ReadOnlyPart*>( part ) ->openURL( url );
124 /* close num-th tab */
125 /* see also customEvent */ /* public slot */
126 void KitaTabWidgetBase::slotCloseTab( int num )
128 CloseTabEvent * e = new CloseTabEvent( num );
129 QApplication::postEvent( this, e ); // Qt will delete it when done
133 /* Calling deleteWidget in the child part will be the
134 cause of crash. So you need to call deleteWidget
135 via custom event. */ /* protected */ /* virtual */
136 void KitaTabWidgetBase::customEvent( QCustomEvent * e )
138 if ( e->type() == EVENT_CloseTab ) {
139 deleteWidget ( page( static_cast< CloseTabEvent* >( e ) ->getIndex() ) );
144 /* protected */ /* virtual */
145 void KitaTabWidgetBase::deleteWidget( QWidget* w )
147 if ( w == NULL ) return ;
150 KParts::Part* part = findPartFromWidget( w );
151 if ( part ) m_manager->removePart( part );
157 KParts::Part* KitaTabWidgetBase::findPartFromWidget( QWidget* w )
159 if ( w == NULL ) return NULL;
160 if ( m_manager == NULL ) return NULL;
161 if ( m_manager->parts() ->isEmpty() ) return NULL;
164 QPtrListIterator<KParts::Part> it( *( m_manager->parts() ) );
165 while ( ( part = ( *it ) ) != NULL ) {
166 if ( part->widget() == w ) return part;
175 void KitaTabWidgetBase::connectSignals()
177 /* connect signals */
178 Kita::SignalCollection * signalCollection = Kita::SignalCollection::getInstance();
180 connect( this, SIGNAL( currentChanged ( QWidget * ) ),
181 SLOT( slotCurrentChanged ( QWidget * ) ) );
183 connect( this, SIGNAL( openURLRequestExt( const KURL&, const QString ) ),
184 signalCollection, SIGNAL( openURLRequestExt( const KURL&, const QString ) ) );
188 /*------------------------------------*/
189 /* common tab actions */
193 void KitaTabWidgetBase::setupActions()
195 actionCollection() ->setWidget( this );
198 QString str = i18n( "Configure S&hortcuts..." ) + "(" + QString( name() ) + ")";
202 SLOT( slotConfigureKeys() ),
206 new KAction( i18n( "Activate Next Tab" ),
207 KStdAccel::tabNext(),
209 SLOT( slotNextTab() ),
213 new KAction( i18n( "Activate Previous Tab" ),
214 KStdAccel::tabPrev(),
216 SLOT( slotPrevTab() ),
220 new KAction( i18n( "Close this tab" ),
223 SLOT( slotCloseCurrentTab() ),
227 new KAction( i18n( "Close Other Tabs" ),
230 SLOT( slotCloseOtherTab() ),
232 "tab_closeothertab" );
234 new KAction( i18n( "Close right tabs" ),
237 SLOT( slotCloseRightTab() ),
239 "tab_closerighttab" );
241 new KAction( i18n( "Close left tabs" ),
244 SLOT( slotCloseLeftTab() ),
246 "tab_closelefttab" );
248 new KAction( i18n( "Close all tabs" ),
251 SLOT( slotCloseAllTab() ),
259 void KitaTabWidgetBase::slotConfigureKeys()
261 QString str = "Tab Actions (" + QString( name() ) + ")";
262 KKeyDialog dlg( TRUE, this );
263 dlg.insert( actionCollection(), str );
269 void KitaTabWidgetBase::slotPrevTab()
272 int curpage = currentPageIndex();
273 if ( max <= 1 ) return ;
275 if ( curpage == 0 ) setCurrentPage( max - 1 );
276 else setCurrentPage( curpage - 1 );
280 void KitaTabWidgetBase::slotNextTab()
283 int curpage = currentPageIndex();
284 if ( max <= 1 ) return ;
286 if ( curpage == max - 1 ) setCurrentPage( 0 );
287 else setCurrentPage( curpage + 1 );
291 /* see also customEvent */ /* public slot */
292 void KitaTabWidgetBase::slotCloseCurrentTab()
294 slotCloseTab( currentPageIndex() );
298 /* see also customEvent */ /* public slot */
299 void KitaTabWidgetBase::slotCloseOtherTab( int idx )
302 if ( max == 0 ) return ;
303 if ( idx == -1 ) idx = currentPageIndex();
307 while ( i < max && i != idx ) {
320 /* see also customEvent */ /* public slot */
321 void KitaTabWidgetBase::slotCloseRightTab( int idx )
324 if ( max == 0 ) return ;
325 if ( idx == -1 ) idx = currentPageIndex();
337 /* see also customEvent */ /* public slot */
338 void KitaTabWidgetBase::slotCloseLeftTab( int idx )
341 if ( max == 0 ) return ;
342 if ( idx == -1 ) idx = currentPageIndex();
346 while ( i < max && i != idx ) {
353 /* see also customEvent */ /* public slot */
354 void KitaTabWidgetBase::slotCloseAllTab()
357 if ( max == 0 ) return ;
371 /*--------------------------------------------------------------------------------*/
372 /*--------------------------------------------------------------------------------*/
373 /*--------------------------------------------------------------------------------*/
379 /*--------------------------------------------------------------------------------*/
380 /*--------------------------------------------------------------------------------*/
381 /*--------------------------------------------------------------------------------*/
384 KitaDockWidgetBase::KitaDockWidgetBase( KDockManager* dockManager,
386 const QPixmap &pixmap,
388 const QString& strCaption,
389 const QString& strTabPageLabel,
391 : KDockWidget( dockManager, name, pixmap, parent, strCaption, strTabPageLabel, f )
393 setDockSite( KDockWidget::DockNone );
395 m_parentDock = static_cast< KParts::DockMainWindow* >( parent );
396 m_closeButtonClicked = FALSE;
398 /* connect signals */
399 connect( this, SIGNAL( headerCloseButtonClicked() ), SLOT( slotHeaderCloseButtonClicked() ) );
400 connect( this, SIGNAL( iMBeingClosed() ), SLOT( slotSaveDocStatus() ) );
402 Kita::SignalCollection* signalCollection = Kita::SignalCollection::getInstance();
404 /* emit when this widget is deactivated */
405 connect( this, SIGNAL( windowDeactivated() ),
406 signalCollection, SIGNAL( windowDeactivated() ) );
408 /* If this widget is active and receives
409 signal isKitaActive, then emit signal kitaIsActive. */
410 /* see also KitaHTMLPart::slotOnURL */
411 connect( signalCollection, SIGNAL( isKitaActive() ),
412 this, SLOT( slotIsKitaActive() ) );
414 connect( this, SIGNAL( kitaIsActive() ),
415 signalCollection, SIGNAL( kitaIsActive() ) );
419 KitaDockWidgetBase::~KitaDockWidgetBase() {}
423 void KitaDockWidgetBase::slotShowPart( const KURL& url, const QString& libName, const QString& mimetype )
425 slotShowDock( TRUE, TRUE );
427 static_cast<KitaTabWidgetBase*> ( getWidget() ) ->slotShowPart( url, libName, mimetype );
431 /* see also KitaMainWindow::KitaMainWindow() */ /* public */
432 void KitaDockWidgetBase::loadSession()
434 QString cfgPath = locateLocal( "appdata", "session.conf" );
435 KConfig cfg( cfgPath );
436 m_tabbed = cfg.readBoolEntry( name() + QString( "_Tabbed" ), FALSE );
437 m_docked = cfg.readBoolEntry( name() + QString( "_Docked" ), FALSE );
441 /* see also KitaMainWindow::~KitaMainWindow() */ /* public */
442 void KitaDockWidgetBase::saveSession()
444 /* copied from slotSaveDocStatus */
450 if ( parentDockTabGroup() ) m_tabbed = TRUE;
454 QString cfgPath = locateLocal( "appdata", "session.conf" );
455 KConfig cfg( cfgPath );
456 cfg.writeEntry( name() + QString( "_Tabbed" ), m_tabbed );
457 cfg.writeEntry( name() + QString( "_Docked" ), m_docked );
461 /* see also KitaMainWindow::resetWindows() */ /* public */
462 void KitaDockWidgetBase::setSession( bool docked, bool tabbed )
469 /* save the current dock status. */
470 /* This slot is called before this widget is closed. */
471 /* See also slotHeaderCloseButtonClicked(), */
472 /* slotHideDock(), and closeEvent(). */ /* private slot */
473 void KitaDockWidgetBase::slotSaveDocStatus()
478 /* This widget is docked.*/
481 if ( parentDockTabGroup() ) m_tabbed = TRUE; /* This widget is in the tab group.*/
484 emit checkToggleAction( FALSE ); /* to KitaMainWindow. see also KitaMainWindow::setupView() */
488 /* This slot is called when user clicks the close button. */
489 /* m_closeButtonClicked is set to prevent from re-openning */
490 /* the dock. To reset m_closeButtonClicked, call showDock */
491 /* with force = TRUE. See also slotShowDock() and showDock() */ /* private slot */
492 void KitaDockWidgetBase::slotHeaderCloseButtonClicked()
494 m_closeButtonClicked = TRUE;
499 /* show this dock widget later. */
500 /* Usually, call this slot instead of showDock(). */
501 /* See also showDock() and customEvent(). */ /* public slot */
502 void KitaDockWidgetBase::slotShowDock( bool activate, bool force )
504 ShowDockEvent * e = new ShowDockEvent( activate, force );
505 QApplication::postEvent( this, e ); // Qt will delete it when done
509 /* show this dock widget immediately. */
510 /* If activate is TRUE, activate this dock. */
511 /* If force is TRUE, show this anyway. */
512 /* If force is FALSE and tab has no children, */
513 /* this dock is not shown. */ /* public */
514 void KitaDockWidgetBase::showDock( bool activate, bool force )
516 if ( force ) m_closeButtonClicked = FALSE; /* see also slotHeaderCloseButtonClicked() */
517 if ( m_closeButtonClicked ) return ;
519 QWidget* wd = getWidget();
520 KitaTabWidgetBase* w = NULL;
521 if ( wd && wd->inherits( "KitaTabWidgetBase" ) ) w = static_cast<KitaTabWidgetBase*> ( wd );
522 if ( !force && w && w->count() == 0 ) return ;
524 if ( !isVisible() ) {
526 if ( m_docked ) { /* This dock was docked to the other dock. */
528 /* Sometimes the dock widget loses the former brother DockWidget.
529 because the brogher widget had transformed. So, find and set new brogher widget here. */
531 /* find new brother dock widget */
532 KDockWidget * newBrsDock = dockManager() ->getDockWidgetFromName( "Thread" );
536 if ( !m_tabbed ) { /* This dock was not tabbed */
538 /* Is thread dock on the tab? */
539 QWidget * tmpwidget = newBrsDock->parentDockTabGroup();
541 tmpwidget = tmpwidget->parentWidget();
542 if ( tmpwidget->inherits( "KDockWidget" ) )
543 newBrsDock = static_cast< KDockWidget* >( tmpwidget );
547 setFormerBrotherDockWidget( newBrsDock );
553 if ( !activate ) return ;
555 if ( isMinimized() ) showNormal();
556 topLevelWidget() ->raise();
559 emit checkToggleAction( TRUE ); /* to KitaMainWindow */
561 /* activate child Part */
562 if ( w ) w->slotCurrentChanged( w->currentPage() );
564 wd->setActiveWindow();
571 void KitaDockWidgetBase::slotHideDock()
575 m_parentDock->makeDockInvisible( this );
581 void KitaDockWidgetBase::slotToggleShowHide()
583 if ( !isVisible() ) slotShowDock( TRUE, TRUE );
588 /* when this widget is deactivated, emit signal
589 to popup vie SignalCollection. */ /* protected */
590 void KitaDockWidgetBase::windowActivationChange ( bool )
592 if ( !isActiveWindow() ) emit windowDeactivated();
597 void KitaDockWidgetBase::closeEvent( QCloseEvent* e )
600 KDockWidget::closeEvent( e );
604 /* protected */ /* virtual */
605 void KitaDockWidgetBase::customEvent( QCustomEvent * e )
607 if ( e->type() == EVENT_ShowDock ) {
608 ShowDockEvent * sde = static_cast< ShowDockEvent* >( e );
609 showDock( sde->getActivate(), sde->getForce() );
614 /* see also KitaHTMLPart::slotOnURL */ /* private slot */
615 void KitaDockWidgetBase::slotIsKitaActive()
617 if ( isActiveWindow() ) emit kitaIsActive();