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