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