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