00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qcombobox.h>
00025 #include <qhbox.h>
00026 #include <qimage.h>
00027 #include <qobjectlist.h>
00028 #include <qsplitter.h>
00029 #include <qwhatsthis.h>
00030
00031 #include <dcopclient.h>
00032 #include <kapplication.h>
00033 #include <kconfig.h>
00034 #include <kdebug.h>
00035 #include <kedittoolbar.h>
00036 #include <kguiitem.h>
00037 #include <khelpmenu.h>
00038 #include <kiconloader.h>
00039 #include <kkeydialog.h>
00040 #include <klibloader.h>
00041 #include <klistbox.h>
00042 #include <klocale.h>
00043 #include <kmessagebox.h>
00044 #include <kparts/componentfactory.h>
00045 #include <kplugininfo.h>
00046 #include <kpopupmenu.h>
00047 #include <ksettings/componentsdialog.h>
00048 #include <ksettings/dispatcher.h>
00049 #include <kshortcut.h>
00050 #include <kstandarddirs.h>
00051 #include <kstatusbar.h>
00052 #include <kstdaction.h>
00053 #include <ktip.h>
00054 #include <ktrader.h>
00055
00056 #include <infoextension.h>
00057
00058 #include "aboutdialog.h"
00059 #include "iconsidepane.h"
00060 #include "mainwindow.h"
00061 #include "plugin.h"
00062 #include "prefs.h"
00063 #include "sidepane.h"
00064
00065 using namespace Kontact;
00066
00067 MainWindow::MainWindow()
00068 : Kontact::Core(), mTopWidget( 0 ), mHeaderText( 0 ), mHeaderPixmap( 0 ), mSplitter( 0 ),
00069 mCurrentPlugin( 0 ), mLastInfoExtension( 0 ), mAboutDialog( 0 )
00070 {
00071 KTrader::OfferList offers = KTrader::self()->query(
00072 QString::fromLatin1( "Kontact/Plugin" ),
00073 QString( "[X-KDE-KontactPluginVersion] == %1" ).arg( KONTACT_PLUGIN_VERSION ) );
00074 mPluginInfos = KPluginInfo::fromServices( offers, Prefs::self()->config(),
00075 "Plugins" );
00076 for( KPluginInfo::List::Iterator it = mPluginInfos.begin();
00077 it != mPluginInfos.end(); ++it )
00078 ( *it )->load();
00079
00080 initWidgets();
00081
00082
00083 mPartManager = new KParts::PartManager( this );
00084 connect( mPartManager, SIGNAL( activePartChanged( KParts::Part* ) ),
00085 this, SLOT( slotActivePartChanged( KParts::Part* ) ) );
00086
00087 setupActions();
00088
00089 setHelpMenuEnabled( false );
00090
00091 KHelpMenu *helpMenu = new KHelpMenu( this, 0, true, actionCollection() );
00092 connect( helpMenu, SIGNAL( showAboutApplication() ),
00093 SLOT( showAboutDialog() ) );
00094
00095 loadPlugins();
00096
00097 KStdAction::keyBindings( this, SLOT( configureShortcuts() ), actionCollection() );
00098 KStdAction::configureToolbars( this, SLOT( configureToolbars() ), actionCollection() );
00099 setXMLFile( "kontactui.rc" );
00100
00101 setStandardToolBarMenuEnabled( true );
00102
00103 createGUI( 0 );
00104
00105 resize( 700, 520 );
00106 setAutoSaveSettings();
00107
00108 if ( mSidePane )
00109 mSidePane->updatePlugins();
00110
00111 #if 0
00112 KSettings::Dispatcher::self()->registerInstance( instance(), this,
00113 SLOT( updateConfig() ) );
00114 #endif
00115 loadSettings();
00116
00117 showTip( false );
00118
00119 statusBar()->show();
00120 }
00121
00122 MainWindow::~MainWindow()
00123 {
00124 saveSettings();
00125
00126 QPtrList<KParts::Part> parts = *mPartManager->parts();
00127 parts.setAutoDelete( true );
00128 parts.clear();
00129
00130 Prefs::self()->writeConfig();
00131 }
00132
00133 void MainWindow::initWidgets()
00134 {
00135 QHBox *topWidget = new QHBox( this );
00136 topWidget->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00137
00138 mTopWidget = topWidget;
00139
00140 setCentralWidget( mTopWidget );
00141
00142 mSidePaneType = Prefs::self()->mSidePaneType;
00143
00144 QHBox *mBox = 0;
00145
00146 if ( mSidePaneType == Prefs::SidePaneBars ) {
00147 mSplitter = new QSplitter( mTopWidget );
00148 mSidePane = new SidePane( this, mSplitter );
00149 mSidePane->setSizePolicy( QSizePolicy( QSizePolicy::Maximum,
00150 QSizePolicy::Preferred ) );
00151 mSplitter->setResizeMode( mSidePane, QSplitter::KeepSize );
00152 } else {
00153 mSplitter = 0;
00154 mBox = new QHBox( mTopWidget );
00155 mSidePane = new IconSidePane( this, mBox );
00156 mSidePane->setSizePolicy( QSizePolicy( QSizePolicy::Maximum,
00157 QSizePolicy::Preferred ) );
00158 }
00159
00160 connect( mSidePane, SIGNAL( pluginSelected( Kontact::Plugin * ) ),
00161 SLOT( selectPlugin( Kontact::Plugin * ) ) );
00162
00163 QVBox *vBox;
00164 if ( mSplitter ) {
00165 vBox = new QVBox( mSplitter );
00166 } else {
00167 vBox = new QVBox( mBox );
00168 }
00169
00170 initHeaderWidget( vBox );
00171 if ( mSidePaneType != Prefs::SidePaneBars )
00172 mHeaderFrame->hide();
00173
00174 vBox->setSpacing( 0 );
00175
00176 mStack = new QWidgetStack( vBox );
00177 }
00178
00179 void MainWindow::setupActions()
00180 {
00181 (void) KStdAction::quit( this, SLOT( slotQuit() ), actionCollection() );
00182 mNewActions = new KToolBarPopupAction( KGuiItem(i18n( "New" ), ""),
00183 KShortcut(), this, SLOT(slotNewClicked()),actionCollection(), "action_new" );
00184
00185 new KAction( i18n("Configure Kontact..."), "configure", 0, this, SLOT( slotPreferences() ),
00186 actionCollection(), "settings_configure_kontact" );
00187
00188 ( void )new KAction( i18n( "&Tip of the Day" ), 0,
00189 this, SLOT( slotShowTip() ), actionCollection(), "help_tipofday" );
00190
00191 }
00192
00193 void MainWindow::initHeaderWidget(QVBox *vBox)
00194 {
00195
00196 mHeaderFrame = new QHBox( vBox );
00197 mHeaderFrame->setSizePolicy( QSizePolicy::MinimumExpanding,
00198 QSizePolicy::Maximum );
00199 mHeaderFrame->setSpacing( 0 );
00200 mHeaderFrame->setFixedHeight( 22 );
00201
00202 mHeaderText = new QLabel( mHeaderFrame );
00203 mHeaderText->setSizePolicy( QSizePolicy::MinimumExpanding,
00204 QSizePolicy::Preferred );
00205 mHeaderText->setPaletteForegroundColor( colorGroup().light() );
00206 mHeaderText->setPaletteBackgroundColor( colorGroup().dark() );
00207
00208 mHeaderPixmap = new QLabel( mHeaderFrame );
00209 mHeaderPixmap->setSizePolicy( QSizePolicy::Maximum,
00210 QSizePolicy::Preferred );
00211 mHeaderPixmap->setAlignment( AlignRight|AlignVCenter );
00212 mHeaderPixmap->setPaletteBackgroundColor( colorGroup().dark() );
00213
00214 connect( this, SIGNAL( textChanged( const QString& ) ),
00215 this, SLOT( setHeaderText( const QString& ) ) );
00216 connect( this, SIGNAL( iconChanged( const QPixmap& ) ),
00217 this, SLOT( setHeaderPixmap( const QPixmap& ) ) );
00218
00219 QFont fnt( mSidePane->font() );
00220 fnt.setBold( true );
00221 fnt.setPointSize( mSidePane->font().pointSize() + 3 );
00222 mHeaderText->setFont( fnt );
00223 }
00224
00225 bool MainWindow::isPluginLoaded( const KPluginInfo * info )
00226 {
00227 return ( pluginFromInfo( info ) != 0 );
00228 }
00229
00230 Plugin *MainWindow::pluginFromInfo( const KPluginInfo *info )
00231 {
00232 PluginList::ConstIterator end = mPlugins.end();
00233 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it )
00234 if ( ( *it )->identifier() == info->pluginName() )
00235 return *it;
00236
00237 return 0;
00238 }
00239
00240 void MainWindow::loadPlugins()
00241 {
00242 QPtrList<Plugin> plugins;
00243 QPtrList<KParts::Part> loadDelayed;
00244
00245 uint i;
00246
00247 for( KPluginInfo::List::ConstIterator it = mPluginInfos.begin();
00248 it != mPluginInfos.end(); ++it )
00249 {
00250 if( ! ( *it )->isPluginEnabled() )
00251 continue;
00252 if( isPluginLoaded( *it ) ) {
00253 Plugin *plugin = pluginFromInfo( *it );
00254 if ( plugin )
00255 plugin->configUpdated();
00256 continue;
00257 }
00258
00259 kdDebug(5600) << "Loading Plugin: " << ( *it )->name() << endl;
00260 Kontact::Plugin *plugin =
00261 KParts::ComponentFactory::createInstanceFromService<Kontact::Plugin>(
00262 ( *it )->service(), this );
00263
00264 if ( !plugin )
00265 continue;
00266
00267 plugin->setIdentifier( ( *it )->pluginName() );
00268 plugin->setTitle( ( *it )->name() );
00269 plugin->setIcon( ( *it )->icon() );
00270
00271 QVariant libNameProp = ( *it )->property( "X-KDE-KontactPartLibraryName" );
00272 QVariant exeNameProp = ( *it )->property( "X-KDE-KontactPartExecutableName" );
00273 QVariant loadOnStart = ( *it )->property( "X-KDE-KontactPartLoadOnStart" );
00274
00275 if (!loadOnStart.isNull() && loadOnStart.toBool() )
00276 {
00277 mDelayedPreload.append(plugin);
00278 }
00279
00280 kdDebug() << "LIBNAMEPART: " << libNameProp.toString() << endl;
00281
00282 plugin->setPartLibraryName( libNameProp.toString().utf8() );
00283 plugin->setExecutableName( exeNameProp.toString() );
00284
00285 for( i = 0; i < plugins.count(); ++i ) {
00286 Plugin *p = plugins.at( i );
00287 if ( plugin->weight() < p->weight() ) break;
00288 }
00289
00290 plugins.insert( i, plugin );
00291 }
00292
00293 for( i = 0; i < plugins.count(); ++ i ) {
00294 Plugin *plugin = plugins.at( i );
00295
00296 KAction *action;
00297 QPtrList<KAction> *actionList = plugin->newActions();
00298
00299 for(action = actionList->first(); action; action = actionList->next()){
00300 kdDebug() << "Plugging " << action->name() << endl;
00301 action->plug(mNewActions->popupMenu());
00302 }
00303 addPlugin( plugin );
00304 }
00305
00306 mLastInfoExtension = 0;
00307 }
00308
00309 void MainWindow::unloadPlugins()
00310 {
00311 KPluginInfo::List::ConstIterator end = mPluginInfos.end();
00312 for ( KPluginInfo::List::ConstIterator it = mPluginInfos.begin();
00313 it != end; ++it ) {
00314 if ( ! ( *it )->isPluginEnabled() )
00315 removePlugin( *it );
00316 }
00317 }
00318
00319 bool MainWindow::removePlugin( const KPluginInfo * info )
00320 {
00321 PluginList::Iterator end = mPlugins.end();
00322 for ( PluginList::Iterator it = mPlugins.begin(); it != end; ++it )
00323 if( ( *it )->identifier() == info->pluginName() ) {
00324 Plugin *plugin = *it;
00325
00326 KAction *action;
00327 QPtrList<KAction> *actionList = plugin->newActions();
00328
00329 for ( action = actionList->first(); action; action = actionList->next() )
00330 {
00331 kdDebug() << "Unplugging " << action->name() << endl;
00332 action->unplug( mNewActions->popupMenu() );
00333 }
00334
00335 removeChildClient( plugin );
00336 delete plugin;
00337 mPlugins.remove( it );
00338 return true;
00339 }
00340 return false;
00341 }
00342
00343 void MainWindow::addPlugin( Kontact::Plugin *plugin )
00344 {
00345 kdDebug(5600) << "Added plugin" << endl;
00346
00347 mPlugins.append( plugin );
00348
00349
00350 insertChildClient( plugin );
00351 }
00352
00353 void MainWindow::partLoaded( Kontact::Plugin * , KParts::Part *part )
00354 {
00355 if ( part->widget() )
00356 mStack->addWidget( part->widget(), 0 );
00357
00358 mPartManager->addPart( part, false );
00359 }
00360
00361 void MainWindow::slotActivePartChanged( KParts::Part *part )
00362 {
00363 if ( !part ) {
00364 createGUI( 0 );
00365 return;
00366 }
00367
00368 if ( mLastInfoExtension ) {
00369 disconnect( mLastInfoExtension, SIGNAL( textChanged( const QString& ) ),
00370 this, SLOT( setHeaderText( const QString& ) ) );
00371 disconnect( mLastInfoExtension, SIGNAL( iconChanged( const QPixmap& ) ),
00372 this, SLOT( setHeaderPixmap( const QPixmap& ) ) );
00373 }
00374
00375 kdDebug(5600) << "Part activated: " << part << " with stack id. "
00376 << mStack->id( part->widget() )<< endl;
00377 QObjectList *l = part->queryList( "KParts::InfoExtension" );
00378 KParts::InfoExtension *ie = 0;
00379 if ( l )
00380 ie = static_cast<KParts::InfoExtension*>( l->first() );
00381 delete l;
00382 if ( ie ) {
00383 connect( ie, SIGNAL( textChanged( const QString& ) ),
00384 SLOT( setHeaderText( const QString& ) ) );
00385 connect( ie, SIGNAL( iconChanged( const QPixmap& ) ),
00386 SLOT( setHeaderPixmap( const QPixmap& ) ) );
00387 }
00388
00389 mLastInfoExtension = ie;
00390
00391 InfoExtData data = mInfoExtCache[ ie ];
00392 setHeaderPixmap( data.pixmap );
00393 setHeaderText( data.text );
00394
00395 createGUI( part );
00396
00397 statusBar()->clear();
00398 }
00399
00400 void MainWindow::slotNewClicked()
00401 {
00402 KAction *action = mCurrentPlugin->newActions()->first();
00403 if ( action ) {
00404 action->activate();
00405 } else {
00406 PluginList::Iterator it;
00407 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00408 action = (*it)->newActions()->first();
00409 if ( action ) {
00410 action->activate();
00411 return;
00412 }
00413 }
00414 }
00415 }
00416
00417 void MainWindow::selectPlugin( Kontact::Plugin *plugin )
00418 {
00419 if ( !plugin )
00420 return;
00421
00422 if ( plugin->isRunningStandalone() )
00423 {
00424 statusBar()->message(
00425 i18n("Application is running standalone. Foregrounding..."), 1000);
00426 plugin->bringToForeground();
00427 return;
00428 }
00429
00430 KApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
00431
00432 if ( mSidePane )
00433 mSidePane->selectPlugin( plugin );
00434
00435 KParts::Part *part = plugin->part();
00436
00437 if ( !part ) {
00438 KMessageBox::error( this, i18n("Can't load Part for %1")
00439 .arg( plugin->title() ) );
00440 KApplication::restoreOverrideCursor();
00441 return;
00442 }
00443
00444 plugin->select();
00445
00446 mPartManager->setActivePart( part );
00447 QWidget *view = part->widget();
00448 Q_ASSERT( view );
00449
00450 if ( view ) {
00451 mStack->raiseWidget( view );
00452 view->show();
00453 view->setFocus();
00454 mCurrentPlugin = plugin;
00455 KAction *action = plugin->newActions()->first();
00456 setCaption( i18n("Plugin dependent window title" ,"%1 - Kontact").arg( plugin->title() ) );
00457 if ( action ) {
00458 mNewActions->setIconSet( action->iconSet() );
00459 mNewActions->setText( action->text() );
00460 } else {
00461 PluginList::Iterator it;
00462 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00463 action = (*it)->newActions()->first();
00464 if ( action ) {
00465 mNewActions->setIconSet( action->iconSet() );
00466 mNewActions->setText( action->text() );
00467 break;
00468 }
00469 }
00470 }
00471 }
00472
00473 QStringList invisibleActions = plugin->invisibleToolbarActions();
00474
00475 QStringList::ConstIterator it;
00476 for ( it = invisibleActions.begin(); it != invisibleActions.end(); ++it ) {
00477 KAction *action = part->actionCollection()->action( (*it).latin1() );
00478 if ( action )
00479 action->unplug( toolBar() );
00480 }
00481
00482 KApplication::restoreOverrideCursor();
00483 }
00484
00485 void MainWindow::selectPlugin( const QString &pluginName )
00486 {
00487 PluginList::ConstIterator end = mPlugins.end();
00488 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it )
00489 if ( ( *it )->identifier() == pluginName ) {
00490 selectPlugin( *it );
00491 return;
00492 }
00493 }
00494
00495 void MainWindow::loadSettings()
00496 {
00497 if ( mSplitter )
00498 mSplitter->setSizes( Prefs::self()->mSidePaneSplitter );
00499
00500
00501 PluginList::ConstIterator it;
00502 for ( it = mDelayedPreload.begin(); it != mDelayedPreload.end(); ++it )
00503 selectPlugin( *it );
00504
00505 selectPlugin( Prefs::self()->mActivePlugin );
00506 }
00507
00508 void MainWindow::saveSettings()
00509 {
00510 if ( mSplitter )
00511 Prefs::self()->mSidePaneSplitter = mSplitter->sizes();
00512
00513 if ( mCurrentPlugin )
00514 Prefs::self()->mActivePlugin = mCurrentPlugin->identifier();
00515 }
00516
00517 void MainWindow::slotShowTip()
00518 {
00519 showTip( true );
00520 }
00521
00522 void MainWindow::showTip(bool force)
00523 {
00524 QStringList tips;
00525 PluginList::ConstIterator end = mPlugins.end();
00526 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it ) {
00527 QString file = ( *it )->tipFile();
00528 if ( !file.isEmpty() )
00529 tips.append( file );
00530 }
00531
00532 KTipDialog::showMultiTip(this, tips, force);
00533 }
00534
00535 void MainWindow::slotQuit()
00536 {
00537 close();
00538 }
00539
00540 void MainWindow::slotPreferences()
00541 {
00542 static KSettings::ComponentsDialog *dlg = 0;
00543 if( !dlg ) {
00544 dlg = new KSettings::ComponentsDialog( this );
00545 dlg->setPluginInfos( mPluginInfos );
00546 connect( dlg, SIGNAL( okClicked() ), SLOT( pluginsChanged() ) );
00547 connect( dlg, SIGNAL( applyClicked() ), SLOT( pluginsChanged() ) );
00548 }
00549
00550 dlg->show();
00551 }
00552
00553 int MainWindow::startServiceFor( const QString& serviceType,
00554 const QString& constraint,
00555 const QString& preferences,
00556 QString *error, QCString* dcopService,
00557 int flags )
00558 {
00559 PluginList::ConstIterator end = mPlugins.end();
00560 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it ) {
00561 if ( ( *it )->createDCOPInterface( serviceType ) ) {
00562 kdDebug(5600) << "found interface for " << serviceType << endl;
00563 if ( dcopService )
00564 *dcopService = ( *it )->dcopClient()->appId();
00565 kdDebug(5600) << "appId=" << ( *it )->dcopClient()->appId() << endl;
00566 return 0;
00567 }
00568 }
00569 kdDebug(5600) <<
00570 "Didn't find dcop interface, falling back to external process" << endl;
00571 return KDCOPServiceStarter::startServiceFor( serviceType, constraint,
00572 preferences, error, dcopService, flags );
00573 }
00574
00575 void MainWindow::setHeaderText( const QString &text )
00576 {
00577 mInfoExtCache[ mLastInfoExtension ].text = text;
00578 mHeaderText->setText( text );
00579 }
00580
00581 void MainWindow::setHeaderPixmap( const QPixmap &pixmap )
00582 {
00583 QPixmap pm( pixmap );
00584
00585 if ( pm.height() > 22 || pm.width() > 22 ) {
00586 QImage img;
00587 img = pixmap;
00588 pm = img.smoothScale( 22, 22, QImage::ScaleMin );
00589 }
00590
00591 mInfoExtCache[ mLastInfoExtension ].pixmap = pm;
00592 mHeaderPixmap->setPixmap( pm );
00593 }
00594
00595 void MainWindow::pluginsChanged()
00596 {
00597 unloadPlugins();
00598 loadPlugins();
00599 mSidePane->updatePlugins();
00600 }
00601
00602 void MainWindow::updateConfig()
00603 {
00604 kdDebug( 5600 ) << k_funcinfo << endl;
00605
00606 saveSettings();
00607
00608 #if 0
00609 bool sidePaneChanged = ( Prefs::self()->mSidePaneType != mSidePaneType );
00610
00611 if ( sidePaneChanged ) {
00612 mSidePaneType = Prefs::self()->mSidePaneType;
00613
00614 delete mSidePane;
00615
00616 switch ( mSidePaneType ) {
00617 case Prefs::SidePaneIcons:
00618 mSidePane = new IconSidePane( this, mSplitter );
00619 mHeaderFrame->hide();
00620 break;
00621 default:
00622 kdError() << "Invalid SidePaneType: " << mSidePaneType << endl;
00623 case Prefs::SidePaneBars:
00624 mSidePane = new SidePane( this, mSplitter );
00625 mHeaderFrame->show();
00626 break;
00627 }
00628
00629 mSplitter->setResizeMode( mSidePane, QSplitter::KeepSize );
00630
00631 mSidePane->setSizePolicy( QSizePolicy( QSizePolicy::Maximum,
00632 QSizePolicy::Preferred ) );
00633
00634 connect( mSidePane, SIGNAL( pluginSelected( Kontact::Plugin * ) ),
00635 SLOT( selectPlugin( Kontact::Plugin * ) ) );
00636
00637 mSplitter->moveToFirst( mSidePane );
00638
00639 mSidePane->show();
00640 }
00641
00642 if ( sidePaneChanged )
00643 mSidePane->updatePlugins();
00644 #endif
00645
00646 loadSettings();
00647 }
00648
00649 void MainWindow::showAboutDialog()
00650 {
00651 KApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
00652
00653 if ( !mAboutDialog ) {
00654 mAboutDialog = new AboutDialog( this );
00655 }
00656
00657 mAboutDialog->show();
00658 mAboutDialog->raise();
00659 KApplication::restoreOverrideCursor();
00660 }
00661
00662 void MainWindow::configureShortcuts()
00663 {
00664 KKeyDialog dialog( true, this );
00665 dialog.insert( actionCollection() );
00666
00667 if ( mCurrentPlugin && mCurrentPlugin->part() )
00668 dialog.insert( mCurrentPlugin->part()->actionCollection() );
00669
00670 dialog.configure();
00671 }
00672
00673 void MainWindow::configureToolbars()
00674 {
00675 saveMainWindowSettings( KGlobal::config(), "MainWindow" );
00676
00677 KEditToolbar edit( factory() );
00678 connect( &edit, SIGNAL( newToolbarConfig() ),
00679 this, SLOT( slotNewToolbarConfig() ) );
00680 edit.exec();
00681 }
00682
00683 void MainWindow::slotNewToolbarConfig()
00684 {
00685 createGUI( mCurrentPlugin->part() );
00686 applyMainWindowSettings( KGlobal::config(), "MainWindow" );
00687 }
00688
00689 #include "mainwindow.moc"
00690