kontact

mainwindow.cpp
1/*
2 This file is part of KDE Kontact.
3
4 Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org>
5 Copyright (c) 2002-2005 Daniel Molkentin <molkentin@kde.org>
6 Copyright (c) 2003-2005 Cornelius Schumacher <schumacher@kde.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21*/
22
23#include <tqaction.h>
24#include <tqcombobox.h>
25#include <tqdockarea.h>
26#include <tqguardedptr.h>
27#include <tqhbox.h>
28#include <tqimage.h>
29#include <tqobjectlist.h>
30#include <tqprogressbar.h>
31#include <tqpushbutton.h>
32#include <tqsplitter.h>
33#include <tqtimer.h>
34#include <tqwhatsthis.h>
35
36#include <dcopclient.h>
37#include <tdeapplication.h>
38#include <tdeconfig.h>
39#include <kdebug.h>
40#include <kedittoolbar.h>
41#include <kguiitem.h>
42#include <khelpmenu.h>
43#include <kiconloader.h>
44#include <kkeydialog.h>
45#include <klibloader.h>
46#include <tdelistbox.h>
47#include <tdelocale.h>
48#include <tdemessagebox.h>
49#include <tdeparts/componentfactory.h>
50#include <kplugininfo.h>
51#include <tdepopupmenu.h>
52#include <ksettings/dialog.h>
53#include <ksettings/dispatcher.h>
54#include <tdeshortcut.h>
55#include <tdestandarddirs.h>
56#include <kstatusbar.h>
57#include <kstdaction.h>
58#include <ktip.h>
59#include <ktrader.h>
60#include <ksettings/componentsdialog.h>
61#include <kstringhandler.h>
62#include <krsqueezedtextlabel.h>
63#include <tdehtml_part.h>
64#include <tdehtmlview.h>
65#include <libtdepim/tdefileio.h>
66#include <kcursor.h>
67#include <krun.h>
68#include <tdeaboutdata.h>
69#include <tdemenubar.h>
70#include <tdestdaccel.h>
71#include <kcmultidialog.h>
72#include <kipc.h>
73
74#include "aboutdialog.h"
75#include "iconsidepane.h"
76#include "mainwindow.h"
77#include "plugin.h"
78#include "prefs.h"
79#include "profiledialog.h"
80#include "profilemanager.h"
81#include "progressdialog.h"
82#include "statusbarprogresswidget.h"
83#include "broadcaststatus.h"
84
85using namespace Kontact;
86
87class SettingsDialogWrapper : public KSettings::Dialog
88{
89 public:
90 SettingsDialogWrapper( ContentInListView content, TQWidget * parent = 0 )
91 : KSettings::Dialog( content, parent, 0 )
92 {
93 }
94
95
96 void fixButtonLabel( TQWidget *widget )
97 {
98 TQObject *object = widget->child( "KJanusWidget::buttonBelowList" );
99 TQPushButton *button = static_cast<TQPushButton*>( object );
100 if ( button )
101 button->setText( i18n( "Select Components ..." ) );
102 }
103};
104
105MainWindow::MainWindow()
106 : Kontact::Core(), mTopWidget( 0 ), mSplitter( 0 ),
107 mCurrentPlugin( 0 ), mAboutDialog( 0 ), mReallyClose( false ), mSyncActionsEnabled( true )
108{
109 // Set this to be the group leader for all subdialogs - this means
110 // modal subdialogs will only affect this dialog, not the other windows
111 setWFlags( getWFlags() | WGroupLeader );
112
113 initGUI();
114 initObject();
115}
116
117void MainWindow::initGUI()
118{
119 initWidgets();
120 setupActions();
121 setHelpMenuEnabled( false );
122 KHelpMenu *helpMenu = new KHelpMenu( this, 0, true, actionCollection() );
123 connect( helpMenu, TQ_SIGNAL( showAboutApplication() ),
124 TQ_SLOT( showAboutDialog() ) );
125
126 TDETrader::OfferList offers = TDETrader::self()->query(
127 TQString::fromLatin1( "Kontact/Plugin" ),
128 TQString( "[X-TDE-KontactPluginVersion] == %1" ).arg( KONTACT_PLUGIN_VERSION ) );
129 mPluginInfos = KPluginInfo::fromServices( offers, Prefs::self()->config(), "Plugins" );
130
131 KPluginInfo::List::Iterator it;
132 for ( it = mPluginInfos.begin(); it != mPluginInfos.end(); ++it ) {
133 (*it)->load();
134
135 TDEAction *action = new TDEAction( (*it)->name(), (*it)->icon(), TDEShortcut(),
136 this, TQ_SLOT(slotActionTriggered()),
137 actionCollection(), (*it)->pluginName().latin1() );
138 action->setName( (*it)->pluginName().latin1() );
139 action->setWhatsThis( i18n( "Switch to plugin %1" ).arg( (*it)->name() ) );
140
141 TQVariant hasPartProp = (*it)->property( "X-TDE-KontactPluginHasPart" );
142 if ( !hasPartProp.isValid() || hasPartProp.toBool() ) {
143 mActionPlugins.append( action );
144 }
145 }
146
147 KStdAction::keyBindings( this, TQ_SLOT( configureShortcuts() ), actionCollection() );
148 KStdAction::configureToolbars( this, TQ_SLOT( configureToolbars() ), actionCollection() );
149 setXMLFile( "kontactui.rc" );
150
151 setStandardToolBarMenuEnabled( true );
152
153 createGUI( 0 );
154
155 loadPlugins();
156
157 resize( 700, 520 ); // initial size to prevent a scrollbar in sidepane
158 setAutoSaveSettings();
159
160 connect( Kontact::ProfileManager::self(), TQ_SIGNAL( profileLoaded( const TQString& ) ),
161 this, TQ_SLOT( slotLoadProfile( const TQString& ) ) );
162 connect( Kontact::ProfileManager::self(), TQ_SIGNAL( saveToProfileRequested( const TQString& ) ),
163 this, TQ_SLOT( slotSaveToProfile( const TQString& ) ) );
164}
165
166
167void MainWindow::initObject()
168{
169 // prepare the part manager
170 mPartManager = new KParts::PartManager( this );
171 connect( mPartManager, TQ_SIGNAL( activePartChanged( KParts::Part* ) ),
172 this, TQ_SLOT( slotActivePartChanged( KParts::Part* ) ) );
173
174 if ( mSidePane ) {
175 mSidePane->updatePlugins();
176 }
177
178 KSettings::Dispatcher::self()->registerInstance( instance(), this,
179 TQ_SLOT( updateConfig() ) );
180
181 loadSettings();
182
183 statusBar()->show();
184
185 showTip( false );
186
187 // done initializing
188 slotShowStatusMsg( TQString() );
189
190 connect( KPIM::BroadcastStatus::instance(), TQ_SIGNAL( statusMsg( const TQString& ) ),
191 this, TQ_SLOT( slotShowStatusMsg( const TQString& ) ) );
192
193 // launch commandline specified module if any
194 activatePluginModule();
195
196 if ( Prefs::lastVersionSeen() == tdeApp->aboutData()->version() ) {
197 selectPlugin( mCurrentPlugin );
198 }
199
200 paintAboutScreen( introductionString() );
201 Prefs::setLastVersionSeen( tdeApp->aboutData()->version() );
202}
203
204MainWindow::~MainWindow()
205{
206 saveSettings();
207
208 TQPtrList<KParts::Part> parts = *mPartManager->parts();
209
210 for ( KParts::Part *p = parts.last(); p; p = parts.prev() ) {
211 delete p;
212 p = 0;
213 }
214
215 Prefs::self()->writeConfig();
216}
217
218void MainWindow::setActivePluginModule( const TQString &module )
219{
220 mActiveModule = module;
221 activatePluginModule();
222}
223
224void MainWindow::activatePluginModule()
225{
226 if ( !mActiveModule.isEmpty() ) {
227 PluginList::ConstIterator end = mPlugins.end();
228 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it )
229 if ( ( *it )->identifier().contains( mActiveModule ) ) {
230 selectPlugin( *it );
231 return;
232 }
233 }
234}
235
236void MainWindow::initWidgets()
237{
238 // includes sidebar and part stack
239 mTopWidget = new TQHBox( this );
240 mTopWidget->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
241 setCentralWidget( mTopWidget );
242
243 TQHBox *mBox = 0;
244 mSplitter = new TQSplitter( mTopWidget );
245 mBox = new TQHBox( mTopWidget );
246 mSidePane = new IconSidePane( this, mSplitter );
247 mSidePane->setSizePolicy( TQSizePolicy( TQSizePolicy::Maximum,
248 TQSizePolicy::Preferred ) );
249 // donÄt occupy screen estate on load
250 TQValueList<int> sizes;
251 sizes << 0;
252 mSplitter->setSizes(sizes);
253
254 connect( mSidePane, TQ_SIGNAL( pluginSelected( Kontact::Plugin * ) ),
255 TQ_SLOT( selectPlugin( Kontact::Plugin * ) ) );
256
257 TQVBox *vBox;
258 if ( mSplitter ) {
259 vBox = new TQVBox( mSplitter );
260 } else {
261 vBox = new TQVBox( mBox );
262 }
263
264 vBox->setSpacing( 0 );
265
266 mPartsStack = new TQWidgetStack( vBox );
267 initAboutScreen();
268
269 TQString loading = i18n( "<h2 style='text-align:center; margin-top: 0px; margin-bottom: 0px'>%1</h2>" )
270 .arg( i18n("Loading Kontact...") );
271
272 paintAboutScreen( loading );
273
274 /* Create a progress dialog and hide it. */
275 KPIM::ProgressDialog *progressDialog = new KPIM::ProgressDialog( statusBar(), this );
276 progressDialog->hide();
277
278 mLittleProgress = new KPIM::StatusbarProgressWidget( progressDialog, statusBar() );
279
280 mStatusMsgLabel = new KRSqueezedTextLabel( i18n( " Initializing..." ), statusBar() );
281 mStatusMsgLabel->setAlignment( AlignLeft | AlignVCenter );
282
283 statusBar()->addWidget( mStatusMsgLabel, 10 , false );
284 statusBar()->addWidget( mLittleProgress, 0 , true );
285 mLittleProgress->show();
286}
287
288
289void MainWindow::paintAboutScreen( const TQString& msg )
290{
291 TQString location = locate( "data", "kontact/about/main.html" );
292 TQString content = KPIM::kFileToString( location );
293 content = content.arg( locate( "data", "libtdepim/about/kde_infopage.css" ) );
294 if ( tdeApp->reverseLayout() )
295 content = content.arg( "@import \"%1\";" ).arg( locate( "data", "libtdepim/about/kde_infopage_rtl.css" ) );
296 else
297 content = content.arg( "" );
298
299 mIntroPart->begin( KURL( location ) );
300
301 TQString appName( i18n( "TDE Kontact" ) );
302 TQString catchPhrase( i18n( "Get Organized!" ) );
303 TQString quickDescription( i18n( "The TDE Personal Information Management Suite" ) );
304
305 mIntroPart->write( content.arg( TQFont().pointSize() + 2 ).arg( appName )
306 .arg( catchPhrase ).arg( quickDescription ).arg( msg ) );
307 mIntroPart->end();
308}
309
310void MainWindow::initAboutScreen()
311{
312 TQHBox *introbox = new TQHBox( mPartsStack );
313 mPartsStack->addWidget( introbox );
314 mPartsStack->raiseWidget( introbox );
315 mIntroPart = new TDEHTMLPart( introbox );
316 mIntroPart->widget()->setFocusPolicy( TQWidget::WheelFocus );
317 // Let's better be paranoid and disable plugins (it defaults to enabled):
318 mIntroPart->setPluginsEnabled( false );
319 mIntroPart->setJScriptEnabled( false ); // just make this explicit
320 mIntroPart->setJavaEnabled( false ); // just make this explicit
321 mIntroPart->setMetaRefreshEnabled( false );
322 mIntroPart->setURLCursor( KCursor::handCursor() );
323 mIntroPart->view()->setLineWidth( 0 );
324
325 connect( mIntroPart->browserExtension(),
326 TQ_SIGNAL( openURLRequest( const KURL&, const KParts::URLArgs& ) ),
327 TQ_SLOT( slotOpenUrl( const KURL& ) ) );
328
329 connect( mIntroPart->browserExtension(),
330 TQ_SIGNAL( createNewWindow( const KURL&, const KParts::URLArgs& ) ),
331 TQ_SLOT( slotOpenUrl( const KURL& ) ) );
332}
333
334void MainWindow::setupActions()
335{
336 KStdAction::quit( this, TQ_SLOT( slotQuit() ), actionCollection() );
337 mNewActions = new TDEToolBarPopupAction( KGuiItem( i18n( "New" ), "" ),
338 TDEStdAccel::shortcut(TDEStdAccel::New), this, TQ_SLOT( slotNewClicked() ),
339 actionCollection(), "action_new" );
340
341 TDEConfig* const cfg = Prefs::self()->config();
342 cfg->setGroup( "Kontact Groupware Settings" );
343 mSyncActionsEnabled = cfg->readBoolEntry( "GroupwareMailFoldersEnabled", true );
344
345 if ( mSyncActionsEnabled ) {
346 mSyncActions = new TDEToolBarPopupAction( KGuiItem( i18n( "Synchronize" ) ),
347 TDEStdAccel::shortcut(TDEStdAccel::Reload), this, TQ_SLOT( slotSyncClicked() ),
348 actionCollection(), "action_sync" );
349 }
350 new TDEAction( i18n( "Configure Kontact..." ), "configure", 0, this, TQ_SLOT( slotPreferences() ),
351 actionCollection(), "settings_configure_kontact" );
352
353 new TDEAction( i18n( "Configure &Profiles..." ), 0, this, TQ_SLOT( slotConfigureProfiles() ),
354 actionCollection(), "settings_configure_kontact_profiles" );
355
356 new TDEAction( i18n( "&Kontact Introduction" ), 0, this, TQ_SLOT( slotShowIntroduction() ),
357 actionCollection(), "help_introduction" );
358 new TDEAction( i18n( "&Tip of the Day" ), 0, this, TQ_SLOT( slotShowTip() ),
359 actionCollection(), "help_tipofday" );
360
361 KWidgetAction* spacerAction = new KWidgetAction( new TQWidget( this ), "SpacerAction", "", 0, 0, actionCollection(), "navigator_spacer_item" );
362 spacerAction->setAutoSized( true );
363}
364
365void MainWindow::slotConfigureProfiles()
366{
367 TQGuardedPtr<Kontact::ProfileDialog> dlg = new Kontact::ProfileDialog( this );
368 dlg->setModal( true );
369 dlg->exec();
370 delete dlg;
371}
372
373namespace {
374 void copyConfigEntry( TDEConfig* source, TDEConfig* dest, const TQString& group, const TQString& key, const TQString& defaultValue=TQString() )
375 {
376 source->setGroup( group );
377 dest->setGroup( group );
378 dest->writeEntry( key, source->readEntry( key, defaultValue ) );
379 }
380}
381
382void MainWindow::slotSaveToProfile( const TQString& id )
383{
384 const TQString path = Kontact::ProfileManager::self()->profileById( id ).saveLocation();
385 if ( path.isNull() )
386 return;
387
388 TDEConfig* const cfg = Prefs::self()->config();
389 Prefs::self()->writeConfig();
390 saveMainWindowSettings( cfg );
391 saveSettings();
392
393 TDEConfig profile( path+"/kontactrc", /*read-only=*/false, /*useglobals=*/false );
394 ::copyConfigEntry( cfg, &profile, "MainWindow Toolbar navigatorToolBar", "Hidden", "true" );
395 ::copyConfigEntry( cfg, &profile, "View", "SidePaneSplitter" );
396 ::copyConfigEntry( cfg, &profile, "Icons", "Theme" );
397
398 for ( PluginList::Iterator it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
399 if ( !(*it)->isRunningStandalone() ) {
400 (*it)->part();
401 }
402 (*it)->saveToProfile( path );
403 }
404}
405
406void MainWindow::slotLoadProfile( const TQString& id )
407{
408 const TQString path = Kontact::ProfileManager::self()->profileById( id ).saveLocation();
409 if ( path.isNull() )
410 return;
411
412 TDEConfig* const cfg = Prefs::self()->config();
413 Prefs::self()->writeConfig();
414 saveMainWindowSettings( cfg );
415 saveSettings();
416
417 const TDEConfig profile( path+"/kontactrc", /*read-only=*/false, /*useglobals=*/false );
418 const TQStringList groups = profile.groupList();
419 for ( TQStringList::ConstIterator it = groups.begin(), end = groups.end(); it != end; ++it )
420 {
421 cfg->setGroup( *it );
422 typedef TQMap<TQString, TQString> StringMap;
423 const StringMap entries = profile.entryMap( *it );
424 for ( StringMap::ConstIterator it2 = entries.begin(), end = entries.end(); it2 != end; ++it2 )
425 {
426 if ( it2.data() == "KONTACT_PROFILE_DELETE_KEY" )
427 cfg->deleteEntry( it2.key() );
428 else
429 cfg->writeEntry( it2.key(), it2.data() );
430 }
431 }
432
433 cfg->sync();
434 Prefs::self()->readConfig();
435 applyMainWindowSettings( cfg );
436 TDEIconTheme::reconfigure();
437 const WId wid = winId();
438 KIPC::sendMessage( KIPC::PaletteChanged, wid );
439 KIPC::sendMessage( KIPC::FontChanged, wid );
440 KIPC::sendMessage( KIPC::StyleChanged, wid );
441 KIPC::sendMessage( KIPC::SettingsChanged, wid );
442 for ( int i = 0; i < TDEIcon::LastGroup; ++i )
443 KIPC::sendMessage( KIPC::IconChanged, wid, i );
444
445 loadSettings();
446
447 for ( PluginList::Iterator it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
448 if ( !(*it)->isRunningStandalone() ) {
449 kdDebug() << "Ensure loaded: " << (*it)->identifier() << endl;
450 (*it)->part();
451 }
452 (*it)->loadProfile( path );
453 }
454}
455
456bool MainWindow::isPluginLoaded( const KPluginInfo *info )
457{
458 return (pluginFromInfo( info ) != 0);
459}
460
461Plugin *MainWindow::pluginFromInfo( const KPluginInfo *info )
462{
463 PluginList::ConstIterator end = mPlugins.end();
464 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it )
465 if ( (*it)->identifier() == info->pluginName() )
466 return *it;
467
468 return 0;
469}
470
471Plugin *MainWindow::pluginFromAction( const TDEAction *action )
472{
473 PluginList::ConstIterator end = mPlugins.end();
474 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it ) {
475 if ( (*it)->identifier() == action->name() ) {
476 return *it;
477 }
478 }
479 return 0;
480}
481
482bool MainWindow::isPluginLoadedByAction( const TDEAction *action )
483{
484 KPluginInfo::List::ConstIterator it;
485 for ( it = mPluginInfos.begin(); it != mPluginInfos.end(); ++it ) {
486 if ( !(*it)->isPluginEnabled() )
487 continue;
488 if ( isPluginLoaded( *it ) ) {
489 Plugin *plugin = pluginFromInfo( *it );
490 if ( plugin ) {
491 if ( plugin->identifier() == action->name() ) {
492 return true;
493 }
494 }
495 }
496 }
497 return false;
498}
499
500void MainWindow::sortActionsByWeight()
501{
502 TQPtrList<TDEAction> sorted;
503
504 TQPtrListIterator<TDEAction> eit( mActionPlugins );
505 TDEAction *action;
506 while ( ( action = eit.current() ) != 0 ) {
507 ++eit;
508 TQPtrListIterator<TDEAction> sortIt( sorted );
509 uint at = 0;
510 TDEAction *saction;
511 Plugin *p1 = pluginFromAction( action );
512 while ( ( saction = sortIt.current() ) != 0 ) {
513 Plugin *p2 = pluginFromAction( saction );
514 if ( p1 && p2 && p1->weight() >= p2->weight() ) {
515 ++sortIt;
516 ++at;
517 } else {
518 break;
519 }
520 }
521 sorted.insert( at, action );
522 }
523 mActionPlugins = sorted;
524}
525
526void MainWindow::loadPlugins()
527{
528 TQPtrList<Plugin> plugins;
529 TQPtrList<KParts::Part> loadDelayed;
530
531 uint i;
532 KPluginInfo::List::ConstIterator it;
533 for ( it = mPluginInfos.begin(); it != mPluginInfos.end(); ++it ) {
534 if ( !(*it)->isPluginEnabled() )
535 continue;
536 if ( isPluginLoaded( *it ) ) {
537 Plugin *plugin = pluginFromInfo( *it );
538 if ( plugin )
539 plugin->configUpdated();
540 continue;
541 }
542
543 kdDebug(5600) << "Loading Plugin: " << (*it)->name() << endl;
544 Kontact::Plugin *plugin =
545 KParts::ComponentFactory::createInstanceFromService<Kontact::Plugin>(
546 (*it)->service(), this );
547
548 if ( !plugin )
549 continue;
550
551 plugin->setIdentifier( (*it)->pluginName() );
552 plugin->setTitle( (*it)->name() );
553 plugin->setIcon( (*it)->icon() );
554
555 TQVariant libNameProp = (*it)->property( "X-TDE-KontactPartLibraryName" );
556 TQVariant exeNameProp = (*it)->property( "X-TDE-KontactPartExecutableName" );
557 TQVariant loadOnStart = (*it)->property( "X-TDE-KontactPartLoadOnStart" );
558 TQVariant hasPartProp = (*it)->property( "X-TDE-KontactPluginHasPart" );
559
560 if ( !loadOnStart.isNull() && loadOnStart.toBool() )
561 mDelayedPreload.append( plugin );
562
563 kdDebug(5600) << "LIBNAMEPART: " << libNameProp.toString() << endl;
564
565 plugin->setPartLibraryName( libNameProp.toString().utf8() );
566 plugin->setExecutableName( exeNameProp.toString() );
567 if ( hasPartProp.isValid() )
568 plugin->setShowInSideBar( hasPartProp.toBool() );
569
570 for ( i = 0; i < plugins.count(); ++i ) {
571 Plugin *p = plugins.at( i );
572 if ( plugin->weight() < p->weight() )
573 break;
574 }
575
576 plugins.insert( i, plugin );
577 }
578
579 for ( i = 0; i < plugins.count(); ++ i ) {
580 Plugin *plugin = plugins.at( i );
581
582 TDEAction *action;
583 TQPtrList<TDEAction> *actionList = plugin->newActions();
584
585 for ( action = actionList->first(); action; action = actionList->next() ) {
586 kdDebug(5600) << "Plugging " << action->name() << endl;
587 action->plug( mNewActions->popupMenu() );
588 if ( action->name() == plugin->identifier() ) {
589 mPluginAction.insert( plugin, action );
590 }
591 }
592
593 if ( mSyncActionsEnabled ) {
594 actionList = plugin->syncActions();
595 for ( action = actionList->first(); action; action = actionList->next() ) {
596 kdDebug(5600) << "Plugging " << action->name() << endl;
597 action->plug( mSyncActions->popupMenu() );
598 }
599 }
600 addPlugin( plugin );
601 }
602 updateShortcuts();
603
604 mNewActions->setEnabled( mPlugins.size() != 0 );
605 if ( mSyncActionsEnabled )
606 mSyncActions->setEnabled( mPlugins.size() != 0 );
607}
608
609void MainWindow::unloadPlugins()
610{
611 KPluginInfo::List::ConstIterator end = mPluginInfos.constEnd();
612 KPluginInfo::List::ConstIterator it;
613 for ( it = mPluginInfos.constBegin(); it != end; ++it ) {
614 if ( !(*it)->isPluginEnabled() )
615 removePlugin( *it );
616 }
617}
618
619void MainWindow::updateShortcuts()
620{
621 TQPtrList<TDEAction> loadedActions;
622
623 sortActionsByWeight();
624
625 TQPtrListIterator<TDEAction> it( mActionPlugins );
626 int i = 1;
627 TDEAction *action;
628 while ( ( action = it.current() ) != 0 ) {
629 ++it;
630 if ( isPluginLoadedByAction( action ) ) {
631 loadedActions.append( action );
632 TQString shortcut = TQString( "CTRL+%1" ).arg( i );
633 action->setShortcut( TDEShortcut( shortcut ) );
634 i++;
635 } else {
636 action->setShortcut( TDEShortcut() );
637 }
638 }
639 unplugActionList( "navigator_actionlist" );
640 factory()->plugActionList( this, TQString( "navigator_actionlist" ), loadedActions );
641}
642
643bool MainWindow::removePlugin( const KPluginInfo *info )
644{
645 PluginList::Iterator end = mPlugins.end();
646 for ( PluginList::Iterator it = mPlugins.begin(); it != end; ++it ) {
647 if ( ( *it )->identifier() == info->pluginName() ) {
648 Plugin *plugin = *it;
649
650 TDEAction *action;
651 TQPtrList<TDEAction> *actionList = plugin->newActions();
652 for ( action = actionList->first(); action; action = actionList->next() ) {
653 kdDebug(5600) << "Unplugging " << action->name() << endl;
654 action->unplug( mNewActions->popupMenu() );
655 }
656
657 if ( mSyncActionsEnabled ) {
658 actionList = plugin->syncActions();
659 for ( action = actionList->first(); action; action = actionList->next() ) {
660 kdDebug(5600) << "Unplugging " << action->name() << endl;
661 action->unplug( mSyncActions->popupMenu() );
662 }
663 }
664 removeChildClient( plugin );
665
666 if ( mCurrentPlugin == plugin )
667 mCurrentPlugin = 0;
668
669 plugin->deleteLater(); // removes the part automatically
670 mPlugins.remove( it );
671
672 if ( plugin->showInSideBar() ) {
673 mPluginAction.remove( plugin );
674 }
675
676 if ( mCurrentPlugin == 0 ) {
677 PluginList::Iterator it;
678 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
679 if ( (*it)->showInSideBar() ) {
680 selectPlugin( *it );
681 return true;
682 }
683 }
684 }
685 return true;
686 }
687 }
688 return false;
689}
690
691void MainWindow::addPlugin( Kontact::Plugin *plugin )
692{
693 kdDebug(5600) << "Added plugin" << endl;
694
695 mPlugins.append( plugin );
696
697 // merge the plugins GUI into the main window
698 insertChildClient( plugin );
699}
700
701void MainWindow::partLoaded( Kontact::Plugin*, KParts::ReadOnlyPart *part )
702{
703 // See if we have this part already (e.g. due to two plugins sharing it)
704 if ( mPartsStack->id( part->widget() ) != -1 )
705 return;
706
707 mPartsStack->addWidget( part->widget() );
708
709 mPartManager->addPart( part, false );
710 // Workaround for KParts misbehavior: addPart calls show!
711 part->widget()->hide();
712}
713
714void MainWindow::slotActivePartChanged( KParts::Part *part )
715{
716 if ( !part ) {
717 createGUI( 0 );
718 return;
719 }
720
721 kdDebug(5600) << "Part activated: " << part << " with stack id. "
722 << mPartsStack->id( part->widget() )<< endl;
723
724 //createGUI( part ); // moved to selectPlugin()
725
726 statusBar()->clear();
727}
728
729void MainWindow::slotNewClicked()
730{
731 TDEAction *action = mCurrentPlugin->newActions()->first();
732 if ( action ) {
733 action->activate();
734 } else {
735 PluginList::Iterator it;
736 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
737 action = (*it)->newActions()->first();
738 if ( action ) {
739 action->activate();
740 return;
741 }
742 }
743 }
744}
745
746void MainWindow::slotSyncClicked()
747{
748 TDEAction *action = mCurrentPlugin->syncActions()->first();
749 if ( action ) {
750 action->activate();
751 } else {
752 PluginList::Iterator it;
753 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
754 action = (*it)->syncActions()->first();
755 if ( action ) {
756 action->activate();
757 return;
758 }
759 }
760 }
761}
762
763TDEToolBar* Kontact::MainWindow::findToolBar(const char* name)
764{
765 // like TDEMainWindow::toolBar, but which doesn't create the toolbar if not found
766 return static_cast<TDEToolBar *>(child(name, "TDEToolBar"));
767}
768
769void MainWindow::slotActionTriggered()
770{
771 const TDEAction *actionSender = static_cast<const TDEAction*>( sender() );
772 TQString identifier = actionSender->name();
773 if ( !identifier.isEmpty() ) {
774 selectPlugin( identifier );
775 }
776}
777
778void MainWindow::selectPlugin( Kontact::Plugin *plugin )
779{
780 if ( !plugin )
781 return;
782
783 if ( plugin->isRunningStandalone() ) {
784 statusBar()->message( i18n( "Application is running standalone. Foregrounding..." ), 1000 );
785 mSidePane->indicateForegrunding( plugin );
786 plugin->bringToForeground();
787 return;
788 }
789
790 TDEApplication::setOverrideCursor( TQCursor( TQt::WaitCursor ) );
791
792 KParts::Part *part = plugin->part();
793
794 if ( !part ) {
795 TDEApplication::restoreOverrideCursor();
796 KMessageBox::error( this, i18n( "Cannot load part for %1." )
797 .arg( plugin->title() )
798 + "\n" + lastErrorMessage() );
799 plugin->setDisabled( true );
800 mSidePane->updatePlugins();
801 return;
802 }
803
804 // store old focus widget
805 TQWidget *focusWidget = tdeApp->focusWidget();
806 if ( mCurrentPlugin && focusWidget ) {
807 // save the focus widget only when it belongs to the activated part
808 TQWidget *parent = focusWidget->parentWidget();
809 while ( parent ) {
810 if ( parent == mCurrentPlugin->part()->widget() )
811 mFocusWidgets.insert( mCurrentPlugin->identifier(), TQGuardedPtr<TQWidget>( focusWidget ) );
812
813 parent = parent->parentWidget();
814 }
815 }
816
817 if ( mSidePane ) {
818 mSidePane->selectPlugin( plugin->identifier() );
819 }
820
821 plugin->select();
822
823 mPartManager->setActivePart( part );
824 TQWidget *view = part->widget();
825 Q_ASSERT( view );
826
827 if ( view ) {
828 mPartsStack->raiseWidget( view );
829 view->show();
830
831 if ( mFocusWidgets.contains( plugin->identifier() ) ) {
832 focusWidget = mFocusWidgets[ plugin->identifier() ];
833 if ( focusWidget )
834 focusWidget->setFocus();
835 } else
836 view->setFocus();
837
838 mCurrentPlugin = plugin;
839 TDEAction *newAction = plugin->newActions()->first();
840 TDEAction *syncAction = plugin->syncActions()->first();
841
842 createGUI( plugin->part() );
843
844 TDEToolBar* navigatorToolBar = findToolBar( "navigatorToolBar" );
845 // Let the navigator toolbar be always the last one, if it's in the top dockwindow
846 if ( navigatorToolBar && !navigatorToolBar->isHidden() &&
847 navigatorToolBar->barPos() == TDEToolBar::Top ) {
848 topDock()->moveDockWindow( navigatorToolBar, -1 );
849 }
850
851 setCaption( i18n( "Plugin dependent window title" ,"%1 - Kontact" ).arg( plugin->title() ) );
852
853 if ( newAction ) {
854 mNewActions->setIcon( newAction->icon() );
855 mNewActions->setText( newAction->text() );
856 } else { // we'll use the action of the first plugin which offers one
857 PluginList::Iterator it;
858 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
859 newAction = (*it)->newActions()->first();
860 if ( newAction ) {
861 mNewActions->setIcon( newAction->icon() );
862 mNewActions->setText( newAction->text() );
863 break;
864 }
865 }
866 }
867 if ( mSyncActionsEnabled ) {
868 if ( syncAction ) {
869 mSyncActions->setIcon( syncAction->icon() );
870 mSyncActions->setText( syncAction->text() );
871 } else { // we'll use the action of the first plugin which offers one
872 PluginList::Iterator it;
873 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it ) {
874 syncAction = (*it)->syncActions()->first();
875 if ( syncAction ) {
876 mSyncActions->setIcon( syncAction->icon() );
877 mSyncActions->setText( syncAction->text() );
878 break;
879 }
880 }
881 }
882 }
883 }
884 TQStringList invisibleActions = plugin->invisibleToolbarActions();
885
886 TQStringList::ConstIterator it;
887 for ( it = invisibleActions.begin(); it != invisibleActions.end(); ++it ) {
888 TDEAction *action = part->actionCollection()->action( (*it).latin1() );
889 if ( action ) {
890 TQPtrListIterator<TDEToolBar> it( toolBarIterator() );
891 for ( ; it.current() ; ++it ) {
892 action->unplug( it.current() );
893 }
894 }
895 }
896
897 TDEApplication::restoreOverrideCursor();
898}
899
900void MainWindow::selectPlugin( const TQString &pluginName )
901{
902 PluginList::ConstIterator end = mPlugins.end();
903 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it )
904 if ( ( *it )->identifier() == pluginName ) {
905 selectPlugin( *it );
906 return;
907 }
908}
909
910void MainWindow::loadSettings()
911{
912 if ( mSplitter )
913 mSplitter->setSizes( Prefs::self()->mSidePaneSplitter );
914
915 // Preload Plugins. This _must_ happen before the default part is loaded
916 PluginList::ConstIterator it;
917 for ( it = mDelayedPreload.begin(); it != mDelayedPreload.end(); ++it )
918 selectPlugin( *it );
919
920 selectPlugin( Prefs::self()->mActivePlugin );
921}
922
923void MainWindow::saveSettings()
924{
925 if ( mSplitter )
926 Prefs::self()->mSidePaneSplitter = mSplitter->sizes();
927
928 if ( mCurrentPlugin )
929 Prefs::self()->mActivePlugin = mCurrentPlugin->identifier();
930}
931
932void MainWindow::slotShowTip()
933{
934 showTip( true );
935}
936
937void MainWindow::slotShowIntroduction()
938{
939 mPartsStack->raiseWidget( 0 ); // ###
940}
941
942void MainWindow::showTip( bool force )
943{
944 TQStringList tips;
945 PluginList::ConstIterator end = mPlugins.end();
946 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it ) {
947 TQString file = (*it)->tipFile();
948 if ( !file.isEmpty() )
949 tips.append( file );
950 }
951
952 KTipDialog::showMultiTip( this, tips, force );
953}
954
955void MainWindow::slotQuit()
956{
957 mReallyClose = true;
958 close();
959}
960
961void MainWindow::slotPreferences()
962{
963 static SettingsDialogWrapper *dlg = 0;
964 if ( !dlg ) {
965 // do not show settings of components running standalone
966 TQValueList<KPluginInfo*> filteredPlugins = mPluginInfos;
967 PluginList::ConstIterator it;
968 for ( it = mPlugins.begin(); it != mPlugins.end(); ++it )
969 if ( (*it)->isRunningStandalone() ) {
970 TQValueList<KPluginInfo*>::ConstIterator infoIt;
971 for ( infoIt = filteredPlugins.begin(); infoIt != filteredPlugins.end(); ++infoIt ) {
972 if ( (*infoIt)->pluginName() == (*it)->identifier() ) {
973 filteredPlugins.remove( *infoIt );
974 break;
975 }
976 }
977 }
978 dlg = new SettingsDialogWrapper( KSettings::Dialog::Configurable, this );
979 dlg->addPluginInfos( filteredPlugins );
980 connect( dlg, TQ_SIGNAL( pluginSelectionChanged() ),
981 TQ_SLOT( pluginsChanged() ) );
982 }
983
984 dlg->show();
985 dlg->fixButtonLabel( this );
986}
987
988int MainWindow::startServiceFor( const TQString& serviceType,
989 const TQString& constraint,
990 const TQString& preferences,
991 TQString *error, TQCString* dcopService,
992 int flags )
993{
994 PluginList::ConstIterator end = mPlugins.end();
995 for ( PluginList::ConstIterator it = mPlugins.begin(); it != end; ++it ) {
996 if ( (*it)->createDCOPInterface( serviceType ) ) {
997 kdDebug(5600) << "found interface for " << serviceType << endl;
998 if ( dcopService )
999 *dcopService = (*it)->dcopClient()->appId();
1000 kdDebug(5600) << "appId=" << (*it)->dcopClient()->appId() << endl;
1001 return 0; // success
1002 }
1003 }
1004
1005 kdDebug(5600) <<
1006 "Didn't find dcop interface, falling back to external process" << endl;
1007
1008 return KDCOPServiceStarter::startServiceFor( serviceType, constraint,
1009 preferences, error, dcopService, flags );
1010}
1011
1012void MainWindow::pluginsChanged()
1013{
1014 unloadPlugins();
1015 loadPlugins();
1016 mSidePane->updatePlugins();
1017 updateShortcuts();
1018}
1019
1020void MainWindow::updateConfig()
1021{
1022 kdDebug( 5600 ) << k_funcinfo << endl;
1023
1024 saveSettings();
1025 loadSettings();
1026}
1027
1028void MainWindow::showAboutDialog()
1029{
1030 TDEApplication::setOverrideCursor( TQCursor( TQt::WaitCursor ) );
1031
1032 if ( !mAboutDialog )
1033 mAboutDialog = new AboutDialog( this );
1034
1035 mAboutDialog->show();
1036 mAboutDialog->raise();
1037 TDEApplication::restoreOverrideCursor();
1038}
1039
1040void MainWindow::configureShortcuts()
1041{
1042 KKeyDialog dialog( true, this );
1043 dialog.insert( actionCollection() );
1044
1045 if ( mCurrentPlugin && mCurrentPlugin->part() )
1046 dialog.insert( mCurrentPlugin->part()->actionCollection() );
1047
1048 dialog.configure();
1049}
1050
1051void MainWindow::configureToolbars()
1052{
1053 saveMainWindowSettings( TDEGlobal::config(), "MainWindow" );
1054
1055 KEditToolbar edit( factory() );
1056 connect( &edit, TQ_SIGNAL( newToolbarConfig() ),
1057 this, TQ_SLOT( slotNewToolbarConfig() ) );
1058 edit.exec();
1059}
1060
1061void MainWindow::slotNewToolbarConfig()
1062{
1063 if ( mCurrentPlugin && mCurrentPlugin->part() ) {
1064 createGUI( mCurrentPlugin->part() );
1065 }
1066 if ( mCurrentPlugin ) {
1067 applyMainWindowSettings( TDEGlobal::config(), "MainWindow" );
1068 }
1069 updateShortcuts(); // for the plugActionList call
1070}
1071
1072void MainWindow::slotOpenUrl( const KURL &url )
1073{
1074 if ( url.protocol() == "exec" ) {
1075 if ( url.path() == "/switch" ) {
1076 selectPlugin( mCurrentPlugin );
1077 }
1078 if ( url.path() == "/gwwizard" ) {
1079 KRun::runCommand( "groupwarewizard" );
1080 slotQuit();
1081 }
1082 if ( url.path().startsWith( "/help" ) ) {
1083 TQString app( "kontact" );
1084 if ( !url.query().isEmpty() ) {
1085 app = url.query().mid( 1 );
1086 }
1087 tdeApp->invokeHelp( TQString(), app );
1088 }
1089 } else {
1090 new KRun( url, this );
1091 }
1092}
1093
1094void MainWindow::readProperties( TDEConfig *config )
1095{
1096 Core::readProperties( config );
1097
1098 TQStringList activePlugins = config->readListEntry( "ActivePlugins" );
1099 TQValueList<Plugin*>::ConstIterator it = mPlugins.begin();
1100 TQValueList<Plugin*>::ConstIterator end = mPlugins.end();
1101 for ( ; it != end; ++it ) {
1102 Plugin *plugin = *it;
1103 if ( !plugin->isRunningStandalone() ) {
1104 TQStringList::ConstIterator activePlugin = activePlugins.find( plugin->identifier() );
1105 if ( activePlugin != activePlugins.end() ) {
1106 plugin->readProperties( config );
1107 }
1108 }
1109 }
1110}
1111
1112void MainWindow::saveProperties( TDEConfig *config )
1113{
1114 Core::saveProperties( config );
1115
1116 TQStringList activePlugins;
1117
1118 KPluginInfo::List::Iterator it = mPluginInfos.begin();
1119 KPluginInfo::List::Iterator end = mPluginInfos.end();
1120 for ( ; it != end; ++it ) {
1121 KPluginInfo *info = *it;
1122 if ( info->isPluginEnabled() ) {
1123 Plugin *plugin = pluginFromInfo( info );
1124 if ( plugin ) {
1125 activePlugins.append( plugin->identifier() );
1126 plugin->saveProperties( config );
1127 }
1128 }
1129 }
1130
1131 config->writeEntry( "ActivePlugins", activePlugins );
1132}
1133
1134bool MainWindow::queryClose()
1135{
1136 //if ( tdeApp->sessionSaving() || mReallyClose )
1137 if ( tdeApp->sessionSaving() )
1138 return true;
1139
1140 bool localClose = true;
1141 TQValueList<Plugin*>::ConstIterator end = mPlugins.end();
1142 TQValueList<Plugin*>::ConstIterator it = mPlugins.begin();
1143 for ( ; it != end; ++it ) {
1144 Plugin *plugin = *it;
1145 if ( !plugin->isRunningStandalone() )
1146 if ( !plugin->queryClose() )
1147 localClose = false;
1148 }
1149
1150 return localClose;
1151}
1152
1153void MainWindow::slotShowStatusMsg( const TQString &msg )
1154{
1155 if ( !statusBar() || !mStatusMsgLabel )
1156 return;
1157
1158 mStatusMsgLabel->setText( msg );
1159}
1160
1161TQString MainWindow::introductionString()
1162{
1163 TDEIconLoader *iconloader = TDEGlobal::iconLoader();
1164 int iconSize = iconloader->currentSize( TDEIcon::Desktop );
1165
1166 TQString handbook_icon_path = iconloader->iconPath( "contents2", TDEIcon::Desktop );
1167 TQString html_icon_path = iconloader->iconPath( "text-html", TDEIcon::Desktop );
1168 TQString wizard_icon_path = iconloader->iconPath( "wizard", TDEIcon::Desktop );
1169
1170 TQString info = i18n( "<h2 style='text-align:center; margin-top: 0px;'>Welcome to Kontact %1</h2>"
1171 "<p>%1</p>"
1172 "<table align=\"center\">"
1173 "<tr><td><a href=\"%1\"><img width=\"%1\" height=\"%1\" src=\"%1\" /></a></td>"
1174 "<td><a href=\"%1\">%1</a><br><span id=\"subtext\"><nobr>%1</td></tr>"
1175 "<tr><td><a href=\"%1\"><img width=\"%1\" height=\"%1\" src=\"%1\" /></a></td>"
1176 "<td><a href=\"%1\">%1</a><br><span id=\"subtext\"><nobr>%1</td></tr>"
1177 "<tr><td><a href=\"%1\"><img width=\"%1\" height=\"%1\" src=\"%1\" /></a></td>"
1178 "<td><a href=\"%1\">%1</a><br><span id=\"subtext\"><nobr>%1</td></tr>"
1179 "</table>"
1180 "<p style=\"margin-bottom: 0px\"> <a href=\"%1\">Skip this introduction</a></p>" )
1181 .arg( tdeApp->aboutData()->version() )
1182 .arg( i18n( "Kontact handles your e-mail, addressbook, calendar, to-do list and more." ) )
1183 .arg( "exec:/help?kontact" )
1184 .arg( iconSize )
1185 .arg( iconSize )
1186 .arg( handbook_icon_path )
1187 .arg( "exec:/help?kontact" )
1188 .arg( i18n( "Read Manual" ) )
1189 .arg( i18n( "Learn more about Kontact and its components" ) )
1190 .arg( "http://kontact.org" )
1191 .arg( iconSize )
1192 .arg( iconSize )
1193 .arg( html_icon_path )
1194 .arg( "http://kontact.org" )
1195 .arg( i18n( "Visit Kontact Website" ) )
1196 .arg( i18n( "Access online resources and tutorials" ) )
1197 .arg( "exec:/gwwizard" )
1198 .arg( iconSize )
1199 .arg( iconSize )
1200 .arg( wizard_icon_path )
1201 .arg( "exec:/gwwizard" )
1202 .arg( i18n( "Configure Kontact as Groupware Client" ) )
1203 .arg( i18n( "Prepare Kontact for use in corporate networks" ) )
1204 .arg( "exec:/switch" );
1205 return info;
1206}
1207
1208#include "mainwindow.moc"
This class provides the interface to the Kontact core for the plugins.
Definition: core.h:42
Base class for all Plugins in Kontact.
Definition: plugin.h:59
KParts::ReadOnlyPart * part()
You can use this method if you need to access the current part.
Definition: plugin.cpp:145
virtual TQStringList invisibleToolbarActions() const
Returns a list of action name which shall be hidden in the main toolbar.
Definition: plugin.h:233
TQString title() const
Returns the localized title.
Definition: plugin.cpp:94
virtual bool isRunningStandalone()
Reimplement this method and return whether a standalone application is still running This is only req...
Definition: plugin.h:131
virtual bool queryClose() const
Reimplement this method if you want to add checks before closing down the main kontact window.
Definition: plugin.h:191
virtual bool showInSideBar() const
Returns whether the plugin provides a part that should be shown in the sidebar.
Definition: plugin.cpp:225
void setTitle(const TQString &title)
Sets the localized title.
Definition: plugin.cpp:89
void setIcon(const TQString &icon)
Sets the icon name.
Definition: plugin.cpp:99
TQPtrList< TDEAction > * syncActions() const
FIXME: write API doc for Kontact::Plugin::syncActions().
Definition: plugin.cpp:191
virtual void bringToForeground()
Reimplement this method if your application needs a different approach to be brought in the foregroun...
Definition: plugin.cpp:219
void setPartLibraryName(const TQCString &)
Set name of library which contains the KPart used by this plugin.
Definition: plugin.cpp:119
void setIdentifier(const TQString &identifier)
Sets the identifier.
Definition: plugin.cpp:79
virtual void select()
This function is called when the plugin is selected by the user before the widget of the KPart belong...
Definition: plugin.cpp:201
TQString identifier() const
Returns the identifier.
Definition: plugin.cpp:84
virtual int weight() const
Return the weight of the plugin.
Definition: plugin.h:208
virtual void saveProperties(TDEConfig *)
Session management: save properties.
Definition: plugin.h:257
virtual void readProperties(TDEConfig *)
Session management: read properties.
Definition: plugin.h:252
virtual void configUpdated()
This function is called whenever the config dialog has been closed successfully.
Definition: plugin.cpp:205
void setShowInSideBar(bool hasPart)
Set if the plugin provides a part that should be shown in the sidebar.
Definition: plugin.cpp:230
TQPtrList< TDEAction > * newActions() const
FIXME: write API doc for Kontact::Plugin::newActions().
Definition: plugin.cpp:186
void setExecutableName(const TQString &bin)
Sets the name of executable (if existant).
Definition: plugin.cpp:109
bool view(TQWidget *parent, Attachment *attachment)