lib Library API Documentation

koMainWindow.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00003    Copyright (C) 2000-2004 David Faure <faure@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include "koMainWindow.h"
00022 #include "koDocument.h"
00023 #include "koView.h"
00024 #include "koFilterManager.h"
00025 #include "koDocumentInfo.h"
00026 #include "koDocumentInfoDlg.h"
00027 #include "koQueryTrader.h"
00028 #include "KoMainWindowIface.h"
00029 #include "koFrame.h"
00030 #include "kofiledialog.h"
00031 #include "koversiondialog.h"
00032 
00033 #include <kprinter.h>
00034 #include <kdeversion.h>
00035 #include <kstdaction.h>
00036 #include <kapplication.h>
00037 #include <kmessagebox.h>
00038 #include <kstandarddirs.h>
00039 #include <kio/netaccess.h>
00040 #include <kkeydialog.h>
00041 #include <kedittoolbar.h>
00042 #include <kprogress.h>
00043 #include <kpushbutton.h>
00044 #include <kdebug.h>
00045 #include <ktempfile.h>
00046 #include <krecentdocument.h>
00047 #include <kparts/partmanager.h>
00048 #include <kparts/plugin.h>
00049 #include <kparts/event.h>
00050 #include <klocale.h>
00051 #include <kstatusbar.h>
00052 #include <kglobalsettings.h>
00053 
00054 #include <qobjectlist.h>
00055 
00056 #include <unistd.h>
00057 #include <stdlib.h>
00058 
00059 class KoPartManager : public KParts::PartManager
00060 {
00061 public:
00062   KoPartManager( QWidget * parent, const char * name = 0L )
00063     : KParts::PartManager( parent, name ) {}
00064   KoPartManager( QWidget *topLevel, QObject *parent, const char *name = 0L )
00065     : KParts::PartManager( topLevel, parent, name ) {}
00066   virtual bool eventFilter( QObject *obj, QEvent *ev )
00067   {
00068     if ( !obj->isWidgetType() || ::qt_cast<KoFrame *>( obj ) )
00069       return false;
00070     return KParts::PartManager::eventFilter( obj, ev );
00071   }
00072 };
00073 
00074 class KoMainWindowPrivate
00075 {
00076 public:
00077   KoMainWindowPrivate()
00078   {
00079     m_rootDoc = 0L;
00080     m_manager = 0L;
00081     bMainWindowGUIBuilt = false;
00082     m_forQuit=false;
00083     m_splitted=false;
00084     m_activePart = 0L;
00085     m_activeView = 0L;
00086     m_splitter=0L;
00087     m_orientation=0L;
00088     m_removeView=0L;
00089     m_toolbarList.setAutoDelete( true );
00090     m_firstTime=true;
00091     m_progress=0L;
00092     m_paDocInfo = 0;
00093     m_paSave = 0;
00094     m_paSaveAs = 0;
00095     m_paPrint = 0;
00096     m_paPrintPreview = 0;
00097     statusBarLabel = 0L;
00098     m_dcopObject = 0;
00099     m_sendfile = 0;
00100     m_paCloseFile = 0L;
00101     m_reloadfile = 0L;
00102     m_versionsfile = 0L;
00103     m_importFile = 0;
00104     m_exportFile = 0;
00105     m_isImporting = false;
00106     m_isExporting = false;
00107     m_windowSizeDirty = false;
00108     m_lastExportSpecialOutputFlag = 0;
00109   }
00110   ~KoMainWindowPrivate()
00111   {
00112     delete m_dcopObject;
00113   }
00114 
00115   KoDocument *m_rootDoc;
00116   QPtrList<KoView> m_rootViews;
00117   KParts::PartManager *m_manager;
00118 
00119   KParts::Part *m_activePart;
00120   KoView *m_activeView;
00121 
00122   QLabel * statusBarLabel;
00123   KProgress *m_progress;
00124 
00125   QPtrList<KAction> m_splitViewActionList;
00126   // This additional list is needed, because we don't plug
00127   // the first list, when an embedded view gets activated (Werner)
00128   QPtrList<KAction> m_veryHackyActionList;
00129   QSplitter *m_splitter;
00130   KSelectAction *m_orientation;
00131   KAction *m_removeView;
00132   KoMainWindowIface *m_dcopObject;
00133 
00134   QPtrList <KAction> m_toolbarList;
00135 
00136   bool bMainWindowGUIBuilt;
00137   bool m_splitted;
00138   bool m_forQuit;
00139   bool m_firstTime;
00140   bool m_windowSizeDirty;
00141 
00142   KAction *m_paDocInfo;
00143   KAction *m_paSave;
00144   KAction *m_paSaveAs;
00145   KAction *m_paPrint;
00146   KAction *m_paPrintPreview;
00147   KAction *m_sendfile;
00148   KAction *m_paCloseFile;
00149   KAction *m_reloadfile;
00150   KAction *m_versionsfile;
00151   KAction *m_importFile;
00152   KAction *m_exportFile;
00153 
00154   bool m_isImporting;
00155   bool m_isExporting;
00156 
00157   KURL m_lastExportURL;
00158   QCString m_lastExportFormat;
00159   int m_lastExportSpecialOutputFlag;
00160 };
00161 
00162 KoMainWindow::KoMainWindow( KInstance *instance, const char* name )
00163     : KParts::MainWindow( name )
00164 {
00165     setStandardToolBarMenuEnabled(true); // should there be a check for >= 3.1 ?
00166     Q_ASSERT(instance);
00167     d = new KoMainWindowPrivate;
00168 
00169     d->m_manager = new KoPartManager( this );
00170     d->m_manager->setSelectionPolicy( KParts::PartManager::TriState );
00171     d->m_manager->setAllowNestedParts( true );
00172     d->m_manager->setIgnoreScrollBars( true );
00173     d->m_manager->setActivationButtonMask( Qt::LeftButton | Qt::MidButton );
00174 
00175     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
00176              this, SLOT( slotActivePartChanged( KParts::Part * ) ) );
00177 
00178     if ( instance )
00179         setInstance( instance, false ); // don't load plugins! we don't want
00180     // the part's plugins with this shell, even though we are using the
00181     // part's instance! (Simon)
00182 
00183     QString doc;
00184     QStringList allFiles = KGlobal::dirs()->findAllResources( "data", "koffice/koffice_shell.rc" );
00185     setXMLFile( findMostRecentXMLFile( allFiles, doc ) );
00186     setLocalXMLFile( locateLocal( "data", "koffice/koffice_shell.rc" ) );
00187 
00188     KStdAction::openNew( this, SLOT( slotFileNew() ), actionCollection(), "file_new" );
00189     KStdAction::open( this, SLOT( slotFileOpen() ), actionCollection(), "file_open" );
00190     m_recent = KStdAction::openRecent( this, SLOT(slotFileOpenRecent(const KURL&)), actionCollection() );
00191     d->m_paSave = KStdAction::save( this, SLOT( slotFileSave() ), actionCollection(), "file_save" );
00192     d->m_paSaveAs = KStdAction::saveAs( this, SLOT( slotFileSaveAs() ), actionCollection(), "file_save_as" );
00193     d->m_paPrint = KStdAction::print( this, SLOT( slotFilePrint() ), actionCollection(), "file_print" );
00194     d->m_paPrintPreview = KStdAction::printPreview( this, SLOT( slotFilePrintPreview() ), actionCollection(), "file_print_preview" );
00195     d->m_sendfile = KStdAction::mail( this, SLOT( slotEmailFile() ), actionCollection(), "file_send_file");
00196 
00197     d->m_paCloseFile = KStdAction::close( this, SLOT( slotFileClose() ), actionCollection(), "file_close" );
00198     KStdAction::quit( this, SLOT( slotFileQuit() ), actionCollection(), "file_quit" );
00199 
00200     d->m_reloadfile = new KAction( i18n( "Reload"), 0,
00201                     this, SLOT( slotReloadFile() ),
00202                     actionCollection(), "file_reload_file");
00203 
00204     d->m_versionsfile = new KAction( i18n( "Versions..."), 0,
00205                     this, SLOT( slotVersionsFile() ),
00206                     actionCollection(), "file_versions_file");
00207 
00208     d->m_importFile = new KAction( i18n( "I&mport..." ), 0, // clashing accel key :(
00209                     this, SLOT( slotImportFile() ),
00210                     actionCollection(), "file_import_file");
00211     d->m_exportFile = new KAction( i18n( "E&xport..." ), 0,
00212                     this, SLOT( slotExportFile() ),
00213                     actionCollection(), "file_export_file");
00214 
00215     /* The following entry opens the document information dialog.  Since the action is named so it
00216         intends to show data this entry should not have a trailing ellipses (...).  */
00217     d->m_paDocInfo = new KAction( i18n( "&Document Information" ), "documentinfo", 0,
00218                         this, SLOT( slotDocumentInfo() ),
00219                         actionCollection(), "file_documentinfo" );
00220 
00221     KStdAction::keyBindings( this, SLOT( slotConfigureKeys() ), actionCollection() );
00222     KStdAction::configureToolbars( this, SLOT( slotConfigureToolbars() ), actionCollection() );
00223 
00224     d->m_paDocInfo->setEnabled( false );
00225     d->m_paSaveAs->setEnabled( false );
00226     d->m_reloadfile->setEnabled( false );
00227     d->m_versionsfile->setEnabled( false );
00228     d->m_importFile->setEnabled( true );  // always enabled like File --> Open
00229     d->m_exportFile->setEnabled( false );
00230     d->m_paSave->setEnabled( false );
00231     d->m_paPrint->setEnabled( false );
00232     d->m_paPrintPreview->setEnabled( false );
00233     d->m_sendfile->setEnabled( false);
00234     d->m_paCloseFile->setEnabled( false);
00235 
00236     d->m_splitter=new QSplitter(Qt::Vertical, this, "mw-splitter");
00237     setCentralWidget( d->m_splitter );
00238 
00239     // set up the action "list" for "Close all Views" (hacky :) (Werner)
00240     d->m_veryHackyActionList.append(
00241         new KAction(i18n("&Close All Views"), "fileclose",
00242                     0, this, SLOT(slotCloseAllViews()),
00243                     actionCollection(), "view_closeallviews") );
00244 
00245     // set up the action list for the splitter stuff
00246     d->m_splitViewActionList.append(new KAction(i18n("&Split View"), "view_split", 0,
00247         this, SLOT(slotSplitView()),
00248         actionCollection(), "view_split"));
00249     d->m_removeView=new KAction(i18n("&Remove View"), "view_remove", 0,
00250         this, SLOT(slotRemoveView()),
00251         actionCollection(), "view_rm_splitter");
00252     d->m_splitViewActionList.append(d->m_removeView);
00253     d->m_removeView->setEnabled(false);
00254     d->m_orientation=new KSelectAction(i18n("Splitter &Orientation"), "view_orientation", 0,
00255         this, SLOT(slotSetOrientation()),
00256         actionCollection(), "view_splitter_orientation");
00257     QStringList items;
00258     items << i18n("&Vertical")
00259           << i18n("&Horizontal");
00260     d->m_orientation->setItems(items);
00261     d->m_orientation->setCurrentItem(static_cast<int>(d->m_splitter->orientation()));
00262     d->m_splitViewActionList.append(d->m_orientation);
00263     d->m_splitViewActionList.append(new KActionSeparator(this));
00264 
00265     // Load list of recent files
00266     KConfig * config = instance ? instance->config() : KGlobal::config();
00267     m_recent->loadEntries( config );
00268 
00269     createShellGUI();
00270     d->bMainWindowGUIBuilt = true;
00271 
00272     if ( !initialGeometrySet() )
00273     {
00274         // Default size
00275         const int deskWidth = KGlobalSettings::desktopGeometry(this).width();
00276         if (deskWidth > 1100) // very big desktop ?
00277             resize( 1000, 800 );
00278         if (deskWidth > 850) // big desktop ?
00279             resize( 800, 600 );
00280         else // small (800x600, 640x480) desktop
00281             resize( 600, 400 );
00282     }
00283 
00284     // Saved size
00285     config->setGroup( "MainWindow" );
00286     //kdDebug(30003) << "KoMainWindow::restoreWindowSize" << endl;
00287     restoreWindowSize( config );
00288 }
00289 
00290 KoMainWindow::~KoMainWindow()
00291 {
00292     // The doc and view might still exist (this is the case when closing the window)
00293     if (d->m_rootDoc)
00294         d->m_rootDoc->removeShell(this);
00295 
00296     // safety first ;)
00297     d->m_manager->setActivePart(0);
00298 
00299     if(d->m_rootViews.findRef(d->m_activeView)==-1) {
00300         delete d->m_activeView;
00301         d->m_activeView=0L;
00302     }
00303     d->m_rootViews.setAutoDelete( true );
00304     d->m_rootViews.clear();
00305 
00306     // We have to check if this was a root document.
00307     // -> We aren't allowed to delete the (embedded) document!
00308     // This has to be checked from queryClose, too :)
00309     if ( d->m_rootDoc && d->m_rootDoc->viewCount() == 0 &&
00310          !d->m_rootDoc->isEmbedded())
00311     {
00312         //kdDebug(30003) << "Destructor. No more views, deleting old doc " << d->m_rootDoc << endl;
00313         delete d->m_rootDoc;
00314     }
00315 
00316     delete d->m_manager;
00317     delete d;
00318 }
00319 
00320 void KoMainWindow::setRootDocument( KoDocument *doc )
00321 {
00322   if ( d->m_rootDoc == doc )
00323     return;
00324 
00325   //kdDebug(30003) <<  "KoMainWindow::setRootDocument this = " << this << " doc = " << doc << endl;
00326   QPtrList<KoView> oldRootViews = d->m_rootViews;
00327   d->m_rootViews.clear();
00328   KoDocument *oldRootDoc = d->m_rootDoc;
00329 
00330   if ( oldRootDoc )
00331     oldRootDoc->removeShell( this );
00332 
00333   d->m_rootDoc = doc;
00334 
00335   if ( doc )
00336   {
00337     doc->setSelectable( false );
00338     //d->m_manager->addPart( doc, false ); // done by KoView::setPartManager
00339     d->m_rootViews.append( doc->createView( d->m_splitter, "view" /*not unique, but better than unnamed*/ ) );
00340     d->m_rootViews.current()->setPartManager( d->m_manager );
00341 
00342     d->m_rootViews.current()->show();
00343     // The addShell has been done already if using openURL
00344     if ( !d->m_rootDoc->shells().contains( this ) )
00345         d->m_rootDoc->addShell( this );
00346     d->m_removeView->setEnabled(false);
00347     d->m_orientation->setEnabled(false);
00348   }
00349 
00350   bool enable = d->m_rootDoc != 0 ? true : false;
00351   d->m_paDocInfo->setEnabled( enable );
00352   d->m_paSave->setEnabled( enable );
00353   d->m_paSaveAs->setEnabled( enable );
00354   d->m_importFile->setEnabled( enable );
00355   d->m_exportFile->setEnabled( enable );
00356   d->m_paPrint->setEnabled( enable );
00357   d->m_paPrintPreview->setEnabled( enable );
00358   d->m_sendfile->setEnabled( enable);
00359   d->m_paCloseFile->setEnabled( enable);
00360   updateCaption();
00361 
00362   d->m_manager->setActivePart( d->m_rootDoc, d->m_rootViews.current() );
00363 
00364   oldRootViews.setAutoDelete( true );
00365   oldRootViews.clear();
00366 
00367   if ( oldRootDoc && oldRootDoc->viewCount() == 0 )
00368   {
00369     //kdDebug(30003) << "No more views, deleting old doc " << oldRootDoc << endl;
00370     delete oldRootDoc;
00371   }
00372 }
00373 
00374 void KoMainWindow::updateReloadFileAction(KoDocument *doc)
00375 {
00376     d->m_reloadfile->setEnabled( doc && !doc->url().isEmpty()&&doc->isModified());
00377 }
00378 
00379 void KoMainWindow::updateVersionsFileAction(KoDocument *doc)
00380 {
00381     //TODO activate it just when we save it in oasis file format
00382     d->m_versionsfile->setEnabled( doc && !doc->url().isEmpty()&&doc->isModified());
00383 }
00384 
00385 
00386 void KoMainWindow::setRootDocumentDirect( KoDocument *doc, const QPtrList<KoView> & views )
00387 {
00388   d->m_rootDoc = doc;
00389   d->m_rootViews = views;
00390   bool enable = d->m_rootDoc != 0 ? true : false;
00391   d->m_paDocInfo->setEnabled( enable );
00392   d->m_paSave->setEnabled( enable );
00393   d->m_paSaveAs->setEnabled( enable );
00394   d->m_exportFile->setEnabled( enable );
00395   d->m_paPrint->setEnabled( enable );
00396   d->m_paPrintPreview->setEnabled( enable );
00397   d->m_sendfile->setEnabled( enable);
00398   d->m_paCloseFile->setEnabled( enable );
00399 }
00400 
00401 void KoMainWindow::addRecentURL( const KURL& url )
00402 {
00403     kdDebug(30003) << "KoMainWindow::addRecentURL url=" << url.prettyURL() << endl;
00404     // Add entry to recent documents list
00405     // (call coming from KoDocument because it must work with cmd line, template dlg, file/open, etc.)
00406     if ( !url.isEmpty() )
00407     {
00408         bool ok = true;
00409         if ( url.isLocalFile() )
00410         {
00411             QString path = url.path( -1 );
00412             QStringList tmpDirs = KGlobal::dirs()->resourceDirs( "tmp" );
00413             for ( QStringList::Iterator it = tmpDirs.begin() ; ok && it != tmpDirs.end() ; ++it )
00414                 if ( path.contains( *it ) )
00415                     ok = false; // it's in the tmp resource
00416             if ( ok )
00417                 KRecentDocument::add(path);
00418         }
00419         else
00420             KRecentDocument::add(url.url(-1), true);
00421 
00422         if ( ok )
00423             m_recent->addURL( url );
00424         saveRecentFiles();
00425     }
00426 }
00427 
00428 void KoMainWindow::saveRecentFiles()
00429 {
00430     // Save list of recent files
00431     KConfig * config = instance() ? instance()->config() : KGlobal::config();
00432     kdDebug(30003) << this << " Saving recent files list into config. instance()=" << instance() << endl;
00433     m_recent->saveEntries( config );
00434     config->sync();
00435     if (KMainWindow::memberList)
00436     {
00437         // Tell all windows to reload their list, after saving
00438         // Doesn't work multi-process, but it's a start
00439         KMainWindow *window = KMainWindow::memberList->first();
00440         for (; window; window = KMainWindow::memberList->next())
00441             static_cast<KoMainWindow *>(window)->reloadRecentFileList();
00442     }
00443 }
00444 
00445 void KoMainWindow::reloadRecentFileList()
00446 {
00447     KConfig * config = instance() ? instance()->config() : KGlobal::config();
00448     m_recent->loadEntries( config );
00449 }
00450 
00451 KoDocument* KoMainWindow::createDoc() const
00452 {
00453     const QCString mimetype = KoDocument::readNativeFormatMimeType();
00454     KoDocumentEntry entry = KoDocumentEntry::queryByMimeType( mimetype );
00455     return entry.createDoc();
00456 }
00457 
00458 void KoMainWindow::updateCaption()
00459 {
00460   //kdDebug(30003) << "KoMainWindow::updateCaption()" << endl;
00461   if ( !d->m_rootDoc )
00462     setCaption(QString::null);
00463   else if ( rootDocument()->isCurrent() )
00464   {
00465       QString caption;
00466       // Get caption from document info (title(), in about page)
00467       if ( rootDocument()->documentInfo() )
00468       {
00469           KoDocumentInfoPage * page = rootDocument()->documentInfo()->page( QString::fromLatin1("about") );
00470           if (page)
00471               caption = static_cast<KoDocumentInfoAbout *>(page)->title();
00472       }
00473       const QString url = rootDocument()->url().prettyURL( 0, KURL::StripFileProtocol );
00474       if ( !caption.isEmpty() && !url.isEmpty() )
00475           caption = QString( "%1 - %2" ).arg( caption ).arg( url );
00476       else if ( caption.isEmpty() )
00477           caption = url;
00478 
00479       setCaption( caption, rootDocument()->isModified() );
00480       if ( !rootDocument()->url().fileName(false).isEmpty() )
00481         d->m_paSave->setToolTip( i18n("Save as %1").arg(rootDocument()->url().fileName(false)) );
00482       else
00483         d->m_paSave->setToolTip( i18n("Save") );
00484   }
00485 }
00486 
00487 void KoMainWindow::updateCaption( QString caption, bool mod )
00488 {
00489   //kdDebug(30003)<<"KoMainWindow::updateCaption("<<caption<<","<<mod<<")"<<endl;
00490   setCaption( caption, mod );
00491 }
00492 
00493 KoDocument *KoMainWindow::rootDocument() const
00494 {
00495     return d->m_rootDoc;
00496 }
00497 
00498 KoView *KoMainWindow::rootView() const
00499 {
00500   if(d->m_rootViews.find(d->m_activeView)!=-1)
00501     return d->m_activeView;
00502   return d->m_rootViews.first();
00503 }
00504 
00505 KParts::PartManager *KoMainWindow::partManager()
00506 {
00507   return d->m_manager;
00508 }
00509 
00510 bool KoMainWindow::openDocument( const KURL & url )
00511 {
00512     if ( !KIO::NetAccess::exists(url,true,0) )
00513     {
00514         KMessageBox::error(0L, i18n("The file %1 does not exist.").arg(url.url()) );
00515         m_recent->removeURL(url); //remove the file from the recent-opened-file-list
00516         saveRecentFiles();
00517         return false;
00518     }
00519     return  openDocumentInternal( url );
00520 }
00521 
00522 // (not virtual)
00523 bool KoMainWindow::openDocument( KoDocument *newdoc, const KURL & url )
00524 {
00525     if (!KIO::NetAccess::exists(url,true,0) )
00526     {
00527         if ( newdoc->checkAutoSaveFile() || newdoc->initDoc(KoDocument::InitDocEmpty) ) //create an emtpy document
00528         {
00529                 setRootDocument( newdoc );
00530                 newdoc->setURL(url);
00531                 QString mime = KMimeType::findByURL(url)->name();
00532                 if ( mime.isEmpty() || mime == KMimeType::defaultMimeType() )
00533                     mime = newdoc->nativeFormatMimeType();
00534                 if ( url.isLocalFile() ) // workaround for kde<=3.3 kparts bug, fixed for 3.4
00535                     newdoc->setFile(url.path());
00536                 newdoc->setMimeTypeAfterLoading( mime );
00537                 updateCaption();
00538                 return true;
00539         }
00540         return false;
00541     }
00542     return openDocumentInternal( url, newdoc );
00543 }
00544 
00545 // ## If you modify anything here, please check KoShellWindow::openDocumentInternal
00546 bool KoMainWindow::openDocumentInternal( const KURL & url, KoDocument *newdoc )
00547 {
00548     //kdDebug(30003) << "KoMainWindow::openDocument " << url.url() << endl;
00549 
00550     if ( !newdoc )
00551         newdoc = createDoc();
00552 
00553     d->m_firstTime=true;
00554     connect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00555     connect(newdoc, SIGNAL(completed()), this, SLOT(slotLoadCompleted()));
00556     connect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotLoadCanceled( const QString & )));
00557     newdoc->addShell( this ); // used by openURL
00558     bool openRet = (!isImporting ()) ? newdoc->openURL(url) : newdoc->import(url);
00559     if(!newdoc || !openRet)
00560     {
00561         newdoc->removeShell(this);
00562         delete newdoc;
00563         return false;
00564     }
00565     updateReloadFileAction(newdoc);
00566     updateVersionsFileAction( newdoc );
00567     return true;
00568 }
00569 
00570 // Separate from openDocument to handle async loading (remote URLs)
00571 void KoMainWindow::slotLoadCompleted()
00572 {
00573     kdDebug(30003) << "KoMainWindow::slotLoadCompleted" << endl;
00574     KoDocument* doc = rootDocument();
00575     KoDocument* newdoc = (KoDocument *)(sender());
00576 
00577     if ( doc && doc->isEmpty() && !doc->isEmbedded() )
00578     {
00579         // Replace current empty document
00580         setRootDocument( newdoc );
00581     }
00582     else if ( doc && !doc->isEmpty() )
00583     {
00584         // Open in a new shell
00585         // (Note : could create the shell first and the doc next for this
00586         // particular case, that would give a better user feedback...)
00587         KoMainWindow *s = new KoMainWindow( newdoc->instance() );
00588         s->show();
00589         newdoc->removeShell( this );
00590         s->setRootDocument( newdoc );
00591     }
00592     else
00593     {
00594         // We had no document, set the new one
00595        setRootDocument( newdoc );
00596     }
00597     disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00598     disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotLoadCompleted()));
00599     disconnect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotLoadCanceled( const QString & )));
00600 }
00601 
00602 void KoMainWindow::slotLoadCanceled( const QString & errMsg )
00603 {
00604     kdDebug(30003) << "KoMainWindow::slotLoadCanceled" << endl;
00605     if ( !errMsg.isEmpty() ) // empty when canceled by user
00606         KMessageBox::error( this, errMsg );
00607     // ... can't delete the document, it's the one who emitted the signal...
00608 
00609     KoDocument* newdoc = (KoDocument *)(sender());
00610     disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00611     disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotLoadCompleted()));
00612     disconnect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotLoadCanceled( const QString & )));
00613 }
00614 
00615 void KoMainWindow::slotSaveCanceled( const QString &errMsg )
00616 {
00617     kdDebug(30003) << "KoMainWindow::slotSaveCanceled" << endl;
00618     if ( !errMsg.isEmpty() ) // empty when canceled by user
00619         KMessageBox::error( this, errMsg );
00620     slotSaveCompleted();
00621 }
00622 
00623 void KoMainWindow::slotSaveCompleted()
00624 {
00625     kdDebug(30003) << "KoMainWindow::slotSaveCompleted" << endl;
00626     KoDocument* pDoc = (KoDocument *)(sender());
00627     disconnect(pDoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00628     disconnect(pDoc, SIGNAL(completed()), this, SLOT(slotSaveCompleted()));
00629     disconnect(pDoc, SIGNAL(canceled( const QString & )),
00630                this, SLOT(slotSaveCanceled( const QString & )));
00631 }
00632 
00633 // returns true if we should save, false otherwise.
00634 bool KoMainWindow::exportConfirmation( const QCString &outputFormat )
00635 {
00636     KMimeType::Ptr mime = KMimeType::mimeType( outputFormat );
00637 
00638     const bool neverHeardOfIt = ( mime->name() == KMimeType::defaultMimeType() );
00639     QString comment = neverHeardOfIt ?
00640                       i18n( "%1 (unknown file type)" ).arg( outputFormat )
00641                       : mime->comment();
00642 
00643     // Warn the user
00644     int ret;
00645     if (!isExporting ()) // File --> Save
00646     {
00647         ret = KMessageBox::warningContinueCancel
00648               (
00649                   this,
00650                   i18n( "<qt>Saving as a %1 may result in some loss of formatting."
00651                         "<p>Do you still want to save in this format?</qt>" )
00652                   .arg( QString( "<b>%1</b>" ).arg( comment ) ), // in case we want to remove the bold later
00653                   i18n( "Confirm Save" ),
00654                   KStdGuiItem::save (),
00655                   "NonNativeSaveConfirmation",
00656                   true
00657                   );
00658     }
00659     else // File --> Export
00660     {
00661         ret = KMessageBox::warningContinueCancel
00662               (
00663                   this,
00664                   i18n( "<qt>Exporting as a %1 may result in some loss of formatting."
00665                         "<p>Do you still want to export to this format?</qt>" )
00666                   .arg( QString( "<b>%1</b>" ).arg( comment ) ), // in case we want to remove the bold later
00667                   i18n( "Confirm Export" ),
00668                   i18n ("Export"),
00669                   "NonNativeExportConfirmation", // different to the one used for Save (above)
00670                   true
00671                   );
00672     }
00673 
00674     return (ret == KMessageBox::Continue);
00675 }
00676 
00677 bool KoMainWindow::saveDocument( bool saveas, bool silent )
00678 {
00679     KoDocument* pDoc = rootDocument();
00680     if(!pDoc)
00681         return true;
00682 
00683     bool reset_url;
00684     if ( pDoc->url().isEmpty() )
00685     {
00686         emit saveDialogShown();
00687         reset_url = true;
00688         saveas = true;
00689     }
00690     else
00691         reset_url = false;
00692 
00693     connect(pDoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00694     connect(pDoc, SIGNAL(completed()), this, SLOT(slotSaveCompleted()));
00695     connect(pDoc, SIGNAL(canceled( const QString & )),
00696             this, SLOT(slotSaveCanceled( const QString & )));
00697 
00698     KURL oldURL = pDoc->url();
00699     QString oldFile = pDoc->file();
00700     QCString _native_format = pDoc->nativeFormatMimeType();
00701     QCString oldOutputFormat = pDoc->outputMimeType();
00702     int oldSpecialOutputFlag = pDoc->specialOutputFlag();
00703     KURL suggestedURL = pDoc->url();
00704 
00705     QStringList mimeFilter = KoFilterManager::mimeFilter( _native_format, KoFilterManager::Export, pDoc->extraNativeMimeTypes() );
00706     if (mimeFilter.findIndex (oldOutputFormat) < 0 && !isExporting())
00707     {
00708         kdDebug(30003) << "KoMainWindow::saveDocument no export filter for '" << oldOutputFormat << "'" << endl;
00709 
00710         // --- don't setOutputMimeType in case the user cancels the Save As
00711         // dialog and then tries to just plain Save ---
00712 
00713         // suggest a different filename extension (yes, we fortunately don't all live in a world of magic :))
00714         QString suggestedFilename = suggestedURL.fileName ();
00715         if ( !suggestedFilename.isEmpty () ) // ".kwd" looks strange for a name
00716         {
00717             int c = suggestedFilename.findRev ('.');
00718 
00719             KMimeType::Ptr mime = KMimeType::mimeType( _native_format );
00720             QString ext = mime->property( "X-KDE-NativeExtension" ).toString();
00721             if (!ext.isEmpty ())
00722             {
00723                 if (c < 0)
00724                     suggestedFilename += ext;
00725                 else
00726                     suggestedFilename = suggestedFilename.left (c) + ext;
00727             }
00728             else  // current filename extension wrong anyway
00729             {
00730                 if (c > 0)
00731                 {
00732                     // this assumes that a . signifies an extension, not just a .
00733                     suggestedFilename = suggestedFilename.left (c);
00734                 }
00735             }
00736 
00737             suggestedURL.setFileName (suggestedFilename);
00738         }
00739 
00740         // force the user to choose outputMimeType
00741         saveas = true;
00742     }
00743 
00744     bool ret = false;
00745 
00746     if ( pDoc->url().isEmpty() || saveas )
00747     {
00748         // if you're just File/Save As'ing to change filter options you
00749         // don't want to be reminded about overwriting files etc.
00750         bool justChangingFilterOptions = false;
00751 
00752         KoFileDialog *dialog = new KoFileDialog( (isExporting() && !d->m_lastExportURL.isEmpty() )? d->m_lastExportURL.url () : suggestedURL.url (),
00753                                                 QString::null, this, "file dialog", true);
00754 
00755         if (!isExporting())
00756             dialog->setCaption( i18n("Save Document As") );
00757         else
00758             dialog->setCaption( i18n("Export Document As") );
00759 
00760         dialog->setOperationMode( KFileDialog::Saving );
00761         dialog->setSpecialMimeFilter( mimeFilter,
00762                                       isExporting() ? d->m_lastExportFormat : pDoc->mimeType(),
00763                                       isExporting() ? d->m_lastExportSpecialOutputFlag : oldSpecialOutputFlag,
00764                                       _native_format,
00765                                       pDoc->supportedSpecialFormats() );
00766 
00767         KURL newURL;
00768         QCString outputFormat = _native_format;
00769         int specialOutputFlag = 0;
00770         bool bOk;
00771         do {
00772             bOk=true;
00773             if(dialog->exec()==QDialog::Accepted) {
00774                 newURL=dialog->selectedURL();
00775                 outputFormat=dialog->currentMimeFilter().latin1();
00776                 specialOutputFlag = dialog->specialEntrySelected();
00777                 kdDebug(30003) << "KoMainWindow::saveDocument outputFormat = " << outputFormat << endl;
00778 
00779                 if (!isExporting())
00780                     justChangingFilterOptions = (newURL == pDoc->url()) &&
00781                                                 (outputFormat == pDoc->mimeType()) &&
00782                                                 (specialOutputFlag == oldSpecialOutputFlag);
00783                 else
00784                     justChangingFilterOptions = (newURL == d->m_lastExportURL) &&
00785                                                 (outputFormat == d->m_lastExportFormat) &&
00786                                                 (specialOutputFlag == d->m_lastExportSpecialOutputFlag);
00787             }
00788             else
00789             {
00790                 bOk = false;
00791                 break;
00792             }
00793 
00794             if ( newURL.isEmpty() )
00795             {
00796                 bOk = false;
00797                 break;
00798             }
00799 
00800             // this file exists and we are not just clicking "Save As" to change filter options
00801             // => ask for confirmation
00802             if ( KIO::NetAccess::exists( newURL, false /*will write*/, this ) && !justChangingFilterOptions )
00803             {
00804                 bOk = KMessageBox::questionYesNo( this,
00805                                                   i18n("A document with this name already exists.\n"\
00806                                                        "Do you want to overwrite it?"),
00807                                                   i18n("Warning") ) == KMessageBox::Yes;
00808             }
00809         } while ( !bOk );
00810 
00811         delete dialog;
00812 
00813         if (bOk)
00814         {
00815             bool wantToSave = true;
00816 
00817             // don't change this line unless you know what you're doing :)
00818             if (!justChangingFilterOptions || pDoc->confirmNonNativeSave (isExporting ())) {
00819                 if ( !pDoc->isNativeFormat( outputFormat ) )
00820                     wantToSave = exportConfirmation( outputFormat );
00821             }
00822 
00823             if (wantToSave)
00824             {
00825                 //
00826                 // Note:
00827                 // If the user is stupid enough to Export to the current URL,
00828                 // we do _not_ change this operation into a Save As.  Reasons
00829                 // follow:
00830                 //
00831                 // 1. A check like "isExporting() && oldURL == newURL"
00832                 //    doesn't _always_ work on case-insensitive filesystems
00833                 //    and inconsistent behaviour is bad.
00834                 // 2. It is probably not a good idea to change pDoc->mimeType
00835                 //    and friends because the next time the user File/Save's,
00836                 //    (not Save As) they won't be expecting that they are
00837                 //    using their File/Export settings
00838                 //
00839                 // As a bad side-effect of this, the modified flag will not
00840                 // be updated and it is possible that what is currently on
00841                 // their screen is not what is stored on disk (through loss
00842                 // of formatting).  But if you are dumb enough to change
00843                 // mimetype but not the filename, then arguably, _you_ are
00844                 // the "bug" :)
00845                 //
00846                 // - Clarence
00847                 //
00848 
00849 
00850                 pDoc->setOutputMimeType( outputFormat, specialOutputFlag );
00851                 if (!isExporting ())   // Save As
00852                 {
00853                     ret = pDoc->saveAs( newURL );
00854 
00855                     if (ret)
00856                     {
00857                         kdDebug(30003) << "Successful Save As!" << endl;
00858                         addRecentURL( newURL );
00859                     }
00860                     else
00861                     {
00862                         kdDebug(30003) << "Failed Save As!" << endl;
00863                         pDoc->setURL( oldURL ), pDoc->setFile( oldFile );
00864                         pDoc->setOutputMimeType( oldOutputFormat, oldSpecialOutputFlag );
00865                     }
00866                 }
00867                 else    // Export
00868                 {
00869                     ret = pDoc->exp0rt( newURL );
00870 
00871                     if (ret)
00872                     {
00873                         // a few file dialog convenience things
00874                         d->m_lastExportURL = newURL;
00875                         d->m_lastExportFormat = outputFormat;
00876                         d->m_lastExportSpecialOutputFlag = specialOutputFlag;
00877                     }
00878 
00879                     // always restore output format
00880                     pDoc->setOutputMimeType( oldOutputFormat, oldSpecialOutputFlag );
00881                 }
00882 
00883                 if (silent) // don't let the document change the window caption
00884                   pDoc->setTitleModified();
00885             }   // if (wantToSave)  {
00886             else
00887                 ret = false;
00888         }   // if (bOk) {
00889         else
00890             ret = false;
00891     }
00892     else {  // saving
00893         bool needConfirm = pDoc->confirmNonNativeSave( false ) &&
00894                            !pDoc->isNativeFormat( oldOutputFormat );
00895         if (!needConfirm ||
00896                (needConfirm && exportConfirmation( oldOutputFormat /* not so old :) */ ))
00897            )
00898         {
00899             // be sure pDoc has the correct outputMimeType!
00900             ret = pDoc->save();
00901 
00902             if (!ret)
00903             {
00904                 kdDebug(30003) << "Failed Save!" << endl;
00905                 pDoc->setURL( oldURL ), pDoc->setFile( oldFile );
00906             }
00907         }
00908         else
00909             ret = false;
00910     }
00911 
00912 // Now that there's a File/Export option, this is no longer necessary.
00913 // If you continue to use File/Save to export to a foreign format,
00914 // this signals your intention to continue working in a foreign format.
00915 // You have already been warned by the DoNotAskAgain exportConfirmation
00916 // about losing formatting when you first saved so don't set modified
00917 // here or else it will be reported as a bug by some MSOffice user.
00918 // You have been warned!  Do not click DoNotAskAgain!!!
00919 #if 0
00920     if (ret && !isExporting())
00921     {
00922         // When exporting to a non-native format, we don't reset modified.
00923         // This way the user will be reminded to save it again in the native format,
00924         // if he/she doesn't want to lose formatting.
00925         if ( wasModified && pDoc->outputMimeType() != _native_format )
00926             pDoc->setModified( true );
00927     }
00928 #endif
00929 
00930     if (!ret && reset_url)
00931         pDoc->resetURL(); //clean the suggested filename as the save dialog was rejected
00932     return ret;
00933 }
00934 
00935 void KoMainWindow::closeEvent(QCloseEvent *e) {
00936     if(queryClose()) {
00937         saveWindowSettings();
00938         setRootDocument(0L);
00939         KParts::MainWindow::closeEvent(e);
00940     }
00941 }
00942 
00943 void KoMainWindow::saveWindowSettings()
00944 {
00945     if (d->m_windowSizeDirty && rootDocument())
00946     {
00947         // Save window size into the config file of our instance
00948         instance()->config()->setGroup( "MainWindow" );
00949         //kdDebug(30003) << "KoMainWindow::saveWindowSettings" << endl;
00950         saveWindowSize( instance()->config() );
00951         d->m_windowSizeDirty = false;
00952         // Save toolbar position into the config file of the app, under the doc's instance name
00953         //kdDebug(30003) << "KoMainWindow::closeEvent -> saveMainWindowSettings rootdoc's instance=" << rootDocument()->instance()->instanceName() << endl;
00954         saveMainWindowSettings( KGlobal::config(), rootDocument()->instance()->instanceName() );
00955         KGlobal::config()->sync();
00956         resetAutoSaveSettings(); // Don't let KMainWindow override the good stuff we wrote down
00957     }
00958 }
00959 
00960 void KoMainWindow::resizeEvent( QResizeEvent * e )
00961 {
00962     d->m_windowSizeDirty = true;
00963     KParts::MainWindow::resizeEvent( e );
00964 }
00965 
00966 bool KoMainWindow::queryClose()
00967 {
00968     if ( rootDocument() == 0 )
00969         return true;
00970     //kdDebug(30003) << "KoMainWindow::queryClose() viewcount=" << rootDocument()->viewCount()
00971     //               << " shellcount=" << rootDocument()->shellCount() << endl;
00972     if ( !d->m_forQuit && rootDocument()->shellCount() > 1 )
00973         // there are more open, and we are closing just one, so no problem for closing
00974         return true;
00975 
00976     // see DTOR for a descr. of the test
00977     if ( d->m_rootDoc->isEmbedded() )
00978         return true;
00979 
00980     // main doc + internally stored child documents
00981     if ( d->m_rootDoc->isModified() )
00982     {
00983         QString name;
00984         if ( rootDocument()->documentInfo() )
00985         {
00986             name = rootDocument()->documentInfo()->title();
00987         }
00988         if ( name.isEmpty() )
00989             name = rootDocument()->url().fileName();
00990 
00991         if ( name.isEmpty() )
00992             name = i18n( "Untitled" );
00993 
00994         int res = KMessageBox::warningYesNoCancel( this,
00995                         i18n( "<p>The document <b>'%1'</b> has been modified.</p><p>Do you want to save it?</p>" ).arg(name),
00996                         QString::null,
00997                         KStdGuiItem::save(),
00998                         KStdGuiItem::discard());
00999 
01000         switch(res) {
01001             case KMessageBox::Yes : {
01002                 d->m_rootDoc->setDoNotSaveExtDoc(); // external docs are saved later
01003                 bool isNative = ( d->m_rootDoc->outputMimeType() == d->m_rootDoc->nativeFormatMimeType() );
01004                 if (! saveDocument( !isNative ) )
01005                     return false;
01006                 break;
01007             }
01008             case KMessageBox::No :
01009                 rootDocument()->removeAutoSaveFiles();
01010                 rootDocument()->setModified( false ); // Now when queryClose() is called by closeEvent it won't do anything.
01011                 break;
01012             default : // case KMessageBox::Cancel :
01013                 return false;
01014         }
01015     }
01016 
01017     if ( d->m_rootDoc->queryCloseExternalChildren() == KMessageBox::Cancel )
01018     {
01019         return false;
01020     }
01021 
01022     return true;
01023 }
01024 
01025 // Helper method for slotFileNew and slotFileClose
01026 void KoMainWindow::chooseNewDocument( int /*KoDocument::InitDocFlags*/ initDocFlags )
01027 {
01028     KoDocument* doc = rootDocument();
01029     KoDocument *newdoc = createDoc();
01030     if ( !newdoc )
01031         return;
01032     connect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
01033     if ( !newdoc->initDoc( (KoDocument::InitDocFlags)initDocFlags, this ) )
01034     {
01035         delete newdoc;
01036         // See cancelQuits() in KoTemplateChooseDia.
01037         // The quit() must be done here so that the KoDocument got deleted already.
01038         bool onlyDoc = !KoDocument::documentList() || KoDocument::documentList()->isEmpty();
01039         bool onlyMainWindow = !KMainWindow::memberList || KMainWindow::memberList->count() <= 1;
01040         if ( onlyDoc && onlyMainWindow && kapp->instanceName() != "koshell" ) {
01041             kapp->quit();
01042         }
01043         return;
01044     }
01045     disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
01046     if ( doc && !doc->isEmpty() )
01047     {
01048         KoMainWindow *s = new KoMainWindow( newdoc->instance() );
01049         s->show();
01050         s->setRootDocument( newdoc );
01051         return;
01052     }
01053     setRootDocument( newdoc );
01054 }
01055 
01056 void KoMainWindow::slotFileNew()
01057 {
01058     chooseNewDocument( KoDocument::InitDocFileNew );
01059 }
01060 
01061 void KoMainWindow::slotFileOpen()
01062 {
01063     KFileDialog *dialog=new KFileDialog(QString::null, QString::null, this, "file dialog", true);
01064     if (!isImporting())
01065         dialog->setCaption( i18n("Open Document") );
01066     else
01067         dialog->setCaption( i18n("Import Document") );
01068 
01069     // The few lines below need to be kept in sync with KoTemplateChooseDia::setupFileDialog
01070     const QStringList mimeFilter = KoFilterManager::mimeFilter( KoDocument::readNativeFormatMimeType(),
01071                                                                 KoFilterManager::Import,
01072                                                                 KoDocument::readExtraNativeMimeTypes() );
01073     dialog->setMimeFilter( mimeFilter );
01074     if(dialog->exec()!=QDialog::Accepted) {
01075         delete dialog;
01076         return;
01077     }
01078     KURL url( dialog->selectedURL() );
01079     delete dialog;
01080 
01081     if ( url.isEmpty() )
01082         return;
01083 
01084     (void) openDocument( url );
01085 }
01086 
01087 void KoMainWindow::slotFileOpenRecent( const KURL & url )
01088 {
01089     (void) openDocument( url );
01090 }
01091 
01092 void KoMainWindow::slotFileSave()
01093 {
01094     if ( saveDocument() )
01095         emit documentSaved();
01096 }
01097 
01098 void KoMainWindow::slotFileSaveAs()
01099 {
01100     if ( saveDocument( true ) )
01101         emit documentSaved();
01102 }
01103 
01104 void KoMainWindow::slotDocumentInfo()
01105 {
01106   if ( !rootDocument() )
01107     return;
01108 
01109   KoDocumentInfo *docInfo = rootDocument()->documentInfo();
01110 
01111   if ( !docInfo )
01112     return;
01113 
01114   KoDocumentInfoDlg *dlg = new KoDocumentInfoDlg( docInfo, this, "documentInfoDlg" );
01115   if ( dlg->exec() )
01116   {
01117     dlg->save();
01118     rootDocument()->setModified( true );
01119     rootDocument()->setTitleModified();
01120   }
01121 
01122   delete dlg;
01123 }
01124 
01125 void KoMainWindow::slotFileClose()
01126 {
01127     if (queryClose())
01128     {
01129         saveWindowSettings();
01130         setRootDocument( 0 ); // don't delete this shell when deleting the document
01131         delete d->m_rootDoc;
01132         d->m_rootDoc = 0;
01133         chooseNewDocument( KoDocument::InitDocFileClose );
01134     }
01135 }
01136 
01137 void KoMainWindow::slotFileQuit()
01138 {
01139     close();
01140 }
01141 
01142 void KoMainWindow::print(bool quick) {
01143     if ( !rootView() )
01144     {
01145         kdDebug(30003) << "KoMainWindow::slotFilePrint : No root view!" << endl;
01146         return;
01147     }
01148 
01149     KPrinter printer( true /*, QPrinter::HighResolution*/ );
01150     QString title = rootView()->koDocument()->documentInfo()->title();
01151     QString fileName = rootView()->koDocument()->url().fileName();
01152 
01153     // strip off the native extension (I don't want foobar.kwd.ps when printing into a file)
01154     KMimeType::Ptr mime = KMimeType::mimeType( rootView()->koDocument()->outputMimeType() );
01155     if ( mime ) {
01156         QString extension = mime->property( "X-KDE-NativeExtension" ).toString();
01157 
01158         if ( fileName.endsWith( extension ) )
01159             fileName.truncate( fileName.length() - extension.length() );
01160     }
01161 
01162     if ( title.isEmpty() )
01163         title = fileName;
01164     printer.setDocName( title );
01165     printer.setDocFileName( fileName );
01166     printer.setDocDirectory( rootView()->koDocument()->url().directory() );
01167 
01168     // ### TODO: apply global koffice settings here
01169 
01170     rootView()->setupPrinter( printer );
01171 
01172     if ( quick ||  printer.setup( this ) )
01173         rootView()->print( printer );
01174 }
01175 
01176 
01177 void KoMainWindow::slotFilePrint()
01178 {
01179     print(false);
01180 }
01181 
01182 void KoMainWindow::slotFilePrintPreview()
01183 {
01184     if ( !rootView() )
01185     {
01186         kdWarning() << "KoMainWindow::slotFilePrint : No root view!" << endl;
01187         return;
01188     }
01189     KPrinter printer( false );
01190     KTempFile tmpFile;
01191     // The temp file is deleted by KoPrintPreview
01192 
01193     // This line has to be before setupPrinter to let the apps decide what to
01194     // print and what not (if they want to :)
01195     printer.setFromTo( printer.minPage(), printer.maxPage() );
01196     printer.setPreviewOnly( true );
01197     rootView()->setupPrinter( printer );
01198 
01199     QString oldFileName = printer.outputFileName();
01200     printer.setOutputFileName( tmpFile.name() );
01201     int oldNumCopies = printer.numCopies();
01202     printer.setNumCopies( 1 );
01203     // Disable kdeprint's own preview, we'd get two. This shows that KPrinter needs
01204     // a "don't use the previous settings" mode. The current way is really too much of a hack.
01205     QString oldKDEPreview = printer.option( "kde-preview" );
01206     printer.setOption( "kde-preview", "0" );
01207 
01208     rootView()->print(printer);
01209     //KoPrintPreview::preview(this, "KoPrintPreviewDialog", tmpFile.name());
01210 
01211     // Restore previous values
01212     printer.setOutputFileName( oldFileName );
01213     printer.setNumCopies( oldNumCopies );
01214     printer.setOption( "kde-preview", oldKDEPreview );
01215 }
01216 
01217 void KoMainWindow::slotConfigureKeys()
01218 {
01219     KoView *view = rootView();
01220     // We _need_ a view. We use the view's xmlFile() (e.g. kword.rc)
01221     Q_ASSERT( view );
01222     if ( !view )
01223         return;
01224 
01225     KKeyDialog dlg( this );
01226     dlg.insert( actionCollection() );
01227     dlg.insert( view->actionCollection() );
01228     if ( rootDocument() )
01229         dlg.insert( rootDocument()->actionCollection() );
01230     dlg.configure();
01231 }
01232 
01233 void KoMainWindow::slotConfigureToolbars()
01234 {
01235     if (rootDocument())
01236         saveMainWindowSettings( KGlobal::config(), rootDocument()->instance()->instanceName() );
01237     KEditToolbar edit(factory(), this);
01238     connect(&edit,SIGNAL(newToolbarConfig()),this,SLOT(slotNewToolbarConfig()));
01239     (void) edit.exec();
01240 }
01241 
01242 void KoMainWindow::slotNewToolbarConfig()
01243 {
01244   if (rootDocument())
01245       applyMainWindowSettings( KGlobal::config(), rootDocument()->instance()->instanceName() );
01246   KXMLGUIFactory *factory = guiFactory();
01247 
01248   // Check if there's an active view
01249   if( !d->m_activeView )
01250       return;
01251 
01252   // This gets plugged in even for embedded views
01253   factory->plugActionList(d->m_activeView, "view_closeallviews",
01254                           d->m_veryHackyActionList);
01255 
01256   // This one only for root views
01257   if(d->m_rootViews.findRef(d->m_activeView)!=-1)
01258     factory->plugActionList(d->m_activeView, "view_split",
01259                             d->m_splitViewActionList );
01260   plugActionList( "toolbarlist", d->m_toolbarList );
01261 }
01262 
01263 void KoMainWindow::slotToolbarToggled( bool toggle )
01264 {
01265   //kdDebug(30003) << "KoMainWindow::slotToolbarToggled " << sender()->name() << " toggle=" << true << endl;
01266   // The action (sender) and the toolbar have the same name
01267   KToolBar * bar = toolBar( sender()->name() );
01268   if (bar)
01269   {
01270     if (toggle)
01271       bar->show();
01272     else
01273       bar->hide();
01274 
01275     if (rootDocument())
01276         saveMainWindowSettings( KGlobal::config(), rootDocument()->instance()->instanceName() );
01277   }
01278   else
01279     kdWarning(30003) << "slotToolbarToggled : Toolbar " << sender()->name() << " not found!" << endl;
01280 }
01281 
01282 bool KoMainWindow::toolbarIsVisible(const char *tbName)
01283 {
01284     QWidget *tb = toolBar( tbName);
01285     return !tb->isHidden();
01286 }
01287 
01288 void KoMainWindow::showToolbar( const char * tbName, bool shown )
01289 {
01290     QWidget * tb = toolBar( tbName );
01291     if ( !tb )
01292     {
01293         kdWarning(30003) << "KoMainWindow: toolbar " << tbName << " not found." << endl;
01294         return;
01295     }
01296     if ( shown )
01297         tb->show();
01298     else
01299         tb->hide();
01300 
01301     // Update the action appropriately
01302     QPtrListIterator<KAction> it( d->m_toolbarList );
01303     for ( ; it.current() ; ++it )
01304         if ( !strcmp( it.current()->name(), tbName ) )
01305         {
01306             //kdDebug(30003) << "KoMainWindow::showToolbar setChecked " << shown << endl;
01307             static_cast<KToggleAction *>(it.current())->setChecked( shown );
01308             break;
01309         }
01310 }
01311 
01312 void KoMainWindow::slotSplitView() {
01313     d->m_splitted=true;
01314     d->m_rootViews.append(d->m_rootDoc->createView(d->m_splitter, "splitted-view"));
01315     d->m_rootViews.current()->show();
01316     d->m_rootViews.current()->setPartManager( d->m_manager );
01317     d->m_manager->setActivePart( d->m_rootDoc, d->m_rootViews.current() );
01318     d->m_removeView->setEnabled(true);
01319     d->m_orientation->setEnabled(true);
01320 }
01321 
01322 void KoMainWindow::slotCloseAllViews() {
01323 
01324     // Attention: Very touchy code... you know what you're doing? Goooood :)
01325     d->m_forQuit=true;
01326     if(queryClose()) {
01327         // In case the document is embedded we close all open "extra-shells"
01328         if(d->m_rootDoc && d->m_rootDoc->isEmbedded()) {
01329             hide();
01330             d->m_rootDoc->removeShell(this);
01331             QPtrListIterator<KoMainWindow> it(d->m_rootDoc->shells());
01332             while (it.current()) {
01333                 it.current()->hide();
01334                 delete it.current(); // this updates the lists' current pointer and thus
01335                                      // the iterator (the shell dtor calls removeShell)
01336             d->m_rootDoc=0;
01337             }
01338         }
01339         // not embedded -> destroy the document and all shells/views ;)
01340         else
01341             setRootDocument( 0L );
01342         close();  // close this window (and quit the app if necessary)
01343     }
01344     d->m_forQuit=false;
01345 }
01346 
01347 void KoMainWindow::slotRemoveView() {
01348     KoView *view;
01349     if(d->m_rootViews.findRef(d->m_activeView)!=-1)
01350         view=d->m_rootViews.current();
01351     else
01352         view=d->m_rootViews.first();
01353     view->hide();
01354     if ( !d->m_rootViews.removeRef(view) )
01355         kdWarning() << "view not found in d->m_rootViews!" << endl;
01356 
01357     if(d->m_rootViews.count()==1)
01358     {
01359         d->m_removeView->setEnabled(false);
01360         d->m_orientation->setEnabled(false);
01361     }
01362     // Prevent the view's destroyed() signal from triggering GUI rebuilding (too early)
01363     d->m_manager->setActivePart( 0, 0 );
01364 
01365     delete view;
01366     view=0L;
01367 
01368     d->m_rootViews.first()->setPartManager( d->m_manager );
01369     d->m_manager->setActivePart( d->m_rootDoc, d->m_rootViews.first() );
01370 
01371     if(d->m_rootViews.count()==1)
01372         d->m_splitted=false;
01373 }
01374 
01375 void KoMainWindow::slotSetOrientation() {
01376     d->m_splitter->setOrientation(static_cast<Qt::Orientation>
01377                                   (d->m_orientation->currentItem()));
01378 }
01379 
01380 void KoMainWindow::slotProgress(int value) {
01381     //kdDebug(30003) << "KoMainWindow::slotProgress " << value << endl;
01382     if(value==-1) {
01383         if ( d->m_progress )
01384         {
01385             statusBar()->removeWidget(d->m_progress);
01386             delete d->m_progress;
01387             d->m_progress=0L;
01388         }
01389         d->m_firstTime=true;
01390         return;
01391     }
01392     if(d->m_firstTime)
01393     {
01394         // The statusbar might not even be created yet.
01395         // So check for that first, and create it if necessary
01396         QObjectList *l = queryList( "QStatusBar" );
01397         if ( !l || !l->first() ) {
01398             statusBar()->show();
01399             QApplication::sendPostedEvents( this, QEvent::ChildInserted );
01400             setUpLayout();
01401         }
01402         delete l;
01403 
01404         if ( d->m_progress )
01405         {
01406             statusBar()->removeWidget(d->m_progress);
01407             delete d->m_progress;
01408             d->m_progress=0L;
01409         }
01410         statusBar()->setMaximumHeight(statusBar()->height());
01411         d->m_progress=new KProgress(statusBar());
01412         //d->m_progress->setMaximumHeight(statusBar()->height());
01413         statusBar()->addWidget( d->m_progress, 0, true );
01414         d->m_progress->show();
01415         d->m_firstTime=false;
01416     }
01417     d->m_progress->setProgress(value);
01418     kapp->processEvents();
01419 }
01420 
01421 
01422 void KoMainWindow::slotActivePartChanged( KParts::Part *newPart )
01423 {
01424 
01425   // This looks very much like KParts::MainWindow::createGUI, but we have
01426   // to reimplement it because it works with an active part, whereas we work
01427   // with an active view _and_ an active part, depending for what.
01428   // Both are KXMLGUIClients, but e.g. the plugin query needs a QObject.
01429   //kdDebug(30003) <<  "KoMainWindow::slotActivePartChanged( Part * newPart) newPart = " << newPart << endl;
01430   //kdDebug(30003) <<  "current active part is " << d->m_activePart << endl;
01431 
01432   if ( d->m_activePart && d->m_activePart == newPart && !d->m_splitted )
01433   {
01434     //kdDebug(30003) << "no need to change the GUI" << endl;
01435     return;
01436   }
01437 
01438   KXMLGUIFactory *factory = guiFactory();
01439 
01440   setUpdatesEnabled( false );
01441 
01442   if ( d->m_activeView )
01443   {
01444     KParts::GUIActivateEvent ev( false );
01445     QApplication::sendEvent( d->m_activePart, &ev );
01446     QApplication::sendEvent( d->m_activeView, &ev );
01447 
01448 
01449     factory->removeClient( d->m_activeView );
01450 
01451     unplugActionList( "toolbarlist" );
01452     d->m_toolbarList.clear(); // deletes the actions
01453   }
01454 
01455   if ( !d->bMainWindowGUIBuilt )
01456   {
01457     // Load mainwindow plugins
01458     KParts::Plugin::loadPlugins( this, this, instance(), true );
01459     createShellGUI();
01460   }
01461 
01462   if ( newPart && d->m_manager->activeWidget() && d->m_manager->activeWidget()->inherits( "KoView" ) )
01463   {
01464     d->m_activeView = (KoView *)d->m_manager->activeWidget();
01465     d->m_activePart = newPart;
01466     //kdDebug(30003) <<  "new active part is " << d->m_activePart << endl;
01467 
01468     factory->addClient( d->m_activeView );
01469 
01470 
01471     // This gets plugged in even for embedded views
01472     factory->plugActionList(d->m_activeView, "view_closeallviews",
01473                             d->m_veryHackyActionList);
01474     // This one only for root views
01475     if(d->m_rootViews.findRef(d->m_activeView)!=-1)
01476         factory->plugActionList(d->m_activeView, "view_split", d->m_splitViewActionList );
01477 
01478     // Position and show toolbars according to user's preference
01479     setAutoSaveSettings( newPart->instance()->instanceName(), false );
01480 
01481     // Create and plug toolbar list for Settings menu
01482     //QPtrListIterator<KToolBar> it = toolBarIterator();
01483     QPtrList<QWidget> toolBarList = factory->containers( "ToolBar" );
01484     QPtrListIterator<QWidget> it( toolBarList );
01485     for ( ; it.current() ; ++it )
01486     {
01487       if ( it.current()->inherits("KToolBar") )
01488       {
01489           KToolBar * tb = static_cast<KToolBar *>(it.current());
01490           KToggleAction * act = new KToggleAction( i18n("Show %1 Toolbar").arg( tb->text() ), 0,
01491                                                actionCollection(), tb->name() );
01492       act->setCheckedState(i18n("Hide %1 Toolbar").arg( tb->text() ));
01493       connect( act, SIGNAL( toggled( bool ) ), this, SLOT( slotToolbarToggled( bool ) ) );
01494           act->setChecked ( !tb->isHidden() );
01495           d->m_toolbarList.append( act );
01496       }
01497       else
01498           kdWarning(30003) << "Toolbar list contains a " << it.current()->className() << " which is not a toolbar!" << endl;
01499     }
01500     plugActionList( "toolbarlist", d->m_toolbarList );
01501 
01502     // Send the GUIActivateEvent only now, since it might show/hide toolbars too
01503     // (and this has priority over applyMainWindowSettings)
01504     KParts::GUIActivateEvent ev( true );
01505     QApplication::sendEvent( d->m_activePart, &ev );
01506     QApplication::sendEvent( d->m_activeView, &ev );
01507   }
01508   else
01509   {
01510     d->m_activeView = 0L;
01511     d->m_activePart = 0L;
01512   }
01513   setUpdatesEnabled( true );
01514 }
01515 
01516 QLabel * KoMainWindow::statusBarLabel()
01517 {
01518   if ( !d->statusBarLabel )
01519   {
01520     d->statusBarLabel = new QLabel( statusBar() );
01521     statusBar()->addWidget( d->statusBarLabel, 1, true );
01522   }
01523   return d->statusBarLabel;
01524 }
01525 
01526 void KoMainWindow::setMaxRecentItems(uint _number)
01527 {
01528         m_recent->setMaxItems( _number );
01529 }
01530 
01531 DCOPObject * KoMainWindow::dcopObject()
01532 {
01533     if ( !d->m_dcopObject )
01534     {
01535         d->m_dcopObject = new KoMainWindowIface( this );
01536     }
01537 
01538     return d->m_dcopObject;
01539 }
01540 
01541 void KoMainWindow::slotEmailFile()
01542 {
01543     if (!rootDocument())
01544         return;
01545 
01546     // Subject = Document file name
01547     // Attachment = The current file
01548     // Message Body = The current document in HTML export? <-- This may be an option.
01549     QString theSubject;
01550     QStringList urls;
01551     QString fileURL;
01552     if (rootDocument()->url ().isEmpty () ||
01553         rootDocument()->isModified())
01554     {
01555         //Save the file as a temporary file
01556         bool const tmp_modified = rootDocument()->isModified();
01557         KURL const tmp_url = rootDocument()->url();
01558         QCString const tmp_mimetype = rootDocument()->outputMimeType();
01559         KTempFile tmpfile; //TODO: The temorary file should be deleted when the mail program is closed
01560         KURL u;
01561         u.setPath(tmpfile.name());
01562         rootDocument()->setURL(u);
01563         rootDocument()->setModified(true);
01564         rootDocument()->setOutputMimeType(rootDocument()->nativeFormatMimeType());
01565 
01566         saveDocument(false, true);
01567 
01568         fileURL = tmpfile.name();
01569         theSubject = i18n("Document");
01570         urls.append( fileURL );
01571 
01572         rootDocument()->setURL(tmp_url);
01573         rootDocument()->setModified(tmp_modified);
01574         rootDocument()->setOutputMimeType(tmp_mimetype);
01575     }
01576     else
01577     {
01578         fileURL = rootDocument()->url().url();
01579         theSubject = i18n("Document - %1").arg(rootDocument()->url().fileName(false));
01580         urls.append( fileURL );
01581     }
01582 
01583     kdDebug(30003) << "(" << fileURL <<")" << endl;
01584 
01585     if (!fileURL.isEmpty())
01586     {
01587         kapp->invokeMailer(QString::null, QString::null, QString::null, theSubject,
01588                             QString::null, //body
01589                             QString::null,
01590                             urls); // attachments
01591     }
01592 }
01593 
01594 void KoMainWindow::slotVersionsFile()
01595 {
01596     KoVersionDialog *dlg = new KoVersionDialog(  this );
01597     dlg->exec();
01598     delete dlg;
01599 }
01600 
01601 void KoMainWindow::slotReloadFile()
01602 {
01603     KoDocument* pDoc = rootDocument();
01604     if(!pDoc || pDoc->url().isEmpty() || !pDoc->isModified())
01605         return;
01606 
01607     bool bOk = KMessageBox::questionYesNo( this,
01608                                       i18n("You will lose all your changes!\n"
01609                                            "Do you want to continue?"),
01610                                       i18n("Warning") ) == KMessageBox::Yes;
01611     if ( !bOk )
01612         return;
01613 
01614     KURL url = pDoc->url();
01615     if ( pDoc && !pDoc->isEmpty() )
01616     {
01617         setRootDocument( 0L ); // don't delete this shell when deleting the document
01618         delete d->m_rootDoc;
01619         d->m_rootDoc = 0L;
01620     }
01621     openDocument( url );
01622     return;
01623 
01624 }
01625 
01626 void KoMainWindow::slotImportFile()
01627 {
01628     kdDebug(30003) << "slotImportFile()" << endl;
01629 
01630     d->m_isImporting = true;
01631     slotFileOpen();
01632     d->m_isImporting = false;
01633 }
01634 
01635 void KoMainWindow::slotExportFile()
01636 {
01637     kdDebug(30003) << "slotExportFile()" << endl;
01638 
01639     d->m_isExporting = true;
01640     slotFileSaveAs();
01641     d->m_isExporting = false;
01642 }
01643 
01644 bool KoMainWindow::isImporting() const
01645 {
01646     return d->m_isImporting;
01647 }
01648 
01649 bool KoMainWindow::isExporting() const
01650 {
01651     return d->m_isExporting;
01652 }
01653 
01654 #include <koMainWindow.moc>
KDE Logo
This file is part of the documentation for lib Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:40:02 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003