00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <qaction.h>
00024 #include <qcombobox.h>
00025 #include <qdockarea.h>
00026 #include <qguardedptr.h>
00027 #include <qhbox.h>
00028 #include <qimage.h>
00029 #include <qobjectlist.h>
00030 #include <qprogressbar.h>
00031 #include <qpushbutton.h>
00032 #include <qsplitter.h>
00033 #include <qtimer.h>
00034 #include <qwhatsthis.h>
00035
00036 #include <dcopclient.h>
00037 #include <kapplication.h>
00038 #include <kconfig.h>
00039 #include <kdebug.h>
00040 #include <kedittoolbar.h>
00041 #include <kguiitem.h>
00042 #include <khelpmenu.h>
00043 #include <kiconloader.h>
00044 #include <kkeydialog.h>
00045 #include <klibloader.h>
00046 #include <klistbox.h>
00047 #include <klocale.h>
00048 #include <kmessagebox.h>
00049 #include <kparts/componentfactory.h>
00050 #include <kplugininfo.h>
00051 #include <kpopupmenu.h>
00052 #include <ksettings/dialog.h>
00053 #include <ksettings/dispatcher.h>
00054 #include <kshortcut.h>
00055 #include <kstandarddirs.h>
00056 #include <kstatusbar.h>
00057 #include <kstdaction.h>
00058 #include <ktip.h>
00059 #include <ktrader.h>
00060 #include <ksettings/componentsdialog.h>
00061 #include <kstringhandler.h>
00062 #include <krsqueezedtextlabel.h>
00063 #include <khtml_part.h>
00064 #include <khtmlview.h>
00065 #include <libkdepim/kfileio.h>
00066 #include <kcursor.h>
00067 #include <krun.h>
00068 #include <kaboutdata.h>
00069 #include <kmenubar.h>
00070 #include <kstdaccel.h>
00071 #include <kcmultidialog.h>
00072 #include <kipc.h>
00073
00074 #include "aboutdialog.h"
00075 #include "iconsidepane.h"
00076 #include "mainwindow.h"
00077 #include "plugin.h"
00078 #include "prefs.h"
00079 #include "profiledialog.h"
00080 #include "profilemanager.h"
00081 #include "progressdialog.h"
00082 #include "statusbarprogresswidget.h"
00083 #include "broadcaststatus.h"
00084
00085 using namespace Kontact;
00086
00087 class SettingsDialogWrapper : public KSettings::Dialog
00088 {
00089 public:
00090 SettingsDialogWrapper( ContentInListView content, QWidget * parent = 0 )
00091 : KSettings::Dialog( content, parent, 0 )
00092 {
00093 }
00094
00095
00096 void fixButtonLabel( QWidget *widget )
00097 {
00098 QObject *object = widget->child( "KJanusWidget::buttonBelowList" );
00099 QPushButton *button = static_cast<QPushButton*>( object );
00100 if ( button )
00101 button->setText( i18n( "Select Components ..." ) );
00102 }
00103 };
00104
00105 MainWindow::MainWindow()
00106 : Kontact::Core(), mTopWidget( 0 ), mSplitter( 0 ),
00107 mCurrentPlugin( 0 ), mAboutDialog( 0 ), mReallyClose( false ), mSyncActionsEnabled( true )
00108 {
00109
00110
00111 setWFlags( getWFlags() | WGroupLeader );
00112
00113 initGUI();
00114 initObject();
00115 kdDebug(5600) << "Kontact Version: " << kapp->aboutData()->version()
00116 << " started at: " << QDateTime::currentDateTime().toString() << endl;
00117 }
00118
00119 void MainWindow::initGUI()
00120 {
00121 initWidgets();
00122 setupActions();
00123 setHelpMenuEnabled( false );
00124 KHelpMenu *helpMenu = new KHelpMenu( this, 0, true, actionCollection() );
00125 connect( helpMenu, SIGNAL( showAboutApplication() ),
00126 SLOT( showAboutDialog() ) );
00127
00128 KTrader::OfferList offers = KTrader::self()->query(
00129 QString::fromLatin1( "Kontact/Plugin" ),
00130 QString( "[X-KDE-KontactPluginVersion] == %1" ).arg( KONTACT_PLUGIN_VERSION ) );
00131 mPluginInfos = KPluginInfo::fromServices( offers, Prefs::self()->config(), "Plugins" );
00132
00133 KPluginInfo::List::Iterator it;
00134 for ( it = mPluginInfos.begin(); it != mPluginInfos.end(); ++it ) {
00135 (*it)->load();
00136
00137 KAction *action = new KAction( (*it)->name(), (*it)->icon(), KShortcut(),
00138 this, SLOT(slotActionTriggered()),
00139 actionCollection(), (*it)->pluginName().latin1() );
00140 action->setName( (*it)->pluginName().latin1() );
00141 action->setWhatsThis( i18n( "Switch to plugin %1" ).arg( (*it)->name() ) );
00142
00143 QVariant hasPartProp = (*it)->property( "X-KDE-KontactPluginHasPart" );
00144 if ( !hasPartProp.isValid() || hasPartProp.toBool() ) {
00145 mActionPlugins.append( action );
00146 }
00147 }
00148
00149 KStdAction::keyBindings( this, SLOT( configureShortcuts() ), actionCollection() );
00150 KStdAction::configureToolbars( this, SLOT( configureToolbars() ), actionCollection() );
00151 setXMLFile( "kontactui.rc" );
00152
00153 setStandardToolBarMenuEnabled( true );
00154
00155 createGUI( 0 );
00156
00157 loadPlugins();
00158
00159 resize( 700, 520 );
00160 setAutoSaveSettings();
00161
00162 connect( Kontact::ProfileManager::self(), SIGNAL( profileLoaded( const QString& ) ),
00163 this, SLOT( slotLoadProfile( const QString& ) ) );
00164 connect( Kontact::ProfileManager::self(), SIGNAL( saveToProfileRequested( const QString& ) ),
00165 this, SLOT( slotSaveToProfile( const QString& ) ) );
00166 }
00167
00168
00169 void MainWindow::initObject()
00170 {
00171
00172 mPartManager = new KParts::PartManager( this );
00173 connect( mPartManager, SIGNAL( activePartChanged( KParts::Part* ) ),
00174 this, SLOT( slotActivePartChanged( KParts::Part* ) ) );
00175
00176 if ( mSidePane ) {
00177 mSidePane->updatePlugins();
00178 }
00179
00180 KSettings::Dispatcher::self()->registerInstance( instance(), this,
00181 SLOT( updateConfig() ) );
00182
00183 loadSettings();
00184
00185 statusBar()->show();
00186
00187 showTip( false );
00188
00189
00190 slotShowStatusMsg( QString::null );
00191
00192 connect( KPIM::BroadcastStatus::instance(), SIGNAL( statusMsg( const QString& ) ),
00193 this, SLOT( slotShowStatusMsg( const QString& ) ) );
00194
00195
00196 activatePluginModule();
00197
00198 if ( Prefs::lastVersionSeen() == kapp->aboutData()->version() ) {
00199 selectPlugin( mCurrentPlugin );
00200 }
00201
00202 paintAboutScreen( introductionString() );
00203 Prefs::setLastVersionSeen( kapp->aboutData()->version() );
00204 }
00205
00206 MainWindow::~MainWindow()
00207 {
00208 saveSettings();
00209
00210 QPtrList<KParts::Part> parts = *mPartManager->parts();
00211
00212 for ( KParts::Part *p = parts.last(); p; p = parts.prev() ) {
00213 delete p;
00214 p = 0;
00215 }
00216
00217 Prefs::self()->writeConfig();
00218 }
00219
00220 void MainWindow::setActivePluginModule( const QString &module )
00221 {
00222 mActiveModule = module;
00223 activatePluginModule();
00224 }
00225
00226 void MainWindow::activatePluginModule()
00227 {
00228 if ( !mActiveModule.isEmpty() ) {
00229 PluginList::ConstIterator end = mPlugins.end();
00230 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it )
00231 if ( ( *it )->identifier().contains( mActiveModule ) ) {
00232 selectPlugin( *it );
00233 return;
00234 }
00235 }
00236 }
00237
00238 void MainWindow::initWidgets()
00239 {
00240
00241 mTopWidget = new QHBox( this );
00242 mTopWidget->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00243 setCentralWidget( mTopWidget );
00244
00245 QHBox *mBox = 0;
00246 mSplitter = new QSplitter( mTopWidget );
00247 mBox = new QHBox( mTopWidget );
00248 mSidePane = new IconSidePane( this, mSplitter );
00249 mSidePane->setSizePolicy( QSizePolicy( QSizePolicy::Maximum,
00250 QSizePolicy::Preferred ) );
00251
00252 QValueList<int> sizes;
00253 sizes << 0;
00254 mSplitter->setSizes(sizes);
00255
00256 connect( mSidePane, SIGNAL( pluginSelected( Kontact::Plugin * ) ),
00257 SLOT( selectPlugin( Kontact::Plugin * ) ) );
00258
00259 QVBox *vBox;
00260 if ( mSplitter ) {
00261 vBox = new QVBox( mSplitter );
00262 } else {
00263 vBox = new QVBox( mBox );
00264 }
00265
00266 vBox->setSpacing( 0 );
00267
00268 mPartsStack = new QWidgetStack( vBox );
00269 initAboutScreen();
00270
00271 QString loading = i18n( "<h2 style='text-align:center; margin-top: 0px; margin-bottom: 0px'>%1</h2>" )
00272 .arg( i18n("Loading Kontact...") );
00273
00274 paintAboutScreen( loading );
00275
00276
00277 KPIM::ProgressDialog *progressDialog = new KPIM::ProgressDialog( statusBar(), this );
00278 progressDialog->hide();
00279
00280 mLittleProgress = new KPIM::StatusbarProgressWidget( progressDialog, statusBar() );
00281
00282 mStatusMsgLabel = new KRSqueezedTextLabel( i18n( " Initializing..." ), statusBar() );
00283 mStatusMsgLabel->setAlignment( AlignLeft | AlignVCenter );
00284
00285 statusBar()->addWidget( mStatusMsgLabel, 10 , false );
00286 statusBar()->addWidget( mLittleProgress, 0 , true );
00287 mLittleProgress->show();
00288 }
00289
00290
00291 void MainWindow::paintAboutScreen( const QString& msg )
00292 {
00293 QString location = locate( "data", "kontact/about/main.html" );
00294 QString content = KPIM::kFileToString( location );
00295 content = content.arg( locate( "data", "libkdepim/about/kde_infopage.css" ) );
00296 if ( kapp->reverseLayout() )
00297 content = content.arg( "@import \"%1\";" ).arg( locate( "data", "libkdepim/about/kde_infopage_rtl.css" ) );
00298 else
00299 content = content.arg( "" );
00300
00301 mIntroPart->begin( KURL( location ) );
00302
00303 QString appName( i18n( "KDE Kontact" ) );
00304 QString catchPhrase( i18n( "Get Organized!" ) );
00305 QString quickDescription( i18n( "The KDE Personal Information Management Suite" ) );
00306
00307 mIntroPart->write( content.arg( QFont().pointSize() + 2 ).arg( appName )
00308 .arg( catchPhrase ).arg( quickDescription ).arg( msg ) );
00309 mIntroPart->end();
00310 }
00311
00312 void MainWindow::initAboutScreen()
00313 {
00314 QHBox *introbox = new QHBox( mPartsStack );
00315 mPartsStack->addWidget( introbox );
00316 mPartsStack->raiseWidget( introbox );
00317 mIntroPart = new KHTMLPart( introbox );
00318 mIntroPart->widget()->setFocusPolicy( WheelFocus );
00319
00320 mIntroPart->setPluginsEnabled( false );
00321 mIntroPart->setJScriptEnabled( false );
00322 mIntroPart->setJavaEnabled( false );
00323 mIntroPart->setMetaRefreshEnabled( false );
00324 mIntroPart->setURLCursor( KCursor::handCursor() );
00325 mIntroPart->view()->setLineWidth( 0 );
00326
00327 connect( mIntroPart->browserExtension(),
00328 SIGNAL( openURLRequest( const KURL&, const KParts::URLArgs& ) ),
00329 SLOT( slotOpenUrl( const KURL& ) ) );
00330
00331 connect( mIntroPart->browserExtension(),
00332 SIGNAL( createNewWindow( const KURL&, const KParts::URLArgs& ) ),
00333 SLOT( slotOpenUrl( const KURL& ) ) );
00334 }
00335
00336 void MainWindow::setupActions()
00337 {
00338 KStdAction::quit( this, SLOT( slotQuit() ), actionCollection() );
00339 mNewActions = new KToolBarPopupAction( KGuiItem( i18n( "New" ), "" ),
00340 KStdAccel::shortcut(KStdAccel::New), this, SLOT( slotNewClicked() ),
00341 actionCollection(), "action_new" );
00342
00343 KConfig* const cfg = Prefs::self()->config();
00344 cfg->setGroup( "Kontact Groupware Settings" );
00345 mSyncActionsEnabled = cfg->readBoolEntry( "GroupwareMailFoldersEnabled", true );
00346
00347 if ( mSyncActionsEnabled ) {
00348 mSyncActions = new KToolBarPopupAction( KGuiItem( i18n( "Synchronize" ), "kitchensync" ),
00349 KStdAccel::shortcut(KStdAccel::Reload), this, SLOT( slotSyncClicked() ),
00350 actionCollection(), "action_sync" );
00351 }
00352 new KAction( i18n( "Configure Kontact..." ), "configure", 0, this, SLOT( slotPreferences() ),
00353 actionCollection(), "settings_configure_kontact" );
00354
00355 new KAction( i18n( "Configure &Profiles..." ), 0, this, SLOT( slotConfigureProfiles() ),
00356 actionCollection(), "settings_configure_kontact_profiles" );
00357
00358 new KAction( i18n( "&Kontact Introduction" ), 0, this, SLOT( slotShowIntroduction() ),
00359 actionCollection(), "help_introduction" );
00360 new KAction( i18n( "&Tip of the Day" ), 0, this, SLOT( slotShowTip() ),
00361 actionCollection(), "help_tipofday" );
00362
00363 KWidgetAction* spacerAction = new KWidgetAction( new QWidget( this ), "SpacerAction", "", 0, 0, actionCollection(), "navigator_spacer_item" );
00364 spacerAction->setAutoSized( true );
00365 }
00366
00367 void MainWindow::slotConfigureProfiles()
00368 {
00369 QGuardedPtr<Kontact::ProfileDialog> dlg = new Kontact::ProfileDialog( this );
00370 dlg->setModal( true );
00371 dlg->exec();
00372 delete dlg;
00373 }
00374
00375 namespace {
00376 void copyConfigEntry( KConfig* source, KConfig* dest, const QString& group, const QString& key, const QString& defaultValue=QString() )
00377 {
00378 source->setGroup( group );
00379 dest->setGroup( group );
00380 dest->writeEntry( key, source->readEntry( key, defaultValue ) );
00381 }
00382 }
00383
00384 void MainWindow::slotSaveToProfile( const QString& id )
00385 {
00386 const QString path = Kontact::ProfileManager::self()->profileById( id ).saveLocation();
00387 if ( path.isNull() )
00388 return;
00389
00390 KConfig* const cfg = Prefs::self()->config();
00391 Prefs::self()->writeConfig();
00392 saveMainWindowSettings( cfg );
00393 saveSettings();
00394
00395 KConfig profile( path+"/kontactrc", false, false );
00396 ::copyConfigEntry( cfg, &profile, "MainWindow Toolbar navigatorToolBar", "Hidden", "true" );
00397 ::copyConfigEntry( cfg, &profile, "View", "SidePaneSplitter" );
00398 ::copyConfigEntry( cfg, &profile, "Icons", "Theme" );
00399
00400 for ( PluginList::Iterator it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00401 if ( !(*it)->isRunningStandalone() ) {
00402 (*it)->part();
00403 }
00404 (*it)->saveToProfile( path );
00405 }
00406 }
00407
00408 void MainWindow::slotLoadProfile( const QString& id )
00409 {
00410 const QString path = Kontact::ProfileManager::self()->profileById( id ).saveLocation();
00411 if ( path.isNull() )
00412 return;
00413
00414 KConfig* const cfg = Prefs::self()->config();
00415 Prefs::self()->writeConfig();
00416 saveMainWindowSettings( cfg );
00417 saveSettings();
00418
00419 const KConfig profile( path+"/kontactrc", false, false );
00420 const QStringList groups = profile.groupList();
00421 for ( QStringList::ConstIterator it = groups.begin(), end = groups.end(); it != end; ++it )
00422 {
00423 cfg->setGroup( *it );
00424 typedef QMap<QString, QString> StringMap;
00425 const StringMap entries = profile.entryMap( *it );
00426 for ( StringMap::ConstIterator it2 = entries.begin(), end = entries.end(); it2 != end; ++it2 )
00427 {
00428 if ( it2.data() == "KONTACT_PROFILE_DELETE_KEY" )
00429 cfg->deleteEntry( it2.key() );
00430 else
00431 cfg->writeEntry( it2.key(), it2.data() );
00432 }
00433 }
00434
00435 cfg->sync();
00436 Prefs::self()->readConfig();
00437 applyMainWindowSettings( cfg );
00438 KIconTheme::reconfigure();
00439 const WId wid = winId();
00440 KIPC::sendMessage( KIPC::PaletteChanged, wid );
00441 KIPC::sendMessage( KIPC::FontChanged, wid );
00442 KIPC::sendMessage( KIPC::StyleChanged, wid );
00443 KIPC::sendMessage( KIPC::SettingsChanged, wid );
00444 for ( int i = 0; i < KIcon::LastGroup; ++i )
00445 KIPC::sendMessage( KIPC::IconChanged, wid, i );
00446
00447 loadSettings();
00448
00449 for ( PluginList::Iterator it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00450 if ( !(*it)->isRunningStandalone() ) {
00451 kdDebug() << "Ensure loaded: " << (*it)->identifier() << endl;
00452 (*it)->part();
00453 }
00454 (*it)->loadProfile( path );
00455 }
00456 }
00457
00458 bool MainWindow::isPluginLoaded( const KPluginInfo *info )
00459 {
00460 return (pluginFromInfo( info ) != 0);
00461 }
00462
00463 Plugin *MainWindow::pluginFromInfo( const KPluginInfo *info )
00464 {
00465 PluginList::ConstIterator end = mPlugins.end();
00466 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it )
00467 if ( (*it)->identifier() == info->pluginName() )
00468 return *it;
00469
00470 return 0;
00471 }
00472
00473 Plugin *MainWindow::pluginFromAction( const KAction *action )
00474 {
00475 PluginList::ConstIterator end = mPlugins.end();
00476 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it ) {
00477 if ( (*it)->identifier() == action->name() ) {
00478 return *it;
00479 }
00480 }
00481 return 0;
00482 }
00483
00484 bool MainWindow::isPluginLoadedByAction( const KAction *action )
00485 {
00486 KPluginInfo::List::ConstIterator it;
00487 for ( it = mPluginInfos.begin(); it != mPluginInfos.end(); ++it ) {
00488 if ( !(*it)->isPluginEnabled() )
00489 continue;
00490 if ( isPluginLoaded( *it ) ) {
00491 Plugin *plugin = pluginFromInfo( *it );
00492 if ( plugin ) {
00493 if ( plugin->identifier() == action->name() ) {
00494 return true;
00495 }
00496 }
00497 }
00498 }
00499 return false;
00500 }
00501
00502 void MainWindow::sortActionsByWeight()
00503 {
00504 QPtrList<KAction> sorted;
00505
00506 QPtrListIterator<KAction> eit( mActionPlugins );
00507 KAction *action;
00508 while ( ( action = eit.current() ) != 0 ) {
00509 ++eit;
00510 QPtrListIterator<KAction> sortIt( sorted );
00511 uint at = 0;
00512 KAction *saction;
00513 Plugin *p1 = pluginFromAction( action );
00514 while ( ( saction = sortIt.current() ) != 0 ) {
00515 Plugin *p2 = pluginFromAction( saction );
00516 if ( p1 && p2 && p1->weight() >= p2->weight() ) {
00517 ++sortIt;
00518 ++at;
00519 } else {
00520 break;
00521 }
00522 }
00523 sorted.insert( at, action );
00524 }
00525 mActionPlugins = sorted;
00526 }
00527
00528 void MainWindow::loadPlugins()
00529 {
00530 QPtrList<Plugin> plugins;
00531 QPtrList<KParts::Part> loadDelayed;
00532
00533 uint i;
00534 KPluginInfo::List::ConstIterator it;
00535 for ( it = mPluginInfos.begin(); it != mPluginInfos.end(); ++it ) {
00536 if ( !(*it)->isPluginEnabled() )
00537 continue;
00538 if ( isPluginLoaded( *it ) ) {
00539 Plugin *plugin = pluginFromInfo( *it );
00540 if ( plugin )
00541 plugin->configUpdated();
00542 continue;
00543 }
00544
00545 kdDebug(5600) << "Loading Plugin: " << (*it)->name() << endl;
00546 Kontact::Plugin *plugin =
00547 KParts::ComponentFactory::createInstanceFromService<Kontact::Plugin>(
00548 (*it)->service(), this );
00549
00550 if ( !plugin )
00551 continue;
00552
00553 plugin->setIdentifier( (*it)->pluginName() );
00554 plugin->setTitle( (*it)->name() );
00555 plugin->setIcon( (*it)->icon() );
00556
00557 QVariant libNameProp = (*it)->property( "X-KDE-KontactPartLibraryName" );
00558 QVariant exeNameProp = (*it)->property( "X-KDE-KontactPartExecutableName" );
00559 QVariant loadOnStart = (*it)->property( "X-KDE-KontactPartLoadOnStart" );
00560 QVariant hasPartProp = (*it)->property( "X-KDE-KontactPluginHasPart" );
00561
00562 if ( !loadOnStart.isNull() && loadOnStart.toBool() )
00563 mDelayedPreload.append( plugin );
00564
00565 kdDebug(5600) << "LIBNAMEPART: " << libNameProp.toString() << endl;
00566
00567 plugin->setPartLibraryName( libNameProp.toString().utf8() );
00568 plugin->setExecutableName( exeNameProp.toString() );
00569 if ( hasPartProp.isValid() )
00570 plugin->setShowInSideBar( hasPartProp.toBool() );
00571
00572 for ( i = 0; i < plugins.count(); ++i ) {
00573 Plugin *p = plugins.at( i );
00574 if ( plugin->weight() < p->weight() )
00575 break;
00576 }
00577
00578 plugins.insert( i, plugin );
00579 }
00580
00581 for ( i = 0; i < plugins.count(); ++ i ) {
00582 Plugin *plugin = plugins.at( i );
00583
00584 KAction *action;
00585 QPtrList<KAction> *actionList = plugin->newActions();
00586
00587 for ( action = actionList->first(); action; action = actionList->next() ) {
00588 kdDebug(5600) << "Plugging " << action->name() << endl;
00589 action->plug( mNewActions->popupMenu() );
00590 if ( action->name() == plugin->identifier() ) {
00591 mPluginAction.insert( plugin, action );
00592 }
00593 }
00594
00595 if ( mSyncActionsEnabled ) {
00596 actionList = plugin->syncActions();
00597 for ( action = actionList->first(); action; action = actionList->next() ) {
00598 kdDebug(5600) << "Plugging " << action->name() << endl;
00599 action->plug( mSyncActions->popupMenu() );
00600 }
00601 }
00602 addPlugin( plugin );
00603 }
00604 updateShortcuts();
00605
00606 mNewActions->setEnabled( mPlugins.size() != 0 );
00607 if ( mSyncActionsEnabled )
00608 mSyncActions->setEnabled( mPlugins.size() != 0 );
00609 }
00610
00611 void MainWindow::unloadPlugins()
00612 {
00613 KPluginInfo::List::ConstIterator end = mPluginInfos.constEnd();
00614 KPluginInfo::List::ConstIterator it;
00615 for ( it = mPluginInfos.constBegin(); it != end; ++it ) {
00616 if ( !(*it)->isPluginEnabled() )
00617 removePlugin( *it );
00618 }
00619 }
00620
00621 void MainWindow::updateShortcuts()
00622 {
00623 QPtrList<KAction> loadedActions;
00624
00625 sortActionsByWeight();
00626
00627 QPtrListIterator<KAction> it( mActionPlugins );
00628 int i = 1;
00629 KAction *action;
00630 while ( ( action = it.current() ) != 0 ) {
00631 ++it;
00632 if ( isPluginLoadedByAction( action ) ) {
00633 loadedActions.append( action );
00634 QString shortcut = QString( "CTRL+%1" ).arg( i );
00635 action->setShortcut( KShortcut( shortcut ) );
00636 i++;
00637 } else {
00638 action->setShortcut( KShortcut() );
00639 }
00640 }
00641 unplugActionList( "navigator_actionlist" );
00642 factory()->plugActionList( this, QString( "navigator_actionlist" ), loadedActions );
00643 }
00644
00645 bool MainWindow::removePlugin( const KPluginInfo *info )
00646 {
00647 PluginList::Iterator end = mPlugins.end();
00648 for ( PluginList::Iterator it = mPlugins.begin(); it != end; ++it ) {
00649 if ( ( *it )->identifier() == info->pluginName() ) {
00650 Plugin *plugin = *it;
00651
00652 KAction *action;
00653 QPtrList<KAction> *actionList = plugin->newActions();
00654 for ( action = actionList->first(); action; action = actionList->next() ) {
00655 kdDebug(5600) << "Unplugging " << action->name() << endl;
00656 action->unplug( mNewActions->popupMenu() );
00657 }
00658
00659 if ( mSyncActionsEnabled ) {
00660 actionList = plugin->syncActions();
00661 for ( action = actionList->first(); action; action = actionList->next() ) {
00662 kdDebug(5600) << "Unplugging " << action->name() << endl;
00663 action->unplug( mSyncActions->popupMenu() );
00664 }
00665 }
00666 removeChildClient( plugin );
00667
00668 if ( mCurrentPlugin == plugin )
00669 mCurrentPlugin = 0;
00670
00671 plugin->deleteLater();
00672 mPlugins.remove( it );
00673
00674 if ( plugin->showInSideBar() ) {
00675 mPluginAction.remove( plugin );
00676 }
00677
00678 if ( mCurrentPlugin == 0 ) {
00679 PluginList::Iterator it;
00680 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00681 if ( (*it)->showInSideBar() ) {
00682 selectPlugin( *it );
00683 return true;
00684 }
00685 }
00686 }
00687 return true;
00688 }
00689 }
00690 return false;
00691 }
00692
00693 void MainWindow::addPlugin( Kontact::Plugin *plugin )
00694 {
00695 kdDebug(5600) << "Added plugin" << endl;
00696
00697 mPlugins.append( plugin );
00698
00699
00700 insertChildClient( plugin );
00701 }
00702
00703 void MainWindow::partLoaded( Kontact::Plugin*, KParts::ReadOnlyPart *part )
00704 {
00705
00706 if ( mPartsStack->id( part->widget() ) != -1 )
00707 return;
00708
00709 mPartsStack->addWidget( part->widget() );
00710
00711 mPartManager->addPart( part, false );
00712
00713 part->widget()->hide();
00714 }
00715
00716 void MainWindow::slotActivePartChanged( KParts::Part *part )
00717 {
00718 if ( !part ) {
00719 createGUI( 0 );
00720 return;
00721 }
00722
00723 kdDebug(5600) << "Part activated: " << part << " with stack id. "
00724 << mPartsStack->id( part->widget() )<< endl;
00725
00726
00727
00728 statusBar()->clear();
00729 }
00730
00731 void MainWindow::slotNewClicked()
00732 {
00733 KAction *action = mCurrentPlugin->newActions()->first();
00734 if ( action ) {
00735 action->activate();
00736 } else {
00737 PluginList::Iterator it;
00738 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00739 action = (*it)->newActions()->first();
00740 if ( action ) {
00741 action->activate();
00742 return;
00743 }
00744 }
00745 }
00746 }
00747
00748 void MainWindow::slotSyncClicked()
00749 {
00750 KAction *action = mCurrentPlugin->syncActions()->first();
00751 if ( action ) {
00752 action->activate();
00753 } else {
00754 PluginList::Iterator it;
00755 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00756 action = (*it)->syncActions()->first();
00757 if ( action ) {
00758 action->activate();
00759 return;
00760 }
00761 }
00762 }
00763 }
00764
00765 KToolBar* Kontact::MainWindow::findToolBar(const char* name)
00766 {
00767
00768 return static_cast<KToolBar *>(child(name, "KToolBar"));
00769 }
00770
00771 void MainWindow::slotActionTriggered()
00772 {
00773 const KAction *actionSender = static_cast<const KAction*>( sender() );
00774 QString identifier = actionSender->name();
00775 if ( !identifier.isEmpty() ) {
00776 selectPlugin( identifier );
00777 }
00778 }
00779
00780 void MainWindow::selectPlugin( Kontact::Plugin *plugin )
00781 {
00782 if ( !plugin )
00783 return;
00784
00785 if ( plugin->isRunningStandalone() ) {
00786 statusBar()->message( i18n( "Application is running standalone. Foregrounding..." ), 1000 );
00787 mSidePane->indicateForegrunding( plugin );
00788 plugin->bringToForeground();
00789 return;
00790 }
00791
00792 KApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
00793
00794 KParts::Part *part = plugin->part();
00795
00796 if ( !part ) {
00797 KApplication::restoreOverrideCursor();
00798 KMessageBox::error( this, i18n( "Cannot load part for %1." )
00799 .arg( plugin->title() )
00800 + "\n" + lastErrorMessage() );
00801 plugin->setDisabled( true );
00802 mSidePane->updatePlugins();
00803 return;
00804 }
00805
00806
00807 QWidget *focusWidget = kapp->focusWidget();
00808 if ( mCurrentPlugin && focusWidget ) {
00809
00810 QWidget *parent = focusWidget->parentWidget();
00811 while ( parent ) {
00812 if ( parent == mCurrentPlugin->part()->widget() )
00813 mFocusWidgets.insert( mCurrentPlugin->identifier(), QGuardedPtr<QWidget>( focusWidget ) );
00814
00815 parent = parent->parentWidget();
00816 }
00817 }
00818
00819 if ( mSidePane ) {
00820 mSidePane->selectPlugin( plugin->identifier() );
00821 }
00822
00823 plugin->select();
00824
00825 mPartManager->setActivePart( part );
00826 QWidget *view = part->widget();
00827 Q_ASSERT( view );
00828
00829 if ( view ) {
00830 mPartsStack->raiseWidget( view );
00831 view->show();
00832
00833 if ( mFocusWidgets.contains( plugin->identifier() ) ) {
00834 focusWidget = mFocusWidgets[ plugin->identifier() ];
00835 if ( focusWidget )
00836 focusWidget->setFocus();
00837 } else
00838 view->setFocus();
00839
00840 mCurrentPlugin = plugin;
00841 KAction *newAction = plugin->newActions()->first();
00842 KAction *syncAction = plugin->syncActions()->first();
00843
00844 createGUI( plugin->part() );
00845
00846 KToolBar* navigatorToolBar = findToolBar( "navigatorToolBar" );
00847
00848 if ( navigatorToolBar && !navigatorToolBar->isHidden() &&
00849 navigatorToolBar->barPos() == KToolBar::Top ) {
00850 topDock()->moveDockWindow( navigatorToolBar, -1 );
00851 }
00852
00853 setCaption( i18n( "Plugin dependent window title" ,"%1 - Kontact" ).arg( plugin->title() ) );
00854
00855 if ( newAction ) {
00856 mNewActions->setIcon( newAction->icon() );
00857 mNewActions->setText( newAction->text() );
00858 } else {
00859 PluginList::Iterator it;
00860 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00861 newAction = (*it)->newActions()->first();
00862 if ( newAction ) {
00863 mNewActions->setIcon( newAction->icon() );
00864 mNewActions->setText( newAction->text() );
00865 break;
00866 }
00867 }
00868 }
00869 if ( mSyncActionsEnabled ) {
00870 if ( syncAction ) {
00871 mSyncActions->setIcon( syncAction->icon() );
00872 mSyncActions->setText( syncAction->text() );
00873 } else {
00874 PluginList::Iterator it;
00875 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
00876 syncAction = (*it)->syncActions()->first();
00877 if ( syncAction ) {
00878 mSyncActions->setIcon( syncAction->icon() );
00879 mSyncActions->setText( syncAction->text() );
00880 break;
00881 }
00882 }
00883 }
00884 }
00885 }
00886 QStringList invisibleActions = plugin->invisibleToolbarActions();
00887
00888 QStringList::ConstIterator it;
00889 for ( it = invisibleActions.begin(); it != invisibleActions.end(); ++it ) {
00890 KAction *action = part->actionCollection()->action( (*it).latin1() );
00891 if ( action ) {
00892 QPtrListIterator<KToolBar> it( toolBarIterator() );
00893 for ( ; it.current() ; ++it ) {
00894 action->unplug( it.current() );
00895 }
00896 }
00897 }
00898
00899 KApplication::restoreOverrideCursor();
00900 }
00901
00902 void MainWindow::selectPlugin( const QString &pluginName )
00903 {
00904 PluginList::ConstIterator end = mPlugins.end();
00905 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it )
00906 if ( ( *it )->identifier() == pluginName ) {
00907 selectPlugin( *it );
00908 return;
00909 }
00910 }
00911
00912 void MainWindow::loadSettings()
00913 {
00914 if ( mSplitter )
00915 mSplitter->setSizes( Prefs::self()->mSidePaneSplitter );
00916
00917
00918 PluginList::ConstIterator it;
00919 for ( it = mDelayedPreload.begin(); it != mDelayedPreload.end(); ++it )
00920 selectPlugin( *it );
00921
00922 selectPlugin( Prefs::self()->mActivePlugin );
00923 }
00924
00925 void MainWindow::saveSettings()
00926 {
00927 if ( mSplitter )
00928 Prefs::self()->mSidePaneSplitter = mSplitter->sizes();
00929
00930 if ( mCurrentPlugin )
00931 Prefs::self()->mActivePlugin = mCurrentPlugin->identifier();
00932 }
00933
00934 void MainWindow::slotShowTip()
00935 {
00936 showTip( true );
00937 }
00938
00939 void MainWindow::slotShowIntroduction()
00940 {
00941 mPartsStack->raiseWidget( 0 );
00942 }
00943
00944 void MainWindow::showTip( bool force )
00945 {
00946 QStringList tips;
00947 PluginList::ConstIterator end = mPlugins.end();
00948 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it ) {
00949 QString file = (*it)->tipFile();
00950 if ( !file.isEmpty() )
00951 tips.append( file );
00952 }
00953
00954 KTipDialog::showMultiTip( this, tips, force );
00955 }
00956
00957 void MainWindow::slotQuit()
00958 {
00959 mReallyClose = true;
00960 close();
00961 }
00962
00963 void MainWindow::slotPreferences()
00964 {
00965 static SettingsDialogWrapper *dlg = 0;
00966 if ( !dlg ) {
00967
00968 QValueList<KPluginInfo*> filteredPlugins = mPluginInfos;
00969 PluginList::ConstIterator it;
00970 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it )
00971 if ( (*it)->isRunningStandalone() ) {
00972 QValueList<KPluginInfo*>::ConstIterator infoIt;
00973 for ( infoIt = filteredPlugins.begin(); infoIt != filteredPlugins.end(); ++infoIt ) {
00974 if ( (*infoIt)->pluginName() == (*it)->identifier() ) {
00975 filteredPlugins.remove( *infoIt );
00976 break;
00977 }
00978 }
00979 }
00980 dlg = new SettingsDialogWrapper( KSettings::Dialog::Configurable, this );
00981 dlg->addPluginInfos( filteredPlugins );
00982 connect( dlg, SIGNAL( pluginSelectionChanged() ),
00983 SLOT( pluginsChanged() ) );
00984 }
00985
00986 dlg->show();
00987 dlg->fixButtonLabel( this );
00988 }
00989
00990 int MainWindow::startServiceFor( const QString& serviceType,
00991 const QString& constraint,
00992 const QString& preferences,
00993 QString *error, QCString* dcopService,
00994 int flags )
00995 {
00996 PluginList::ConstIterator end = mPlugins.end();
00997 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it ) {
00998 if ( (*it)->createDCOPInterface( serviceType ) ) {
00999 kdDebug(5600) << "found interface for " << serviceType << endl;
01000 if ( dcopService )
01001 *dcopService = (*it)->dcopClient()->appId();
01002 kdDebug(5600) << "appId=" << (*it)->dcopClient()->appId() << endl;
01003 return 0;
01004 }
01005 }
01006
01007 kdDebug(5600) <<
01008 "Didn't find dcop interface, falling back to external process" << endl;
01009
01010 return KDCOPServiceStarter::startServiceFor( serviceType, constraint,
01011 preferences, error, dcopService, flags );
01012 }
01013
01014 void MainWindow::pluginsChanged()
01015 {
01016 unloadPlugins();
01017 loadPlugins();
01018 mSidePane->updatePlugins();
01019 updateShortcuts();
01020 }
01021
01022 void MainWindow::updateConfig()
01023 {
01024 kdDebug( 5600 ) << k_funcinfo << endl;
01025
01026 saveSettings();
01027 loadSettings();
01028 }
01029
01030 void MainWindow::showAboutDialog()
01031 {
01032 KApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
01033
01034 if ( !mAboutDialog )
01035 mAboutDialog = new AboutDialog( this );
01036
01037 mAboutDialog->show();
01038 mAboutDialog->raise();
01039 KApplication::restoreOverrideCursor();
01040 }
01041
01042 void MainWindow::configureShortcuts()
01043 {
01044 KKeyDialog dialog( true, this );
01045 dialog.insert( actionCollection() );
01046
01047 if ( mCurrentPlugin && mCurrentPlugin->part() )
01048 dialog.insert( mCurrentPlugin->part()->actionCollection() );
01049
01050 dialog.configure();
01051 }
01052
01053 void MainWindow::configureToolbars()
01054 {
01055 saveMainWindowSettings( KGlobal::config(), "MainWindow" );
01056
01057 KEditToolbar edit( factory() );
01058 connect( &edit, SIGNAL( newToolbarConfig() ),
01059 this, SLOT( slotNewToolbarConfig() ) );
01060 edit.exec();
01061 }
01062
01063 void MainWindow::slotNewToolbarConfig()
01064 {
01065 if ( mCurrentPlugin && mCurrentPlugin->part() ) {
01066 createGUI( mCurrentPlugin->part() );
01067 }
01068 if ( mCurrentPlugin ) {
01069 applyMainWindowSettings( KGlobal::config(), "MainWindow" );
01070 }
01071 updateShortcuts();
01072 }
01073
01074 void MainWindow::slotOpenUrl( const KURL &url )
01075 {
01076 if ( url.protocol() == "exec" ) {
01077 if ( url.path() == "/switch" ) {
01078 selectPlugin( mCurrentPlugin );
01079 }
01080 if ( url.path() == "/gwwizard" ) {
01081 KRun::runCommand( "groupwarewizard" );
01082 slotQuit();
01083 }
01084 if ( url.path().startsWith( "/help" ) ) {
01085 QString app( "kontact" );
01086 if ( !url.query().isEmpty() ) {
01087 app = url.query().mid( 1 );
01088 }
01089 kapp->invokeHelp( QString::null, app );
01090 }
01091 } else {
01092 new KRun( url, this );
01093 }
01094 }
01095
01096 void MainWindow::readProperties( KConfig *config )
01097 {
01098 Core::readProperties( config );
01099
01100 QStringList activePlugins = config->readListEntry( "ActivePlugins" );
01101 QValueList<Plugin*>::ConstIterator it = mPlugins.begin();
01102 QValueList<Plugin*>::ConstIterator end = mPlugins.end();
01103 for ( ; it != end; ++it ) {
01104 Plugin *plugin = *it;
01105 if ( !plugin->isRunningStandalone() ) {
01106 QStringList::ConstIterator activePlugin = activePlugins.find( plugin->identifier() );
01107 if ( activePlugin != activePlugins.end() ) {
01108 plugin->readProperties( config );
01109 }
01110 }
01111 }
01112 }
01113
01114 void MainWindow::saveProperties( KConfig *config )
01115 {
01116 Core::saveProperties( config );
01117
01118 QStringList activePlugins;
01119
01120 KPluginInfo::List::Iterator it = mPluginInfos.begin();
01121 KPluginInfo::List::Iterator end = mPluginInfos.end();
01122 for ( ; it != end; ++it ) {
01123 KPluginInfo *info = *it;
01124 if ( info->isPluginEnabled() ) {
01125 Plugin *plugin = pluginFromInfo( info );
01126 if ( plugin ) {
01127 activePlugins.append( plugin->identifier() );
01128 plugin->saveProperties( config );
01129 }
01130 }
01131 }
01132
01133 config->writeEntry( "ActivePlugins", activePlugins );
01134 }
01135
01136 bool MainWindow::queryClose()
01137 {
01138 if ( kapp->sessionSaving() || mReallyClose )
01139 return true;
01140
01141 bool localClose = true;
01142 QValueList<Plugin*>::ConstIterator end = mPlugins.end();
01143 QValueList<Plugin*>::ConstIterator it = mPlugins.begin();
01144 for ( ; it != end; ++it ) {
01145 Plugin *plugin = *it;
01146 if ( !plugin->isRunningStandalone() )
01147 if ( !plugin->queryClose() )
01148 localClose = false;
01149 }
01150
01151 return localClose;
01152 }
01153
01154 void MainWindow::slotShowStatusMsg( const QString &msg )
01155 {
01156 if ( !statusBar() || !mStatusMsgLabel )
01157 return;
01158
01159 mStatusMsgLabel->setText( msg );
01160 }
01161
01162 QString MainWindow::introductionString()
01163 {
01164 KIconLoader *iconloader = KGlobal::iconLoader();
01165 int iconSize = iconloader->currentSize( KIcon::Desktop );
01166
01167 QString handbook_icon_path = iconloader->iconPath( "contents2", KIcon::Desktop );
01168 QString html_icon_path = iconloader->iconPath( "html", KIcon::Desktop );
01169 QString wizard_icon_path = iconloader->iconPath( "wizard", KIcon::Desktop );
01170
01171 QString info = i18n( "<h2 style='text-align:center; margin-top: 0px;'>Welcome to Kontact %1</h2>"
01172 "<p>%1</p>"
01173 "<table align=\"center\">"
01174 "<tr><td><a href=\"%1\"><img width=\"%1\" height=\"%1\" src=\"%1\" /></a></td>"
01175 "<td><a href=\"%1\">%1</a><br><span id=\"subtext\"><nobr>%1</td></tr>"
01176 "<tr><td><a href=\"%1\"><img width=\"%1\" height=\"%1\" src=\"%1\" /></a></td>"
01177 "<td><a href=\"%1\">%1</a><br><span id=\"subtext\"><nobr>%1</td></tr>"
01178 "<tr><td><a href=\"%1\"><img width=\"%1\" height=\"%1\" src=\"%1\" /></a></td>"
01179 "<td><a href=\"%1\">%1</a><br><span id=\"subtext\"><nobr>%1</td></tr>"
01180 "</table>"
01181 "<p style=\"margin-bottom: 0px\"> <a href=\"%1\">Skip this introduction</a></p>" )
01182 .arg( kapp->aboutData()->version() )
01183 .arg( i18n( "Kontact handles your e-mail, addressbook, calendar, to-do list and more." ) )
01184 .arg( "exec:/help?kontact" )
01185 .arg( iconSize )
01186 .arg( iconSize )
01187 .arg( handbook_icon_path )
01188 .arg( "exec:/help?kontact" )
01189 .arg( i18n( "Read Manual" ) )
01190 .arg( i18n( "Learn more about Kontact and its components" ) )
01191 .arg( "http://kontact.org" )
01192 .arg( iconSize )
01193 .arg( iconSize )
01194 .arg( html_icon_path )
01195 .arg( "http://kontact.org" )
01196 .arg( i18n( "Visit Kontact Website" ) )
01197 .arg( i18n( "Access online resources and tutorials" ) )
01198 .arg( "exec:/gwwizard" )
01199 .arg( iconSize )
01200 .arg( iconSize )
01201 .arg( wizard_icon_path )
01202 .arg( "exec:/gwwizard" )
01203 .arg( i18n( "Configure Kontact as Groupware Client" ) )
01204 .arg( i18n( "Prepare Kontact for use in corporate networks" ) )
01205 .arg( "exec:/switch" );
01206 return info;
01207 }
01208
01209 #include "mainwindow.moc"