lib

KoMainWindow.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 Copyright (C) 2000-2006 David Faure <faure@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "KoMainWindow.h"
22#include "KoDocument.h"
23#include "KoView.h"
24#include "KoFilterManager.h"
25#include "KoDocumentInfo.h"
26#include "KoDocumentInfoDlg.h"
27#include "KoQueryTrader.h"
28#include "KoMainWindowIface.h"
29#include "KoFrame.h"
30#include "KoFileDialog.h"
31#include "Koversiondialog.h"
33#include "KoSpeaker.h"
34
35#include <tdeaboutdata.h>
36#include <kprinter.h>
37#include <kstdaction.h>
38#include <tdeapplication.h>
39#include <tdemessagebox.h>
40#include <kstandarddirs.h>
41#include <tdeio/netaccess.h>
42#include <kkeydialog.h>
43#include <kedittoolbar.h>
44#include <kprogress.h>
45#include <kpushbutton.h>
46#include <kdebug.h>
47#include <tdetempfile.h>
48#include <tderecentdocument.h>
49#include <tdeparts/partmanager.h>
50#include <tdeparts/plugin.h>
51#include <tdeparts/event.h>
52#include <tdelocale.h>
53#include <kstatusbar.h>
54#include <tdeglobalsettings.h>
55#include <ksharedptr.h>
56
57#include <tqobjectlist.h>
58
59#include <unistd.h>
60#include <stdlib.h>
61
62class KoPartManager : public KParts::PartManager
63{
64public:
65 KoPartManager( TQWidget * parent, const char * name = 0L )
66 : KParts::PartManager( parent, name )
67 {
68 setSelectionPolicy( KParts::PartManager::TriState );
69 setAllowNestedParts( true );
70 setIgnoreScrollBars( true );
71 // Allow right-click on embedded objects (without activating them)
72 // But beware: this means right-click on parent, from embedded object,
73 // doesn't make the parent active first...
74 setActivationButtonMask( TQt::LeftButton | TQt::MidButton );
75 }
76 virtual bool eventFilter( TQObject *obj, TQEvent *ev )
77 {
78 if ( !obj->isWidgetType() || ::tqt_cast<KoFrame *>( obj ) )
79 return false;
80 return KParts::PartManager::eventFilter( obj, ev );
81 }
82};
83
84class KoMainWindowPrivate
85{
86public:
87 KoMainWindowPrivate()
88 {
89 m_rootDoc = 0L;
90 m_docToOpen = 0L;
91 m_manager = 0L;
92 bMainWindowGUIBuilt = false;
93 m_forQuit=false;
94 m_splitted=false;
95 m_activePart = 0L;
96 m_activeView = 0L;
97 m_splitter=0L;
98 m_orientation=0L;
99 m_removeView=0L;
100 m_toolbarList.setAutoDelete( true );
101 m_firstTime=true;
102 m_progress=0L;
103 m_paDocInfo = 0;
104 m_paSave = 0;
105 m_paSaveAs = 0;
106 m_paPrint = 0;
107 m_paPrintPreview = 0;
108 statusBarLabel = 0L;
109 m_dcopObject = 0;
110 m_sendfile = 0;
111 m_paCloseFile = 0L;
112 m_reloadfile = 0L;
113 m_versionsfile = 0L;
114 m_importFile = 0;
115 m_exportFile = 0;
116 m_isImporting = false;
117 m_isExporting = false;
118 m_windowSizeDirty = false;
119 m_lastExportSpecialOutputFlag = 0;
120
121 // TTS accessibility enhancement (only if KDE 3.4 or later and KTTSD daemon is installed.)
123 if (kospeaker)
124 m_koSpeaker = kospeaker;
125 else
126 m_koSpeaker = new KoSpeaker();
127 } else
128 m_koSpeaker = 0;
129 }
130 ~KoMainWindowPrivate()
131 {
132 delete m_dcopObject;
133 }
134
135 KoDocument *m_rootDoc;
136 KoDocument *m_docToOpen;
137 TQPtrList<KoView> m_rootViews;
138 KParts::PartManager *m_manager;
139
140 KParts::Part *m_activePart;
141 KoView *m_activeView;
142
143 TQLabel * statusBarLabel;
144 KProgress *m_progress;
145
146 TQPtrList<TDEAction> m_splitViewActionList;
147 // This additional list is needed, because we don't plug
148 // the first list, when an embedded view gets activated (Werner)
149 TQPtrList<TDEAction> m_veryHackyActionList;
150 TQSplitter *m_splitter;
151 TDESelectAction *m_orientation;
152 TDEAction *m_removeView;
153 KoMainWindowIface *m_dcopObject;
154
155 TQPtrList <TDEAction> m_toolbarList;
156
157 bool bMainWindowGUIBuilt;
158 bool m_splitted;
159 bool m_forQuit;
160 bool m_firstTime;
161 bool m_windowSizeDirty;
162
163 TDEAction *m_paDocInfo;
164 TDEAction *m_paSave;
165 TDEAction *m_paSaveAs;
166 TDEAction *m_paPrint;
167 TDEAction *m_paPrintPreview;
168 TDEAction *m_sendfile;
169 TDEAction *m_paCloseFile;
170 TDEAction *m_reloadfile;
171 TDEAction *m_versionsfile;
172 TDEAction *m_importFile;
173 TDEAction *m_exportFile;
174
175 bool m_isImporting;
176 bool m_isExporting;
177
178 KURL m_lastExportURL;
179 TQCString m_lastExportFormat;
180 int m_lastExportSpecialOutputFlag;
181
182 TDESharedPtr<KoSpeaker> m_koSpeaker;
183};
184
185KoMainWindow::KoMainWindow( TDEInstance *instance, const char* name )
186 : KParts::MainWindow( 0, 0L, name )
187{
188 setStandardToolBarMenuEnabled(true); // should there be a check for >= 3.1 ?
189 Q_ASSERT(instance);
190 d = new KoMainWindowPrivate;
191
192 d->m_manager = new KoPartManager( this );
193
194 connect( d->m_manager, TQ_SIGNAL( activePartChanged( KParts::Part * ) ),
195 this, TQ_SLOT( slotActivePartChanged( KParts::Part * ) ) );
196
197 if ( instance )
198 setInstance( instance, false ); // don't load plugins! we don't want
199 // the part's plugins with this shell, even though we are using the
200 // part's instance! (Simon)
201
202 TQString doc;
203 TQStringList allFiles = TDEGlobal::dirs()->findAllResources( "data", "koffice/koffice_shell.rc" );
204 setXMLFile( findMostRecentXMLFile( allFiles, doc ) );
205 setLocalXMLFile( locateLocal( "data", "koffice/koffice_shell.rc" ) );
206
207 KStdAction::openNew( this, TQ_SLOT( slotFileNew() ), actionCollection(), "file_new" );
208 KStdAction::open( this, TQ_SLOT( slotFileOpen() ), actionCollection(), "file_open" );
209 m_recent = KStdAction::openRecent( this, TQ_SLOT(slotFileOpenRecent(const KURL&)), actionCollection() );
210 d->m_paSave = KStdAction::save( this, TQ_SLOT( slotFileSave() ), actionCollection(), "file_save" );
211 d->m_paSaveAs = KStdAction::saveAs( this, TQ_SLOT( slotFileSaveAs() ), actionCollection(), "file_save_as" );
212 d->m_paPrint = KStdAction::print( this, TQ_SLOT( slotFilePrint() ), actionCollection(), "file_print" );
213 d->m_paPrintPreview = KStdAction::printPreview( this, TQ_SLOT( slotFilePrintPreview() ), actionCollection(), "file_print_preview" );
214 d->m_sendfile = KStdAction::mail( this, TQ_SLOT( slotEmailFile() ), actionCollection(), "file_send_file");
215
216 d->m_paCloseFile = KStdAction::close( this, TQ_SLOT( slotFileClose() ), actionCollection(), "file_close" );
217 KStdAction::quit( this, TQ_SLOT( slotFileQuit() ), actionCollection(), "file_quit" );
218
219 d->m_reloadfile = new TDEAction( i18n( "Reload"), 0,
220 this, TQ_SLOT( slotReloadFile() ),
221 actionCollection(), "file_reload_file");
222
223 d->m_versionsfile = new TDEAction( i18n( "Versions..."), 0,
224 this, TQ_SLOT( slotVersionsFile() ),
225 actionCollection(), "file_versions_file");
226
227 d->m_importFile = new TDEAction( i18n( "I&mport..." ), 0, // clashing accel key :(
228 this, TQ_SLOT( slotImportFile() ),
229 actionCollection(), "file_import_file");
230 d->m_exportFile = new TDEAction( i18n( "E&xport..." ), 0,
231 this, TQ_SLOT( slotExportFile() ),
232 actionCollection(), "file_export_file");
233
234 /* The following entry opens the document information dialog. Since the action is named so it
235 intends to show data this entry should not have a trailing ellipses (...). */
236 d->m_paDocInfo = new TDEAction( i18n( "&Document Information" ), "documentinfo", 0,
237 this, TQ_SLOT( slotDocumentInfo() ),
238 actionCollection(), "file_documentinfo" );
239
242
243 d->m_paDocInfo->setEnabled( false );
244 d->m_paSaveAs->setEnabled( false );
245 d->m_reloadfile->setEnabled( false );
246 d->m_versionsfile->setEnabled( false );
247 d->m_importFile->setEnabled( true ); // always enabled like File --> Open
248 d->m_exportFile->setEnabled( false );
249 d->m_paSave->setEnabled( false );
250 d->m_paPrint->setEnabled( false );
251 d->m_paPrintPreview->setEnabled( false );
252 d->m_sendfile->setEnabled( false);
253 d->m_paCloseFile->setEnabled( false);
254
255 d->m_splitter=new TQSplitter(TQt::Vertical, this, "mw-splitter");
256 setCentralWidget( d->m_splitter );
257 // Keyboard accessibility enhancements.
258 new KKbdAccessExtensions(this, "mw-panelSizer");
259 // set up the action "list" for "Close all Views" (hacky :) (Werner)
260 d->m_veryHackyActionList.append(
261 new TDEAction(i18n("&Close All Views"), "window-close",
262 "ctrl+shift+w", this, TQ_SLOT(slotCloseAllViews()),
263 actionCollection(), "view_closeallviews") );
264
265 // set up the action list for the splitter stuff
266 d->m_splitViewActionList.append(new TDEAction(i18n("&Split View"), "view_split", 0,
267 this, TQ_SLOT(slotSplitView()),
268 actionCollection(), "view_split"));
269 d->m_removeView=new TDEAction(i18n("&Remove View"), "view_remove", 0,
270 this, TQ_SLOT(slotRemoveView()),
271 actionCollection(), "view_rm_splitter");
272 d->m_splitViewActionList.append(d->m_removeView);
273 d->m_removeView->setEnabled(false);
274 d->m_orientation=new TDESelectAction(i18n("Splitter &Orientation"), "view_orientation", 0,
275 this, TQ_SLOT(slotSetOrientation()),
276 actionCollection(), "view_splitter_orientation");
277 TQStringList items;
278 items << i18n("&Vertical")
279 << i18n("&Horizontal");
280 d->m_orientation->setItems(items);
281 d->m_orientation->setCurrentItem(static_cast<int>(d->m_splitter->orientation()));
282 d->m_splitViewActionList.append(d->m_orientation);
283 d->m_splitViewActionList.append(new TDEActionSeparator(this));
284
285 // Load list of recent files
286 TDEConfig * config = instance ? instance->config() : TDEGlobal::config();
287 m_recent->loadEntries( config );
288
289 createShellGUI();
290 d->bMainWindowGUIBuilt = true;
291
292 if ( !initialGeometrySet() )
293 {
294 // Default size
295 const int deskWidth = TDEGlobalSettings::desktopGeometry(this).width();
296 if (deskWidth > 1100) // very big desktop ?
297 resize( 1000, 800 );
298 if (deskWidth > 850) // big desktop ?
299 resize( 800, 600 );
300 else // small (800x600, 640x480) desktop
301 resize( 600, 400 );
302 }
303
304 // Saved size
305 config->setGroup( "MainWindow" );
306 //kdDebug(30003) << "KoMainWindow::restoreWindowSize" << endl;
307 restoreWindowSize( config );
308}
309
311{
312 if (!d) {
313 return;
314 }
315
316 // The doc and view might still exist (this is the case when closing the window)
317 if (d->m_rootDoc) {
318 d->m_rootDoc->removeShell(this);
319 }
320
321 if (d->m_docToOpen) {
322 d->m_docToOpen->removeShell(this);
323 delete d->m_docToOpen;
324 d->m_docToOpen=0L;
325 }
326
327 // safety first ;)
328 d->m_manager->setActivePart(0);
329
330 if(d->m_rootViews.findRef(d->m_activeView)==-1) {
331 delete d->m_activeView;
332 d->m_activeView=0L;
333 }
334 d->m_rootViews.setAutoDelete( true );
335 d->m_rootViews.clear();
336
337 // We have to check if this was a root document.
338 // -> We aren't allowed to delete the (embedded) document!
339 // This has to be checked from queryClose, too :)
340 if ( d->m_rootDoc && d->m_rootDoc->viewCount() == 0 &&
341 !d->m_rootDoc->isEmbedded())
342 {
343 //kdDebug(30003) << "Destructor. No more views, deleting old doc " << d->m_rootDoc << endl;
344 delete d->m_rootDoc;
345 d->m_rootDoc=0L;
346 }
347
348 delete d->m_manager;
349 d->m_manager=0L;
350 delete d;
351 d=0L;
352}
353
355{
356 if ( d->m_rootDoc == doc )
357 return;
358
359 if (d->m_docToOpen && d->m_docToOpen != doc) {
360 d->m_docToOpen->removeShell(this);
361 delete d->m_docToOpen;
362 d->m_docToOpen = 0;
363 } else {
364 d->m_docToOpen = 0;
365 }
366
367 //kdDebug(30003) << "KoMainWindow::setRootDocument this = " << this << " doc = " << doc << endl;
368 TQPtrList<KoView> oldRootViews = d->m_rootViews;
369 d->m_rootViews.clear();
370 KoDocument *oldRootDoc = d->m_rootDoc;
371
372 if ( oldRootDoc )
373 oldRootDoc->removeShell( this );
374
375 d->m_rootDoc = doc;
376
377 if ( doc )
378 {
379 doc->setSelectable( false );
380 //d->m_manager->addPart( doc, false ); // done by KoView::setPartManager
381 d->m_rootViews.append( doc->createView( d->m_splitter, "view" /*not unique, but better than unnamed*/ ) );
382 d->m_rootViews.current()->setPartManager( d->m_manager );
383
384 d->m_rootViews.current()->show();
385 // The addShell has been done already if using openURL
386 if ( !d->m_rootDoc->shells().contains( this ) )
387 d->m_rootDoc->addShell( this );
388 d->m_removeView->setEnabled(false);
389 d->m_orientation->setEnabled(false);
390 }
391
392 bool enable = d->m_rootDoc != 0 ? true : false;
393 d->m_paDocInfo->setEnabled( enable );
394 d->m_paSave->setEnabled( enable );
395 d->m_paSaveAs->setEnabled( enable );
396 d->m_importFile->setEnabled( enable );
397 d->m_exportFile->setEnabled( enable );
398 d->m_paPrint->setEnabled( enable );
399 d->m_paPrintPreview->setEnabled( enable );
400 d->m_sendfile->setEnabled( enable);
401 d->m_paCloseFile->setEnabled( enable);
403
404 d->m_manager->setActivePart( d->m_rootDoc, d->m_rootViews.current() );
405
406 oldRootViews.setAutoDelete( true );
407 oldRootViews.clear();
408
409 if ( oldRootDoc && oldRootDoc->viewCount() == 0 )
410 {
411 //kdDebug(30003) << "No more views, deleting old doc " << oldRootDoc << endl;
412 delete oldRootDoc;
413 }
414}
415
416void KoMainWindow::updateReloadFileAction(KoDocument *doc)
417{
418 d->m_reloadfile->setEnabled( doc && !doc->url().isEmpty() );
419}
420
421void KoMainWindow::updateVersionsFileAction(KoDocument *doc)
422{
423 //TODO activate it just when we save it in oasis file format
424 d->m_versionsfile->setEnabled( doc && !doc->url().isEmpty()&&doc->isModified());
425}
426
427
428void KoMainWindow::setRootDocumentDirect( KoDocument *doc, const TQPtrList<KoView> & views )
429{
430 d->m_rootDoc = doc;
431 d->m_rootViews = views;
432 bool enable = d->m_rootDoc != 0 ? true : false;
433 d->m_paDocInfo->setEnabled( enable );
434 d->m_paSave->setEnabled( enable );
435 d->m_paSaveAs->setEnabled( enable );
436 d->m_exportFile->setEnabled( enable );
437 d->m_paPrint->setEnabled( enable );
438 d->m_paPrintPreview->setEnabled( enable );
439 d->m_sendfile->setEnabled( enable);
440 d->m_paCloseFile->setEnabled( enable );
441}
442
443void KoMainWindow::addRecentURL( const KURL& url )
444{
445 kdDebug(30003) << "KoMainWindow::addRecentURL url=" << url.prettyURL() << endl;
446 // Add entry to recent documents list
447 // (call coming from KoDocument because it must work with cmd line, template dlg, file/open, etc.)
448 if ( !url.isEmpty() )
449 {
450 bool ok = true;
451 if ( url.isLocalFile() )
452 {
453 TQString path = url.path( -1 );
454 TQStringList tmpDirs = TDEGlobal::dirs()->resourceDirs( "tmp" );
455 for ( TQStringList::Iterator it = tmpDirs.begin() ; ok && it != tmpDirs.end() ; ++it )
456 if ( path.contains( *it ) )
457 ok = false; // it's in the tmp resource
458 if ( ok )
459 TDERecentDocument::add(path);
460 }
461 else
462 TDERecentDocument::add(url.url(-1), true);
463
464 if ( ok )
465 m_recent->addURL( url );
467 }
468}
469
471{
472 // Save list of recent files
473 TDEConfig * config = instance() ? instance()->config() : TDEGlobal::config();
474 kdDebug(30003) << this << " Saving recent files list into config. instance()=" << instance() << endl;
475 m_recent->saveEntries( config );
476 config->sync();
478 {
479 // Tell all windows to reload their list, after saving
480 // Doesn't work multi-process, but it's a start
481 TDEMainWindow *window = TDEMainWindow::memberList->first();
482 for (; window; window = TDEMainWindow::memberList->next())
483 static_cast<KoMainWindow *>(window)->reloadRecentFileList();
484 }
485}
486
488{
489 TDEConfig * config = instance() ? instance()->config() : TDEGlobal::config();
490 m_recent->loadEntries( config );
491}
492
498
500{
501 //kdDebug(30003) << "KoMainWindow::updateCaption()" << endl;
502 if ( !d->m_rootDoc )
503 setCaption(TQString());
504 else if ( rootDocument()->isCurrent() )
505 {
506 TQString caption;
507 // Get caption from document info (title(), in about page)
508 if ( rootDocument()->documentInfo() )
509 {
510 KoDocumentInfoPage * page = rootDocument()->documentInfo()->page( TQString::fromLatin1("about") );
511 if (page)
512 caption = static_cast<KoDocumentInfoAbout *>(page)->title();
513 }
514 const TQString url = rootDocument()->url().prettyURL( 0, KURL::StripFileProtocol );
515 if ( !caption.isEmpty() && !url.isEmpty() )
516 caption = TQString( "%1 - %2" ).arg( caption ).arg( url );
517 else if ( caption.isEmpty() )
518 caption = url;
519
520 setCaption( caption, rootDocument()->isModified() );
521 if ( !rootDocument()->url().fileName(false).isEmpty() )
522 d->m_paSave->setToolTip( i18n("Save as %1").arg(rootDocument()->url().fileName(false)) );
523 else
524 d->m_paSave->setToolTip( i18n("Save") );
525 }
526}
527
528void KoMainWindow::updateCaption( TQString caption, bool mod )
529{
530 //kdDebug(30003)<<"KoMainWindow::updateCaption("<<caption<<","<<mod<<")"<<endl;
531 setCaption( caption, mod );
532}
533
535{
536 return d->m_rootDoc;
537}
538
539KoView *KoMainWindow::rootView() const
540{
541 if(d->m_rootViews.find(d->m_activeView)!=-1)
542 return d->m_activeView;
543 return d->m_rootViews.first();
544}
545
546KParts::PartManager *KoMainWindow::partManager()
547{
548 return d->m_manager;
549}
550
551bool KoMainWindow::openDocument( const KURL & url )
552{
553 if ( !TDEIO::NetAccess::exists(url,true,0) )
554 {
555 KMessageBox::error(0L, i18n("The file %1 does not exist.").arg(url.url()) );
556 m_recent->removeURL(url); //remove the file from the recent-opened-file-list
558 return false;
559 }
560 return openDocumentInternal( url );
561}
562
563// (not virtual)
564bool KoMainWindow::openDocument( KoDocument *newdoc, const KURL & url )
565{
566 if (!TDEIO::NetAccess::exists(url,true,0) )
567 {
568 if (!newdoc->checkAutoSaveFile())
569 {
570 newdoc->initEmpty(); //create an emtpy document
571 }
572
573 setRootDocument( newdoc );
574 newdoc->setURL(url);
575 TQString mime = KMimeType::findByURL(url)->name();
576 if ( mime.isEmpty() || mime == KMimeType::defaultMimeType() )
577 mime = newdoc->nativeFormatMimeType();
578 if ( url.isLocalFile() ) // workaround for kde<=3.3 tdeparts bug, fixed for 3.4
579 newdoc->setFile(url.path());
580 newdoc->setMimeTypeAfterLoading( mime );
582 return true;
583 }
584 return openDocumentInternal( url, newdoc );
585}
586
587// ## If you modify anything here, please check KoShellWindow::openDocumentInternal
588bool KoMainWindow::openDocumentInternal( const KURL & url, KoDocument *newdoc )
589{
590 //kdDebug(30003) << "KoMainWindow::openDocument " << url.url() << endl;
591
592 if ( !newdoc )
593 newdoc = createDoc();
594 if ( !newdoc )
595 return false;
596
597 d->m_firstTime=true;
598 connect(newdoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
599 connect(newdoc, TQ_SIGNAL(completed()), this, TQ_SLOT(slotLoadCompleted()));
600 connect(newdoc, TQ_SIGNAL(canceled( const TQString & )), this, TQ_SLOT(slotLoadCanceled( const TQString & )));
601 newdoc->addShell( this ); // used by openURL
602 bool openRet = (!isImporting ()) ? newdoc->openURL(url) : newdoc->import(url);
603 if(!openRet)
604 {
605 newdoc->removeShell(this);
606 delete newdoc;
607 return false;
608 }
609 updateReloadFileAction(newdoc);
610 updateVersionsFileAction( newdoc );
611 return true;
612}
613
614// Separate from openDocument to handle async loading (remote URLs)
615void KoMainWindow::slotLoadCompleted()
616{
617 kdDebug(30003) << "KoMainWindow::slotLoadCompleted" << endl;
618 KoDocument* doc = rootDocument();
619 KoDocument* newdoc = (KoDocument *)(sender());
620
621 if ( doc && doc->isEmpty() && !doc->isEmbedded() )
622 {
623 // Replace current empty document
624 setRootDocument( newdoc );
625 }
626 else if ( doc && !doc->isEmpty() )
627 {
628 // Open in a new shell
629 // (Note : could create the shell first and the doc next for this
630 // particular case, that would give a better user feedback...)
631 KoMainWindow *s = new KoMainWindow( newdoc->instance() );
632 s->show();
633 newdoc->removeShell( this );
634 s->setRootDocument( newdoc );
635 }
636 else
637 {
638 // We had no document, set the new one
639 setRootDocument( newdoc );
640 }
641 disconnect(newdoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
642 disconnect(newdoc, TQ_SIGNAL(completed()), this, TQ_SLOT(slotLoadCompleted()));
643 disconnect(newdoc, TQ_SIGNAL(canceled( const TQString & )), this, TQ_SLOT(slotLoadCanceled( const TQString & )));
644}
645
646void KoMainWindow::slotLoadCanceled( const TQString & errMsg )
647{
648 kdDebug(30003) << "KoMainWindow::slotLoadCanceled" << endl;
649 if ( !errMsg.isEmpty() ) // empty when canceled by user
650 KMessageBox::error( this, errMsg );
651 // ... can't delete the document, it's the one who emitted the signal...
652
653 KoDocument* newdoc = (KoDocument *)(sender());
654 disconnect(newdoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
655 disconnect(newdoc, TQ_SIGNAL(completed()), this, TQ_SLOT(slotLoadCompleted()));
656 disconnect(newdoc, TQ_SIGNAL(canceled( const TQString & )), this, TQ_SLOT(slotLoadCanceled( const TQString & )));
657
658 newdoc->removeShell(this);
659 delete newdoc;
660}
661
662void KoMainWindow::slotSaveCanceled( const TQString &errMsg )
663{
664 kdDebug(30003) << "KoMainWindow::slotSaveCanceled" << endl;
665 if ( !errMsg.isEmpty() ) // empty when canceled by user
666 KMessageBox::error( this, errMsg );
667 slotSaveCompleted();
668}
669
670void KoMainWindow::slotSaveCompleted()
671{
672 kdDebug(30003) << "KoMainWindow::slotSaveCompleted" << endl;
673 KoDocument* pDoc = (KoDocument *)(sender());
674 disconnect(pDoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
675 disconnect(pDoc, TQ_SIGNAL(completed()), this, TQ_SLOT(slotSaveCompleted()));
676 disconnect(pDoc, TQ_SIGNAL(canceled( const TQString & )),
677 this, TQ_SLOT(slotSaveCanceled( const TQString & )));
678}
679
680// returns true if we should save, false otherwise.
681bool KoMainWindow::exportConfirmation( const TQCString &outputFormat )
682{
683 if (!rootDocument()->wantExportConfirmation()) return true;
684 KMimeType::Ptr mime = KMimeType::mimeType( outputFormat );
685
686 const bool neverHeardOfIt = ( mime->name() == KMimeType::defaultMimeType() );
687 TQString comment = neverHeardOfIt ?
688 i18n( "%1 (unknown file type)" ).arg( outputFormat.data() )
689 : mime->comment();
690
691 // Warn the user
692 int ret;
693 if (!isExporting ()) // File --> Save
694 {
696 (
697 this,
698 i18n( "<qt>Saving as a %1 may result in some loss of formatting."
699 "<p>Do you still want to save in this format?</qt>" )
700 .arg( TQString( "<b>%1</b>" ).arg( comment ) ), // in case we want to remove the bold later
701 i18n( "Confirm Save" ),
702 KStdGuiItem::save (),
703 "NonNativeSaveConfirmation",
704 true
705 );
706 }
707 else // File --> Export
708 {
710 (
711 this,
712 i18n( "<qt>Exporting as a %1 may result in some loss of formatting."
713 "<p>Do you still want to export to this format?</qt>" )
714 .arg( TQString( "<b>%1</b>" ).arg( comment ) ), // in case we want to remove the bold later
715 i18n( "Confirm Export" ),
716 i18n ("Export"),
717 "NonNativeExportConfirmation", // different to the one used for Save (above)
718 true
719 );
720 }
721
722 return (ret == KMessageBox::Continue);
723}
724
725bool KoMainWindow::saveDocument( bool saveas, bool silent )
726{
727 KoDocument* pDoc = rootDocument();
728 if(!pDoc)
729 return true;
730
731 bool reset_url;
732 if ( pDoc->url().isEmpty() )
733 {
734 emit saveDialogShown();
735 reset_url = true;
736 saveas = true;
737 }
738 else
739 reset_url = false;
740
741 connect(pDoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
742 connect(pDoc, TQ_SIGNAL(completed()), this, TQ_SLOT(slotSaveCompleted()));
743 connect(pDoc, TQ_SIGNAL(canceled( const TQString & )),
744 this, TQ_SLOT(slotSaveCanceled( const TQString & )));
745
746 KURL oldURL = pDoc->url();
747 TQString oldFile = pDoc->file();
748 TQCString _native_format = pDoc->nativeFormatMimeType();
749 TQCString oldOutputFormat = pDoc->outputMimeType();
750 int oldSpecialOutputFlag = pDoc->specialOutputFlag();
751 KURL suggestedURL = pDoc->url();
752
753 TQStringList mimeFilter = KoFilterManager::mimeFilter( _native_format, KoFilterManager::Export, pDoc->extraNativeMimeTypes() );
754 if (mimeFilter.findIndex (oldOutputFormat) < 0 && !isExporting())
755 {
756 kdDebug(30003) << "KoMainWindow::saveDocument no export filter for '" << oldOutputFormat << "'" << endl;
757
758 // --- don't setOutputMimeType in case the user cancels the Save As
759 // dialog and then tries to just plain Save ---
760
761 // suggest a different filename extension (yes, we fortunately don't all live in a world of magic :))
762 TQString suggestedFilename = suggestedURL.fileName ();
763 if ( !suggestedFilename.isEmpty () ) // ".kwd" looks strange for a name
764 {
765 int c = suggestedFilename.findRev ('.');
766
767 KMimeType::Ptr mime = KMimeType::mimeType( _native_format );
768 TQString ext = mime->property( "X-TDE-NativeExtension" ).toString();
769 if (!ext.isEmpty ())
770 {
771 if (c < 0)
772 suggestedFilename += ext;
773 else
774 suggestedFilename = suggestedFilename.left (c) + ext;
775 }
776 else // current filename extension wrong anyway
777 {
778 if (c > 0)
779 {
780 // this assumes that a . signifies an extension, not just a .
781 suggestedFilename = suggestedFilename.left (c);
782 }
783 }
784
785 suggestedURL.setFileName (suggestedFilename);
786 }
787
788 // force the user to choose outputMimeType
789 saveas = true;
790 }
791
792 bool ret = false;
793
794 if ( pDoc->url().isEmpty() || saveas )
795 {
796 // if you're just File/Save As'ing to change filter options you
797 // don't want to be reminded about overwriting files etc.
798 bool justChangingFilterOptions = false;
799
800 KoFileDialog *dialog = new KoFileDialog( (isExporting() && !d->m_lastExportURL.isEmpty() )? d->m_lastExportURL.url () : suggestedURL.url (),
801 TQString(), this, "file dialog", true);
802
803 if (!isExporting())
804 dialog->setCaption( i18n("Save Document As") );
805 else
806 dialog->setCaption( i18n("Export Document As") );
807
808 dialog->setOperationMode( KFileDialog::Saving );
809 dialog->setSpecialMimeFilter( mimeFilter,
810 isExporting() ? d->m_lastExportFormat : pDoc->mimeType(),
811 isExporting() ? d->m_lastExportSpecialOutputFlag : oldSpecialOutputFlag,
812 _native_format,
813 pDoc->supportedSpecialFormats() );
814
815 KURL newURL;
816 TQCString outputFormat = _native_format;
817 int specialOutputFlag = 0;
818 bool bOk;
819 do {
820 bOk=true;
821 if(dialog->exec()==TQDialog::Accepted) {
822 newURL=dialog->selectedURL();
823 outputFormat=dialog->currentMimeFilter().latin1();
824 specialOutputFlag = dialog->specialEntrySelected();
825 kdDebug(30003) << "KoMainWindow::saveDocument outputFormat = " << outputFormat << endl;
826
827 if (!isExporting())
828 justChangingFilterOptions = (newURL == pDoc->url()) &&
829 (outputFormat == pDoc->mimeType()) &&
830 (specialOutputFlag == oldSpecialOutputFlag);
831 else
832 justChangingFilterOptions = (newURL == d->m_lastExportURL) &&
833 (outputFormat == d->m_lastExportFormat) &&
834 (specialOutputFlag == d->m_lastExportSpecialOutputFlag);
835 }
836 else
837 {
838 bOk = false;
839 break;
840 }
841
842 if ( newURL.isEmpty() )
843 {
844 bOk = false;
845 break;
846 }
847
848 // adjust URL before doing checks on whether the file exists.
849 if ( specialOutputFlag == KoDocument::SaveAsDirectoryStore ) {
850 TQString fileName = newURL.fileName();
851 if ( fileName != "content.xml" ) {
852 newURL.addPath( "content.xml" );
853 }
854 }
855
856 // this file exists and we are not just clicking "Save As" to change filter options
857 // => ask for confirmation
858 if ( TDEIO::NetAccess::exists( newURL, false /*will write*/, this ) && !justChangingFilterOptions )
859 {
860 bOk = KMessageBox::questionYesNo( this,
861 i18n("A document with this name already exists.\n"\
862 "Do you want to overwrite it?"),
863 i18n("Warning") ) == KMessageBox::Yes;
864 }
865 } while ( !bOk );
866
867 delete dialog;
868
869 if (bOk)
870 {
871 bool wantToSave = true;
872
873 // don't change this line unless you know what you're doing :)
874 if (!justChangingFilterOptions || pDoc->confirmNonNativeSave (isExporting ())) {
875 if ( !pDoc->isNativeFormat( outputFormat ) )
876 wantToSave = exportConfirmation( outputFormat );
877 }
878
879 if (wantToSave)
880 {
881 //
882 // Note:
883 // If the user is stupid enough to Export to the current URL,
884 // we do _not_ change this operation into a Save As. Reasons
885 // follow:
886 //
887 // 1. A check like "isExporting() && oldURL == newURL"
888 // doesn't _always_ work on case-insensitive filesystems
889 // and inconsistent behaviour is bad.
890 // 2. It is probably not a good idea to change pDoc->mimeType
891 // and friends because the next time the user File/Save's,
892 // (not Save As) they won't be expecting that they are
893 // using their File/Export settings
894 //
895 // As a bad side-effect of this, the modified flag will not
896 // be updated and it is possible that what is currently on
897 // their screen is not what is stored on disk (through loss
898 // of formatting). But if you are dumb enough to change
899 // mimetype but not the filename, then arguably, _you_ are
900 // the "bug" :)
901 //
902 // - Clarence
903 //
904
905
906 pDoc->setOutputMimeType( outputFormat, specialOutputFlag );
907 if (!isExporting ()) // Save As
908 {
909 ret = pDoc->saveAs( newURL );
910
911 if (ret)
912 {
913 kdDebug(30003) << "Successful Save As!" << endl;
914 addRecentURL( newURL );
915 }
916 else
917 {
918 kdDebug(30003) << "Failed Save As!" << endl;
919 pDoc->setURL( oldURL ), pDoc->setFile( oldFile );
920 pDoc->setOutputMimeType( oldOutputFormat, oldSpecialOutputFlag );
921 }
922 }
923 else // Export
924 {
925 ret = pDoc->exp0rt( newURL );
926
927 if (ret)
928 {
929 // a few file dialog convenience things
930 d->m_lastExportURL = newURL;
931 d->m_lastExportFormat = outputFormat;
932 d->m_lastExportSpecialOutputFlag = specialOutputFlag;
933 }
934
935 // always restore output format
936 pDoc->setOutputMimeType( oldOutputFormat, oldSpecialOutputFlag );
937 }
938 } // if (wantToSave)
939 else
940 ret = false;
941 } // if (bOk)
942 else
943 ret = false;
944 }
945 else { // saving
946 bool needConfirm = pDoc->confirmNonNativeSave( false ) &&
947 !pDoc->isNativeFormat( oldOutputFormat );
948 if (!needConfirm ||
949 (needConfirm && exportConfirmation( oldOutputFormat /* not so old :) */ ))
950 )
951 {
952 // be sure pDoc has the correct outputMimeType!
953 ret = pDoc->save();
954
955 if (!ret)
956 {
957 kdDebug(30003) << "Failed Save!" << endl;
958 pDoc->setURL( oldURL ), pDoc->setFile( oldFile );
959 }
960 }
961 else
962 ret = false;
963 }
964
965// Now that there's a File/Export option, this is no longer necessary.
966// If you continue to use File/Save to export to a foreign format,
967// this signals your intention to continue working in a foreign format.
968// You have already been warned by the DoNotAskAgain exportConfirmation
969// about losing formatting when you first saved so don't set modified
970// here or else it will be reported as a bug by some MSOffice user.
971// You have been warned! Do not click DoNotAskAgain!!!
972#if 0
973 if (ret && !isExporting())
974 {
975 // When exporting to a non-native format, we don't reset modified.
976 // This way the user will be reminded to save it again in the native format,
977 // if he/she doesn't want to lose formatting.
978 if ( wasModified && pDoc->outputMimeType() != _native_format )
979 pDoc->setModified( true );
980 }
981#endif
982
983 if (!ret && reset_url)
984 pDoc->resetURL(); //clean the suggested filename as the save dialog was rejected
985 else if (! silent) // don't let the document change the window caption
986 pDoc->setTitleModified();
987 return ret;
988}
989
990void KoMainWindow::closeEvent(TQCloseEvent *e) {
991 if(queryClose()) {
992 saveWindowSettings();
993 setRootDocument(0L);
995 }
996}
997
998void KoMainWindow::saveWindowSettings()
999{
1000 if (d->m_windowSizeDirty && rootDocument())
1001 {
1002 // Save window size into the config file of our instance
1003 instance()->config()->setGroup( "MainWindow" );
1004 //kdDebug(30003) << "KoMainWindow::saveWindowSettings" << endl;
1005 saveWindowSize( instance()->config() );
1006 d->m_windowSizeDirty = false;
1007 // Save toolbar position into the config file of the app, under the doc's instance name
1008 //kdDebug(30003) << "KoMainWindow::closeEvent -> saveMainWindowSettings rootdoc's instance=" << rootDocument()->instance()->instanceName() << endl;
1009 saveMainWindowSettings( TDEGlobal::config(), rootDocument()->instance()->instanceName() );
1010 TDEGlobal::config()->sync();
1011 resetAutoSaveSettings(); // Don't let TDEMainWindow override the good stuff we wrote down
1012 }
1013}
1014
1015void KoMainWindow::resizeEvent( TQResizeEvent * e )
1016{
1017 d->m_windowSizeDirty = true;
1018 KParts::MainWindow::resizeEvent( e );
1019}
1020
1022{
1023 if ( rootDocument() == 0 )
1024 return true;
1025 //kdDebug(30003) << "KoMainWindow::queryClose() viewcount=" << rootDocument()->viewCount()
1026 // << " shellcount=" << rootDocument()->shellCount() << endl;
1027 if ( !d->m_forQuit && rootDocument()->shellCount() > 1 )
1028 // there are more open, and we are closing just one, so no problem for closing
1029 return true;
1030
1031 // see DTOR for a descr. of the test
1032 if ( d->m_rootDoc->isEmbedded() )
1033 return true;
1034
1035 // main doc + internally stored child documents
1036 if ( d->m_rootDoc->isModified() )
1037 {
1038 TQString name;
1039 if ( rootDocument()->documentInfo() )
1040 {
1041 name = rootDocument()->documentInfo()->title();
1042 }
1043 if ( name.isEmpty() )
1044 name = rootDocument()->url().fileName();
1045
1046 if ( name.isEmpty() )
1047 name = i18n( "Untitled" );
1048
1049 int res = KMessageBox::warningYesNoCancel( this,
1050 i18n( "<p>The document <b>'%1'</b> has been modified.</p><p>Do you want to save it?</p>" ).arg(name),
1051 TQString(),
1052 KStdGuiItem::save(),
1053 KStdGuiItem::discard());
1054
1055 switch(res) {
1056 case KMessageBox::Yes : {
1057 d->m_rootDoc->setDoNotSaveExtDoc(); // external docs are saved later
1058 bool isNative = ( d->m_rootDoc->outputMimeType() == d->m_rootDoc->nativeFormatMimeType() );
1059 if (! saveDocument( !isNative ) )
1060 return false;
1061 break;
1062 }
1063 case KMessageBox::No :
1065 rootDocument()->setModified( false ); // Now when queryClose() is called by closeEvent it won't do anything.
1066 break;
1067 default : // case KMessageBox::Cancel :
1068 return false;
1069 }
1070 }
1071
1072 if ( d->m_rootDoc->queryCloseExternalChildren() == KMessageBox::Cancel )
1073 {
1074 return false;
1075 }
1076
1077 return true;
1078}
1079
1080// Helper method for slotFileNew and slotFileClose
1081void KoMainWindow::chooseNewDocument( int /*KoDocument::InitDocFlags*/ initDocFlags )
1082{
1083 KoDocument* doc = rootDocument();
1084 KoDocument *newdoc = createDoc();
1085
1086 if ( !newdoc )
1087 return;
1088
1089 //FIXME: This needs to be handled differently
1090 connect(newdoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
1091 disconnect(newdoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
1092
1093 if ( ( !doc && ( initDocFlags == KoDocument::InitDocFileNew ) ) || ( doc && !doc->isEmpty() ) )
1094 {
1095 KoMainWindow *s = new KoMainWindow( newdoc->instance() );
1096 s->show();
1097 newdoc->addShell( s );
1098 newdoc->showStartUpWidget( s, true /*Always show widget*/ );
1099 return;
1100 }
1101
1102 if( doc ) {
1103 setRootDocument( 0 );
1104 delete d->m_rootDoc;
1105 d->m_rootDoc = 0;
1106 }
1107
1108 newdoc->addShell( this );
1109 newdoc->showStartUpWidget( this, true /*Always show widget*/ );
1110}
1111
1113{
1114 chooseNewDocument( KoDocument::InitDocFileNew );
1115}
1116
1118{
1119 KFileDialog *dialog = new KFileDialog(":OpenDialog", TQString(), this, "file dialog", true);
1120 if (!isImporting())
1121 dialog->setCaption( i18n("Open Document") );
1122 else
1123 dialog->setCaption( i18n("Import Document") );
1124
1125 // The few lines below need to be kept in sync with KoTemplateChooseDia::setupFileDialog
1126 const TQStringList mimeFilter = KoFilterManager::mimeFilter( KoDocument::readNativeFormatMimeType(),
1127 KoFilterManager::Import,
1129 dialog->setMimeFilter( mimeFilter );
1130 if(dialog->exec()!=TQDialog::Accepted) {
1131 delete dialog;
1132 return;
1133 }
1134 KURL url( dialog->selectedURL() );
1135 delete dialog;
1136
1137 if ( url.isEmpty() )
1138 return;
1139
1140 (void) openDocument( url );
1141}
1142
1143void KoMainWindow::slotFileOpenRecent( const KURL & url )
1144{
1145 (void) openDocument( url );
1146}
1147
1149{
1150 if ( saveDocument() )
1151 emit documentSaved();
1152}
1153
1155{
1156 if ( saveDocument( true ) )
1157 emit documentSaved();
1158}
1159
1161{
1162 if ( !rootDocument() )
1163 return;
1164
1165 KoDocumentInfo *docInfo = rootDocument()->documentInfo();
1166
1167 if ( !docInfo )
1168 return;
1169
1170 KoDocumentInfoDlg *dlg = new KoDocumentInfoDlg( docInfo, this, "documentInfoDlg" );
1171 if ( dlg->exec() )
1172 {
1173 dlg->save();
1174 rootDocument()->setModified( true );
1176 }
1177
1178 delete dlg;
1179}
1180
1182{
1183 if (queryClose())
1184 {
1185 saveWindowSettings();
1186 setRootDocument( 0 ); // don't delete this shell when deleting the document
1187 delete d->m_rootDoc;
1188 d->m_rootDoc = 0;
1189 chooseNewDocument( KoDocument::InitDocFileClose );
1190 }
1191}
1192
1194{
1195 close();
1196}
1197
1198void KoMainWindow::print(bool quick) {
1199 if ( !rootView() )
1200 {
1201 kdDebug(30003) << "KoMainWindow::slotFilePrint : No root view!" << endl;
1202 return;
1203 }
1204
1205 KPrinter printer( true /*, TQPrinter::HighResolution*/ );
1206 TQString title = rootView()->koDocument()->documentInfo()->title();
1207 TQString fileName = rootView()->koDocument()->url().fileName();
1208
1209 // strip off the native extension (I don't want foobar.kwd.ps when printing into a file)
1210 KMimeType::Ptr mime = KMimeType::mimeType( rootView()->koDocument()->outputMimeType() );
1211 if ( mime ) {
1212 TQString extension = mime->property( "X-TDE-NativeExtension" ).toString();
1213
1214 if ( fileName.endsWith( extension ) )
1215 fileName.truncate( fileName.length() - extension.length() );
1216 }
1217
1218 if ( title.isEmpty() )
1219 title = fileName;
1220 if ( title.isEmpty() ) {
1221 // #139905 - breaks message freeze though
1222 //const TQString programName = instance()->aboutData() ? instance()->aboutData()->programName() : instance()->instanceName();
1223 //title = i18n("%1 unsaved document (%2)").arg(programName).arg(TDEGlobal::locale()->formatDate(TQDate::currentDate(), true/*short*/));
1224 }
1225 printer.setDocName( title );
1226 printer.setDocFileName( fileName );
1227 printer.setDocDirectory( rootView()->koDocument()->url().directory() );
1228
1229 // ### TODO: apply global koffice settings here
1230
1231 rootView()->setupPrinter( printer );
1232
1233 if ( quick || printer.setup( this ) )
1234 rootView()->print( printer );
1235}
1236
1237
1239{
1240 print(false);
1241}
1242
1244{
1245 if ( !rootView() )
1246 {
1247 kdWarning() << "KoMainWindow::slotFilePrint : No root view!" << endl;
1248 return;
1249 }
1250 KPrinter printer( false );
1251 KTempFile tmpFile;
1252 // The temp file is deleted by KoPrintPreview
1253
1254 // This line has to be before setupPrinter to let the apps decide what to
1255 // print and what not (if they want to :)
1256 printer.setFromTo( printer.minPage(), printer.maxPage() );
1257 printer.setPreviewOnly( true );
1258 rootView()->setupPrinter( printer );
1259
1260 TQString oldFileName = printer.outputFileName();
1261 printer.setOutputFileName( tmpFile.name() );
1262 int oldNumCopies = printer.numCopies();
1263 printer.setNumCopies( 1 );
1264 // Disable tdeprint's own preview, we'd get two. This shows that KPrinter needs
1265 // a "don't use the previous settings" mode. The current way is really too much of a hack.
1266 TQString oldKDEPreview = printer.option( "kde-preview" );
1267 printer.setOption( "kde-preview", "0" );
1268
1269 rootView()->print(printer);
1270 //KoPrintPreview::preview(this, "KoPrintPreviewDialog", tmpFile.name());
1271
1272 // Restore previous values
1273 printer.setOutputFileName( oldFileName );
1274 printer.setNumCopies( oldNumCopies );
1275 printer.setOption( "kde-preview", oldKDEPreview );
1276}
1277
1279{
1280 guiFactory()->configureShortcuts();
1281}
1282
1284{
1285 if (rootDocument())
1286 saveMainWindowSettings( TDEGlobal::config(), rootDocument()->instance()->instanceName() );
1287 KEditToolbar edit(factory(), this);
1288 connect(&edit,TQ_SIGNAL(newToolbarConfig()),this,TQ_SLOT(slotNewToolbarConfig()));
1289 (void) edit.exec();
1290}
1291
1293{
1294 if (rootDocument())
1295 applyMainWindowSettings( TDEGlobal::config(), rootDocument()->instance()->instanceName() );
1296 KXMLGUIFactory *factory = guiFactory();
1297
1298 // Check if there's an active view
1299 if( !d->m_activeView )
1300 return;
1301
1302 // This gets plugged in even for embedded views
1303 factory->plugActionList(d->m_activeView, "view_closeallviews",
1304 d->m_veryHackyActionList);
1305
1306 // This one only for root views
1307 if(d->m_rootViews.findRef(d->m_activeView)!=-1)
1308 factory->plugActionList(d->m_activeView, "view_split",
1309 d->m_splitViewActionList );
1310 plugActionList( "toolbarlist", d->m_toolbarList );
1311}
1312
1314{
1315 //kdDebug(30003) << "KoMainWindow::slotToolbarToggled " << sender()->name() << " toggle=" << true << endl;
1316 // The action (sender) and the toolbar have the same name
1317 TDEToolBar * bar = toolBar( sender()->name() );
1318 if (bar)
1319 {
1320 if (toggle)
1321 bar->show();
1322 else
1323 bar->hide();
1324
1325 if (rootDocument())
1326 saveMainWindowSettings( TDEGlobal::config(), rootDocument()->instance()->instanceName() );
1327 }
1328 else
1329 kdWarning(30003) << "slotToolbarToggled : Toolbar " << sender()->name() << " not found!" << endl;
1330}
1331
1332bool KoMainWindow::toolbarIsVisible(const char *tbName)
1333{
1334 TQWidget *tb = toolBar( tbName);
1335 return !tb->isHidden();
1336}
1337
1338void KoMainWindow::showToolbar( const char * tbName, bool shown )
1339{
1340 TQWidget * tb = toolBar( tbName );
1341 if ( !tb )
1342 {
1343 kdWarning(30003) << "KoMainWindow: toolbar " << tbName << " not found." << endl;
1344 return;
1345 }
1346 if ( shown )
1347 tb->show();
1348 else
1349 tb->hide();
1350
1351 // Update the action appropriately
1352 TQPtrListIterator<TDEAction> it( d->m_toolbarList );
1353 for ( ; it.current() ; ++it )
1354 if ( !strcmp( it.current()->name(), tbName ) )
1355 {
1356 //kdDebug(30003) << "KoMainWindow::showToolbar setChecked " << shown << endl;
1357 static_cast<TDEToggleAction *>(it.current())->setChecked( shown );
1358 break;
1359 }
1360}
1361
1363 d->m_splitted=true;
1364 d->m_rootViews.append(d->m_rootDoc->createView(d->m_splitter, "splitted-view"));
1365 d->m_rootViews.current()->show();
1366 d->m_rootViews.current()->setPartManager( d->m_manager );
1367 d->m_manager->setActivePart( d->m_rootDoc, d->m_rootViews.current() );
1368 d->m_removeView->setEnabled(true);
1369 d->m_orientation->setEnabled(true);
1370}
1371
1373
1374 // Attention: Very touchy code... you know what you're doing? Goooood :)
1375 d->m_forQuit=true;
1376 if(queryClose()) {
1377 // In case the document is embedded we close all open "extra-shells"
1378 if(d->m_rootDoc && d->m_rootDoc->isEmbedded()) {
1379 hide();
1380 d->m_rootDoc->removeShell(this);
1381 TQPtrListIterator<KoMainWindow> it(d->m_rootDoc->shells());
1382 while (it.current()) {
1383 it.current()->hide();
1384 delete it.current(); // this updates the lists' current pointer and thus
1385 // the iterator (the shell dtor calls removeShell)
1386 d->m_rootDoc=0;
1387 }
1388 }
1389 // not embedded -> destroy the document and all shells/views ;)
1390 else
1391 setRootDocument( 0L );
1392 close(); // close this window (and quit the app if necessary)
1393 }
1394 d->m_forQuit=false;
1395}
1396
1397void KoMainWindow::slotRemoveView() {
1398 KoView *view;
1399 if(d->m_rootViews.findRef(d->m_activeView)!=-1)
1400 view=d->m_rootViews.current();
1401 else
1402 view=d->m_rootViews.first();
1403 view->hide();
1404 if ( !d->m_rootViews.removeRef(view) )
1405 kdWarning() << "view not found in d->m_rootViews!" << endl;
1406
1407 if(d->m_rootViews.count()==1)
1408 {
1409 d->m_removeView->setEnabled(false);
1410 d->m_orientation->setEnabled(false);
1411 }
1412 // Prevent the view's destroyed() signal from triggering GUI rebuilding (too early)
1413 d->m_manager->setActivePart( 0, 0 );
1414
1415 delete view;
1416 view=0L;
1417
1418 d->m_rootViews.first()->setPartManager( d->m_manager );
1419 d->m_manager->setActivePart( d->m_rootDoc, d->m_rootViews.first() );
1420
1421 if(d->m_rootViews.count()==1)
1422 d->m_splitted=false;
1423}
1424
1425void KoMainWindow::slotSetOrientation() {
1426 d->m_splitter->setOrientation(static_cast<TQt::Orientation>
1427 (d->m_orientation->currentItem()));
1428}
1429
1430void KoMainWindow::slotProgress(int value) {
1431 //kdDebug(30003) << "KoMainWindow::slotProgress " << value << endl;
1432 if(value==-1) {
1433 if ( d->m_progress )
1434 {
1435 statusBar()->removeWidget(d->m_progress);
1436 delete d->m_progress;
1437 d->m_progress=0L;
1438 }
1439 d->m_firstTime=true;
1440 return;
1441 }
1442 if(d->m_firstTime)
1443 {
1444 // The statusbar might not even be created yet.
1445 // So check for that first, and create it if necessary
1446 TQObjectList *l = queryList( "TQStatusBar" );
1447 if ( !l || !l->first() ) {
1448 statusBar()->show();
1449 TQApplication::sendPostedEvents( this, TQEvent::ChildInserted );
1450 setUpLayout();
1451 }
1452 delete l;
1453
1454 if ( d->m_progress )
1455 {
1456 statusBar()->removeWidget(d->m_progress);
1457 delete d->m_progress;
1458 d->m_progress=0L;
1459 }
1460 statusBar()->setMaximumHeight(statusBar()->height());
1461 d->m_progress=new KProgress(statusBar());
1462 //d->m_progress->setMaximumHeight(statusBar()->height());
1463 statusBar()->addWidget( d->m_progress, 0, true );
1464 d->m_progress->show();
1465 d->m_firstTime=false;
1466 }
1467 d->m_progress->setProgress(value);
1468 kapp->processEvents();
1469}
1470
1471
1472void KoMainWindow::slotActivePartChanged( KParts::Part *newPart )
1473{
1474
1475 // This looks very much like KParts::MainWindow::createGUI, but we have
1476 // to reimplement it because it works with an active part, whereas we work
1477 // with an active view _and_ an active part, depending for what.
1478 // Both are KXMLGUIClients, but e.g. the plugin query needs a TQObject.
1479 //kdDebug(30003) << "KoMainWindow::slotActivePartChanged( Part * newPart) newPart = " << newPart << endl;
1480 //kdDebug(30003) << "current active part is " << d->m_activePart << endl;
1481
1482 if ( d->m_activePart && d->m_activePart == newPart && !d->m_splitted )
1483 {
1484 //kdDebug(30003) << "no need to change the GUI" << endl;
1485 return;
1486 }
1487
1488 KXMLGUIFactory *factory = guiFactory();
1489
1490 setUpdatesEnabled( false );
1491
1492 if ( d->m_activeView )
1493 {
1494 KParts::GUIActivateEvent ev( false );
1495 TQApplication::sendEvent( d->m_activePart, &ev );
1496 TQApplication::sendEvent( d->m_activeView, &ev );
1497
1498
1499 factory->removeClient( d->m_activeView );
1500
1501 unplugActionList( "toolbarlist" );
1502 d->m_toolbarList.clear(); // deletes the actions
1503 }
1504
1505 if ( !d->bMainWindowGUIBuilt )
1506 {
1507 // Load mainwindow plugins
1508 KParts::Plugin::loadPlugins( this, this, instance(), true );
1509 createShellGUI();
1510 }
1511
1512 if ( newPart && d->m_manager->activeWidget() && d->m_manager->activeWidget()->inherits( "KoView" ) )
1513 {
1514 d->m_activeView = (KoView *)d->m_manager->activeWidget();
1515 d->m_activePart = newPart;
1516 //kdDebug(30003) << "new active part is " << d->m_activePart << endl;
1517
1518 factory->addClient( d->m_activeView );
1519
1520
1521 // This gets plugged in even for embedded views
1522 factory->plugActionList(d->m_activeView, "view_closeallviews",
1523 d->m_veryHackyActionList);
1524 // This one only for root views
1525 if(d->m_rootViews.findRef(d->m_activeView)!=-1)
1526 factory->plugActionList(d->m_activeView, "view_split", d->m_splitViewActionList );
1527
1528 // Position and show toolbars according to user's preference
1529 setAutoSaveSettings( newPart->instance()->instanceName(), false );
1530
1531 // Create and plug toolbar list for Settings menu
1532 //TQPtrListIterator<TDEToolBar> it = toolBarIterator();
1533 TQPtrList<TQWidget> toolBarList = factory->containers( "ToolBar" );
1534 TQPtrListIterator<TQWidget> it( toolBarList );
1535 for ( ; it.current() ; ++it )
1536 {
1537 if ( it.current()->inherits("TDEToolBar") )
1538 {
1539 TDEToolBar * tb = static_cast<TDEToolBar *>(it.current());
1540 TDEToggleAction * act = new TDEToggleAction( i18n("Show %1 Toolbar").arg( tb->text() ), 0,
1541 actionCollection(), tb->name() );
1542 act->setCheckedState(i18n("Hide %1 Toolbar").arg( tb->text() ));
1543 connect( act, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( slotToolbarToggled( bool ) ) );
1544 act->setChecked ( !tb->isHidden() );
1545 d->m_toolbarList.append( act );
1546 }
1547 else
1548 kdWarning(30003) << "Toolbar list contains a " << it.current()->className() << " which is not a toolbar!" << endl;
1549 }
1550 plugActionList( "toolbarlist", d->m_toolbarList );
1551
1552 // Send the GUIActivateEvent only now, since it might show/hide toolbars too
1553 // (and this has priority over applyMainWindowSettings)
1554 KParts::GUIActivateEvent ev( true );
1555 TQApplication::sendEvent( d->m_activePart, &ev );
1556 TQApplication::sendEvent( d->m_activeView, &ev );
1557 }
1558 else
1559 {
1560 d->m_activeView = 0L;
1561 d->m_activePart = 0L;
1562 }
1563 setUpdatesEnabled( true );
1564}
1565
1567{
1568 if ( !d->statusBarLabel )
1569 {
1570 d->statusBarLabel = new TQLabel( statusBar() );
1571 statusBar()->addWidget( d->statusBarLabel, 1, true );
1572 }
1573 return d->statusBarLabel;
1574}
1575
1577{
1578 m_recent->setMaxItems( _number );
1579}
1580
1581DCOPObject * KoMainWindow::dcopObject()
1582{
1583 if ( !d->m_dcopObject )
1584 {
1585 d->m_dcopObject = new KoMainWindowIface( this );
1586 }
1587
1588 return d->m_dcopObject;
1589}
1590
1592{
1593 if (!rootDocument())
1594 return;
1595
1596 // Subject = Document file name
1597 // Attachment = The current file
1598 // Message Body = The current document in HTML export? <-- This may be an option.
1599 TQString theSubject;
1600 TQStringList urls;
1601 TQString fileURL;
1602 if (rootDocument()->url ().isEmpty () ||
1603 rootDocument()->isModified())
1604 {
1605 //Save the file as a temporary file
1606 bool const tmp_modified = rootDocument()->isModified();
1607 KURL const tmp_url = rootDocument()->url();
1608 TQCString const tmp_mimetype = rootDocument()->outputMimeType();
1609 KTempFile tmpfile; //TODO: The temorary file should be deleted when the mail program is closed
1610 KURL u;
1611 u.setPath(tmpfile.name());
1612 rootDocument()->setURL(u);
1613 rootDocument()->setModified(true);
1614 rootDocument()->setOutputMimeType(rootDocument()->nativeFormatMimeType());
1615
1616 saveDocument(false, true);
1617
1618 fileURL = tmpfile.name();
1619 theSubject = i18n("Document");
1620 urls.append( fileURL );
1621
1622 rootDocument()->setURL(tmp_url);
1623 rootDocument()->setModified(tmp_modified);
1624 rootDocument()->setOutputMimeType(tmp_mimetype);
1625 }
1626 else
1627 {
1628 fileURL = rootDocument()->url().url();
1629 theSubject = i18n("Document - %1").arg(rootDocument()->url().fileName(false));
1630 urls.append( fileURL );
1631 }
1632
1633 kdDebug(30003) << "(" << fileURL <<")" << endl;
1634
1635 if (!fileURL.isEmpty())
1636 {
1637 kapp->invokeMailer(TQString(), TQString(), TQString(), theSubject,
1638 TQString(), //body
1639 TQString(),
1640 urls); // attachments
1641 }
1642}
1643
1645{
1646 KoVersionDialog *dlg = new KoVersionDialog( this );
1647 dlg->exec();
1648 delete dlg;
1649}
1650
1652{
1653 KoDocument* pDoc = rootDocument();
1654 if(!pDoc || pDoc->url().isEmpty() || !pDoc->isModified())
1655 return;
1656
1657 bool bOk = KMessageBox::questionYesNo( this,
1658 i18n("You will lose all your changes!\n"
1659 "Do you want to continue?"),
1660 i18n("Warning") ) == KMessageBox::Yes;
1661 if ( !bOk )
1662 return;
1663
1664 KURL url = pDoc->url();
1665 if ( pDoc && !pDoc->isEmpty() )
1666 {
1667 setRootDocument( 0L ); // don't delete this shell when deleting the document
1668 delete d->m_rootDoc;
1669 d->m_rootDoc = 0L;
1670 }
1671 openDocument( url );
1672 return;
1673
1674}
1675
1677{
1678 kdDebug(30003) << "slotImportFile()" << endl;
1679
1680 d->m_isImporting = true;
1681 slotFileOpen();
1682 d->m_isImporting = false;
1683}
1684
1686{
1687 kdDebug(30003) << "slotExportFile()" << endl;
1688
1689 d->m_isExporting = true;
1691 d->m_isExporting = false;
1692}
1693
1695{
1696 return d->m_isImporting;
1697}
1698
1700{
1701 return d->m_isExporting;
1702}
1703
1705{
1706 d->m_docToOpen = doc;
1707}
1708
1709#include <KoMainWindow.moc>
This file is part of the KDE/KOffice project.
KKbdAccessExtensions is an object that improves accessibility for motor impaired users who may not be...
static void error(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, int options=Notify)
static int questionYesNo(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const KGuiItem &buttonYes=KStdGuiItem::yes(), const KGuiItem &buttonNo=KStdGuiItem::no(), const TQString &dontAskAgainName=TQString::null, int options=Notify)
static int warningYesNoCancel(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const KGuiItem &buttonYes=KStdGuiItem::yes(), const KGuiItem &buttonNo=KStdGuiItem::no(), const TQString &dontAskAgainName=TQString::null, int options=Notify)
static int warningContinueCancel(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const KGuiItem &buttonContinue=KStdGuiItem::cont(), const TQString &dontAskAgainName=TQString::null, int options=Notify)
MainWindow(TQWidget *parent, const char *name=0L, WFlags f=(WFlags)(WType_TopLevel|WDestructiveClose))
virtual void setInstance(TDEInstance *instance)
void setIgnoreScrollBars(bool ignore)
PartManager(TQWidget *parent, const char *name=0L)
void setActivationButtonMask(short int buttonMask)
void setSelectionPolicy(SelectionPolicy policy)
void setAllowNestedParts(bool allow)
virtual void setSelectable(bool selectable)
static void loadPlugins(TQObject *parent, const TDEInstance *instance)
virtual bool saveAs(const KURL &url)
virtual bool save()
void plugActionList(const TQString &name, const TQPtrList< TDEAction > &actionList)
void unplugActionList(const TQString &name)
virtual TDEInstance * instance() const
virtual void setXMLFile(const TQString &file, bool merge=false, bool setXMLDoc=true)
KXMLGUIFactory * factory() const
virtual TDEActionCollection * actionCollection() const
Represents an available KOffice component that supports the document interface.
KoDocument * createDoc(KoDocument *parent=0, const char *name=0) const
Uses the factory of the component to create a document.
The KOffice document class.
Definition KoDocument.h:61
void resetURL()
Sets the document URL to empty URL KParts doesn't allow this, but KOffice apps have e....
Definition KoDocument.h:818
void removeAutoSaveFiles()
Performs a cleanup of unneeded backup files.
virtual int supportedSpecialFormats() const
Return the set of SupportedSpecialFormats that the application wants to offer in the "Save" file dial...
bool checkAutoSaveFile()
Called by koApplication to check for an autosave file in $HOME.
KoView * createView(TQWidget *parent=0, const char *name=0)
Create a new view for the document.
static TQCString readNativeFormatMimeType(TDEInstance *instance=0)
Used by KoApplication, and by KoMainWindow, when no document exists yet.
virtual TQStringList extraNativeMimeTypes() const
Returns a list of the mimetypes considered "native", i.e.
bool isNativeFormat(const TQCString &mimetype) const
Checks whether a given mimetype can be handled natively.
TQString & file()
Only use these functions to restore m_file (in KoMainWindow) after a failed save (remember to use set...
Definition KoDocument.h:846
virtual void removeShell(KoMainWindow *shell)
Removes the shell from the list.
static TQStringList readExtraNativeMimeTypes(TDEInstance *instance=0)
Used by KoMainWindow, when no document exists yet.
TQCString mimeType() const
Returns the actual mimetype of the document.
bool isEmbedded() const
Is the document embedded?
bool import(const KURL &url)
Opens the document given by url, without storing the URL in the KoDocument.
bool confirmNonNativeSave(const bool exporting) const
Returns true if this document was the result of opening a foreign file format and if the user hasn't ...
virtual void addShell(KoMainWindow *shell)
Appends the shell to the list of shells which show this document as their root document.
virtual void setModified(bool _mod)
Sets the modified flag on the document.
virtual void initEmpty()
Initialize an empty document using default values.
int viewCount() const
virtual bool openURL(const KURL &url)
Reimplemented from KParts::ReadWritePart for internal reasons (for the autosave functionality).
KoDocumentInfo * documentInfo() const
virtual TQCString nativeFormatMimeType() const
To be preferred when a document exists.
bool exp0rt(const KURL &url)
Saves the document as url without changing the state of the KoDocument (URL, modified flag etc....
void setURL(const KURL &url)
Sets the document URL to url KParts doesn't really allow this, but it is needed for undo of setStoreI...
Definition KoDocument.h:836
bool isModified() const
Returns true if this document or any of its internal child documents are modified.
void setOutputMimeType(const TQCString &mimeType, int specialOutputFlag=0)
Set the format in which the document should be saved.
static KService::Ptr readNativeService(TDEInstance *instance=0)
With the help of instance or TDEApplication::instance() this method figures out which ....
virtual void showStartUpWidget(KoMainWindow *parent, bool alwaysShow=false)
Creates and shows the start up widget.
virtual bool isEmpty() const
Definition KoDocument.h:489
void setFile(const TQString &file)
Only use these functions to restore m_file (in KoMainWindow) after a failed save (remember to use set...
Definition KoDocument.h:856
virtual void setTitleModified()
Tells the document that its title has been modified, either because the modified status changes (this...
Extension to KFileDialog in order to add special entries to the filter combo, like "save as koffice-1...
static TQStringList mimeFilter()
The same method as KoFilterManager::mimeFilter but suited for KoShell.
bool isImporting() const
Returns whether or not the current slotFileOpen() or openDocument() call is actually an import operat...
KoMainWindow(TDEInstance *instance, const char *_name=0)
Constructor.
virtual void slotToolbarToggled(bool toggle)
Shows or hides a toolbar.
void slotEmailFile()
Slot for eMailing the document using KMail.
virtual void slotConfigureKeys()
Configure key bindings.
void slotFilePrintPreview()
Show a print preview.
virtual void slotConfigureToolbars()
Configure toolbars.
virtual void slotNewToolbarConfig()
Post toolbar config.
virtual void slotDocumentInfo()
Show a dialog with author and document information.
void setRootDocumentDirect(KoDocument *doc, const TQPtrList< KoView > &views)
Special method for KOShell, to allow switching the root document (and its views) among a set of them.
virtual void slotFileClose()
Closes the document.
void slotImportFile()
File --> Import.
void saveRecentFiles()
Save the list of recent files.
bool isExporting() const
Returns whether or not the current slotFileSave[As]() or saveDocument() call is actually an export op...
void slotReloadFile()
Reload file.
virtual bool saveDocument(bool saveas=false, bool silent=false)
Saves the document, asking for a filename if necessary.
void print(bool quick)
Prints the document.
virtual void slotSplitView()
View splitting stuff.
void setDocToOpen(KoDocument *doc)
This is used to handle the document used at start up before it actually added as root document.
virtual bool queryClose()
Ask user about saving changes to the document upon exit.
virtual void setRootDocument(KoDocument *doc)
Called when a document is assigned to this mainwindow.
void slotExportFile()
File --> Export.
TQLabel * statusBarLabel()
Get hold of the label in the statusbar, to write messages to it.
virtual void slotFileOpen()
Slot for opening a saved file.
~KoMainWindow()
Destructor.
virtual void slotFilePrint()
Prints the actual document.
virtual void slotFileSave()
Saves the current document with the current name.
virtual KoDocument * createDoc() const
Create a new empty document.
virtual void slotCloseAllViews()
Close all views.
void saveDialogShown()
This signals is emmitted before the save dialog is shown.
virtual void slotFileSaveAs()
Saves the current document with a new name.
virtual void slotFileOpenRecent(const KURL &)
Slot for opening a file among the recently opened files.
void slotVersionsFile()
This will call a dialogbox to add version to list of files.
void showToolbar(const char *tbName, bool shown)
The application should call this to show or hide a toolbar.
virtual KoDocument * rootDocument() const
Retrieves the document that is displayed in the mainwindow.
bool toolbarIsVisible(const char *tbName)
void setMaxRecentItems(uint _number)
Sets the maximum number of recent documents entries.
virtual bool openDocument(const KURL &url)
Load the desired document and show it.
void addRecentURL(const KURL &url)
The document opened a URL -> store into recent documents list.
virtual void slotFileQuit()
Closes the shell.
void reloadRecentFileList()
Reloads the recent documents list.
virtual void updateCaption()
Update caption from document info - call when document info (title in the about page) changes.
void chooseNewDocument(int initDocFlags)
Helper method for slotFileNew and slotFileClose.
void documentSaved()
This signal is emitted if the document has been saved successfully.
virtual void slotFileNew()
Slot for opening a new document.
static bool isKttsdInstalled()
Returns whether the KTTSD deamon is installed in the system.
This class is used to display a KoDocument.
Definition KoView.h:58
virtual void setEnabled(bool enable)
TDEToolBar * toolBar(const char *name=0)
virtual void hide()
KStatusBar * statusBar()
void setStandardToolBarMenuEnabled(bool enable)
virtual void setCaption(const TQString &caption)
bool initialGeometrySet() const
void saveMainWindowSettings(TDEConfig *config, const TQString &groupName=TQString::null)
void resetAutoSaveSettings()
void saveWindowSize(TDEConfig *config) const
static TQPtrList< TDEMainWindow > * memberList
virtual void closeEvent(TQCloseEvent *)
void restoreWindowSize(TDEConfig *config)
void setAutoSaveSettings(const TQString &groupName=TQString::fromLatin1("MainWindow"), bool saveWindowSize=true)
void applyMainWindowSettings(TDEConfig *config, const TQString &groupName, bool force)
TDEMainWindow(TQWidget *parent=0, const char *name=0, WFlags f=(WFlags)(WType_TopLevel|WDestructiveClose))
virtual void show()
void setCheckedState(const KGuiItem &checkedItem)
virtual void setChecked(bool)
TQString text() const
This file is part of the KDE/KOffice project.
TDEAction * close(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * save(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDERecentFilesAction * openRecent(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * configureToolbars(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * mail(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * open(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * quit(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * printPreview(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * openNew(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * saveAs(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEAction * print(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
const char * name(StdAction id)
TDEAction * keyBindings(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)