koshell

koshell_shell.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00003    Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
00004    Copyright (C) 2000-2005 David Faure <faure@kde.org>
00005    Copyright (C) 2005, 2006 Sven Lüppken <sven@kde.org>
00006 
00007    This program is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU General Public
00009    License as published by the Free Software Foundation; either
00010    version 2 of the License, or (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; see the file COPYING.  If not, write to
00019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include <qcursor.h>
00024 #include <qsplitter.h>
00025 #include <qiconview.h>
00026 #include <qlabel.h>
00027 #include <qvbox.h>
00028 
00029 #include <assert.h>
00030 
00031 #include "koshell_shell.h"
00032 #include "koshellsettings.h"
00033 
00034 #include <kapplication.h>
00035 #include <ktempfile.h>
00036 #include <kfiledialog.h>
00037 #include <klocale.h>
00038 #include <kdebug.h>
00039 #include <kiconloader.h>
00040 #include <kkeydialog.h>
00041 #include <kstandarddirs.h>
00042 #include <klibloader.h>
00043 #include <kpopupmenu.h>
00044 #include <kservice.h>
00045 #include <kmessagebox.h>
00046 #include <krecentdocument.h>
00047 #include <kparts/partmanager.h>
00048 #include <kaction.h>
00049 #include <kdeversion.h>
00050 #include <kaboutdata.h>
00051 
00052 #include <KoQueryTrader.h>
00053 #include <KoDocumentInfo.h>
00054 #include <KoDocument.h>
00055 #include <KoView.h>
00056 #include <KoPartSelectDia.h>
00057 #include <KoFilterManager.h>
00058 #include <kiconloader.h>
00059 
00060 KoShellWindow::KoShellWindow()
00061  : KoMainWindow( KGlobal::instance() )
00062 {
00063   m_activePage = m_lstPages.end();
00064 
00065   m_pLayout = new QSplitter( centralWidget() );
00066 
00067   // Setup the sidebar
00068   m_pSidebar = new IconSidePane( m_pLayout );
00069   m_pSidebar->setSizePolicy( QSizePolicy( QSizePolicy::Maximum,
00070                              QSizePolicy::Preferred ) );
00071   m_pSidebar->setActionCollection( actionCollection() );
00072   m_grpFile = m_pSidebar->insertGroup(i18n("Components"), false, this, SLOT( slotSidebar_Part(int )));
00073   m_grpDocuments = m_pSidebar->insertGroup(i18n("Documents"), true, this, SLOT(slotSidebar_Document(int)));
00074   m_pLayout->setResizeMode(m_pSidebar,QSplitter::FollowSizeHint);
00075 
00076   // Setup the tabbar
00077   m_pFrame = new KTabWidget( m_pLayout );
00078   m_pFrame->setSizePolicy( QSizePolicy( QSizePolicy::Minimum,
00079                             QSizePolicy::Preferred ) );
00080   m_pFrame->setTabPosition( KTabWidget::Bottom );
00081 
00082   m_tabCloseButton = new QToolButton( m_pFrame );
00083   connect( m_tabCloseButton, SIGNAL( clicked() ),
00084            this, SLOT( slotFileClose() ) );
00085   m_tabCloseButton->setIconSet( SmallIconSet( "tab_remove" ) );
00086   m_tabCloseButton->adjustSize();
00087   QToolTip::add(m_tabCloseButton, i18n("Close"));
00088   m_pFrame->setCornerWidget( m_tabCloseButton, BottomRight );
00089   m_tabCloseButton->hide();
00090 
00091   QValueList<KoDocumentEntry> lstComponents = KoDocumentEntry::query(false,QString());
00092   QValueList<KoDocumentEntry>::Iterator it = lstComponents.begin();
00093   int id = 0;
00094   // Get all available components
00095   for( ; it != lstComponents.end(); ++it )
00096   {
00097       KService* service = (*it).service();
00098       if ( !service->genericName().isEmpty() )
00099       {
00100           id = m_pSidebar->insertItem(m_grpFile, service->icon(), service->genericName());
00101       }
00102       else
00103       {
00104           continue;
00105       }
00106 
00107       m_mapComponents[ id++ ] = *it;
00108   }
00109 
00110   QValueList<int> list;
00111   list.append( KoShellSettings::sidebarWidth() );
00112   list.append( this->width() - KoShellSettings::sidebarWidth() );
00113   m_pLayout->setSizes( list );
00114 
00115   connect( this, SIGNAL( documentSaved() ),
00116            this, SLOT( slotNewDocumentName() ) );
00117 
00118   connect( m_pFrame, SIGNAL( currentChanged( QWidget* ) ),
00119            this, SLOT( slotUpdatePart( QWidget* ) ) );
00120   connect( m_pFrame, SIGNAL( contextMenu(QWidget * ,const QPoint &)), this, SLOT( tab_contextMenu(QWidget * ,const QPoint &)) );
00121 
00122   m_client = new KoShellGUIClient( this );
00123   createShellGUI();
00124 }
00125 
00126 KoShellWindow::~KoShellWindow()
00127 {
00128   //kdDebug() << "KoShellWindow::~KoShellWindow()" << endl;
00129 
00130   // Set the active part to 0 (as we do in ~KoMainWindow, but this is too
00131   // late for KoShell, it gets activePartChanged signals delivered to a dead
00132   // KoShellWindow object).
00133   partManager()->setActivePart(0);
00134 
00135   // Destroy all documents - queryClose has made sure we saved them first
00136   QValueList<Page>::ConstIterator it = m_lstPages.begin();
00137   for (; it != m_lstPages.end(); ++it )
00138   {
00139     (*it).m_pDoc->removeShell( this );
00140     delete (*it).m_pView;
00141     if ( (*it).m_pDoc->viewCount() == 0 )
00142       delete (*it).m_pDoc;
00143   }
00144   m_lstPages.clear();
00145 
00146   setRootDocumentDirect( 0L, QPtrList<KoView>() ); // prevent our parent destructor from doing stupid things
00147   saveSettings(); // Now save our settings before exiting
00148 }
00149 
00150 bool KoShellWindow::openDocumentInternal( const KURL &url, KoDocument* )
00151 {
00152   // Here we have to distinguish two cases: The passed URL has a native
00153   // KOffice mimetype. Then we query the trader and create the document.
00154   // The file is loaded and everyone's happy.
00155   // The second case is a non-native file. Here we have to create a
00156   // filter manager, ask it to convert the file to the "closest" available
00157   // KOffice part and open the temporary file.
00158   
00159   /*if (!KIO::NetAccess::exists(url,true,0) )
00160   {
00161     KMessageBox::error(0L, i18n("The file %1 doesn't exist.").arg(url.url()) );
00162     recentAction()->removeURL(url); //remove the file from the recent-opened-file-list
00163     saveRecentFiles();
00164     return false;
00165   }*/
00166   
00167   KMimeType::Ptr mimeType = KMimeType::findByURL( url );
00168   m_documentEntry = KoDocumentEntry::queryByMimeType( mimeType->name().latin1() );
00169 
00170   KTempFile* tmpFile = 0;
00171   KURL tmpUrl( url );  // we might have to load a converted temp. file
00172 
00173   if ( m_documentEntry.isEmpty() ) { // non-native
00174     tmpFile = new KTempFile;
00175 
00176     KoFilterManager *manager = new KoFilterManager( url.path() );
00177     QCString mimetype;                                               // an empty mimetype means, that the "nearest"
00178     KoFilter::ConversionStatus status = manager->exp0rt( tmpFile->name(), mimetype ); // KOffice part will be chosen
00179     delete manager;
00180 
00181     if ( status != KoFilter::OK || mimetype.isEmpty() ) {
00182       tmpFile->unlink();
00183       delete tmpFile;
00184       return false;
00185     }
00186 
00187     // If the conversion was successful we get the mimetype of the
00188     // chosen KOffice part back.
00189     m_documentEntry = KoDocumentEntry::queryByMimeType( mimetype );
00190     if ( m_documentEntry.isEmpty() ) {
00191       tmpFile->unlink();
00192       delete tmpFile;
00193       return false;
00194     }
00195 
00196     // Open the temporary file
00197     tmpUrl.setPath( tmpFile->name() );
00198   }
00199 
00200   recentAction()->addURL( url );
00201 
00202   KoDocument* newdoc = m_documentEntry.createDoc();
00203 
00204   connect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00205   connect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted()));
00206   connect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & )));
00207   newdoc->addShell( this ); // used by openURL
00208   bool openRet = (!isImporting ()) ? newdoc->openURL(tmpUrl) : newdoc->import(tmpUrl);
00209   if ( !newdoc || !openRet )
00210   {
00211       newdoc->removeShell(this);
00212       delete newdoc;
00213       if ( tmpFile ) {
00214         tmpFile->unlink();
00215         delete tmpFile;
00216       }
00217       return false;
00218   }
00219 
00220   if ( tmpFile ) {
00221     //if the loaded file has been a temporary file
00222     //we need to correct a few document settings
00223     //see description of bug #77574 for additional information
00224 
00225     //correct (output) mime type: we need to set it to the non-native format
00226     //to make sure the user knows about saving to a non-native mime type
00227     //setConfirmNonNativeSave is set to true below
00228     newdoc->setMimeType( mimeType->name().latin1() );
00229     newdoc->setOutputMimeType( mimeType->name().latin1() );
00230 
00231     //the next time the user saves the document he should be warned
00232     //because of mime type settings done above;
00233     newdoc->setConfirmNonNativeSave(true,true); //exporting,warn_on
00234     newdoc->setConfirmNonNativeSave(false,true); //save/save as,warn_on
00235 
00236     //correct document file (should point to URL)
00237     newdoc->setFile( url.path() );
00238 
00239     //correct document URL
00240     newdoc->setURL( url );
00241 
00242     //update caption to represent the correct URL in the window titlebar
00243     updateCaption();
00244 
00245     tmpFile->unlink();
00246     delete tmpFile;
00247   }
00248   return true;
00249 }
00250 
00251 void KoShellWindow::slotSidebarItemClicked( QIconViewItem *item )
00252 {
00253   //kdDebug() << "slotSidebarItemClicked called!" << endl;
00254   if( item != 0 )
00255   {
00256     int index = item->index();
00257   
00258     // Create new document from a KoDocumentEntry
00259     m_documentEntry = m_mapComponents[ index ];
00260     KoDocument *doc = m_documentEntry.createDoc();
00261     if (doc)
00262     {
00263         // koshell isn't starting, but this is like starting a new app:
00264         // offer both "open existing file" and "open new file".
00265         if ( doc->showEmbedInitDialog( this ) )
00266         {
00267             partManager()->addPart( doc, false );
00268             setRootDocument( doc );
00269         }
00270         else
00271             delete doc;
00272     }
00273   }
00274 }
00275 
00276 // Separate from openDocument to handle async loading (remote URLs)
00277 void KoShellWindow::slotKSLoadCompleted()
00278 {
00279     KoDocument* newdoc = (KoDocument *)(sender());
00280 
00281     // KoDocument::import() calls resetURL() too late...
00282     // ...setRootDocument will show the URL...
00283     // So let's stop this from happening and the user will never know :)
00284     if (isImporting()) newdoc->resetURL ();
00285 
00286     partManager()->addPart( newdoc, false );
00287     setRootDocument( newdoc );
00288     disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00289     disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted()));
00290     disconnect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & )));
00291 }
00292 
00293 void KoShellWindow::slotKSLoadCanceled( const QString & errMsg )
00294 {
00295     KMessageBox::error( this, errMsg );
00296     // ... can't delete the document, it's the one who emitted the signal...
00297     // ###### FIXME: This can be done in 3.0 with deleteLater, I assume (Werner)
00298 
00299     KoDocument* newdoc = (KoDocument *)(sender());
00300     disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00301     disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted()));
00302     disconnect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & )));
00303 }
00304 
00305 void KoShellWindow::saveAll()
00306 {
00307   KoView *currentView = (*m_activePage).m_pView;
00308   for (QValueList<Page>::iterator it=m_lstPages.begin(); it != m_lstPages.end(); ++it)
00309   {
00310     if ( (*it).m_pDoc->isModified() )
00311     {
00312       m_pFrame->showPage( (*it).m_pView );
00313       (*it).m_pView->shell()->slotFileSave();
00314       if ( (*it).m_pDoc->isModified() )
00315         break;
00316     }
00317   }
00318   m_pFrame->showPage( currentView );
00319 }
00320 
00321 void KoShellWindow::setRootDocument( KoDocument * doc )
00322 {
00323   kdDebug() << "KoShellWindow::setRootDocument this=" << this << " doc=" << doc << endl;
00324   // We do things quite differently from KoMainWindow::setRootDocument
00325   // This one is called with doc != 0 when a new doc is created
00326   // and with 0L after they have all been removed.
00327   // We use setRootDocumentDirect to switch the 'root doc' known by KoMainWindow.
00328 
00329   if ( doc )
00330   {
00331     if ( !doc->shells().contains( this ) )
00332         doc->addShell( this );
00333 
00334     KoView *v = doc->createView(this);
00335     QPtrList<KoView> views;
00336     views.append(v);
00337     setRootDocumentDirect( doc, views );
00338     
00339     v->setGeometry( 0, 0, m_pFrame->width(), m_pFrame->height() );
00340     v->setPartManager( partManager() );
00341     m_pFrame->addTab( v, KGlobal::iconLoader()->loadIcon( m_documentEntry.service()->icon(), KIcon::Small ), i18n("Untitled") );
00342     
00343     // Create a new page for this doc
00344     Page page;
00345     page.m_pDoc = doc;
00346     page.m_pView = v;
00347     // insert the new document in the sidebar
00348     page.m_id = m_pSidebar->insertItem( m_grpDocuments,
00349                                        m_documentEntry.service()->icon(),
00350                                        i18n("Untitled"));
00351     m_lstPages.append( page );
00352     v->show();
00353 
00354     switchToPage( m_lstPages.fromLast() );
00355     mnuSaveAll->setEnabled(true);
00356   } else
00357   {
00358     setRootDocumentDirect( 0L, QPtrList<KoView>() );
00359     m_activePage = m_lstPages.end();
00360     KoMainWindow::updateCaption();
00361   }
00362 }
00363 
00364 void KoShellWindow::slotNewDocumentName()
00365 {
00366     updateCaption();
00367 }
00368 
00369 void KoShellWindow::updateCaption()
00370 {
00371     //kdDebug() << "KoShellWindow::updateCaption() rootDoc=" << rootDocument() << endl;
00372     KoMainWindow::updateCaption();
00373     // Let's take this opportunity for setting a correct name for the icon
00374     // in koolbar
00375     QValueList<Page>::Iterator it = m_lstPages.begin();
00376     for( ; it != m_lstPages.end() ; ++it )
00377     {
00378       if ( (*it).m_pDoc == rootDocument() )
00379       {
00380         //kdDebug() << "updateCaption called for " << rootDocument() << endl;
00381         // Get caption from document info (title(), in about page)
00382         QString name;
00383         if ( rootDocument()->documentInfo() )
00384         {
00385             name = rootDocument()->documentInfo()->title();
00386         }
00387         if ( name.isEmpty() )
00388             // Fall back to document URL
00389             name = rootDocument()->url().fileName();
00390 
00391         if ( !name.isEmpty() ) // else keep Untitled
00392         {
00393           if ( name.length() > 20 )
00394           {
00395             name.truncate( 17 );
00396             name += "...";
00397           }
00398           m_pFrame->changeTab( m_pFrame->currentPage(), name );
00399           m_pSidebar->renameItem(m_grpDocuments, (*m_activePage).m_id, name); //remove the document from the sidebar
00400         }
00401 
00402         return;
00403       }
00404     }
00405 }
00406 
00407 
00408 void KoShellWindow::slotSidebar_Part(int _item)
00409 {
00410   //kdDebug() << "Component part choosed:" << _item << endl;
00411   kapp->setOverrideCursor( QCursor(Qt::WaitCursor) );
00412   m_documentEntry = m_mapComponents[ _item ];
00413   kdDebug() << m_documentEntry.service() << endl;
00414   kdDebug() << m_documentEntry.name() << endl;
00415   KoDocument *doc = m_documentEntry.createDoc();
00416   kapp->restoreOverrideCursor();
00417   if (doc)
00418   {
00419     if ( doc->showEmbedInitDialog( this ) )
00420     {
00421       partManager()->addPart( doc, false );
00422       setRootDocument( doc );
00423       m_tabCloseButton->show();
00424     }
00425     else
00426       delete doc;
00427   }
00428 }
00429 
00430 void KoShellWindow::slotSidebar_Document(int _item)
00431 {
00432     // Switch to an existing document
00433   if ( m_activePage != m_lstPages.end() &&
00434        (*m_activePage).m_id == _item )
00435     return;
00436     
00437   QValueList<Page>::Iterator it = m_lstPages.begin();
00438   while( it != m_lstPages.end() )
00439   {
00440     if ( (*it).m_id == _item )
00441     {
00442       switchToPage( it );
00443       return;
00444     }
00445     ++it;
00446   }
00447 }
00448 
00449 void KoShellWindow::slotShowSidebar()
00450 {
00451   if( m_pSidebar->isShown() )
00452   {
00453     m_pSidebar->hide();
00454     m_pComponentsLabel->hide();
00455   }
00456   else
00457   {
00458     m_pSidebar->show();
00459     m_pComponentsLabel->show();
00460   }
00461 }
00462 
00463 void KoShellWindow::slotUpdatePart( QWidget* widget )
00464 {
00465   KoView* v = dynamic_cast<KoView*>(widget);
00466   if ( v != 0 ) 
00467   {
00468     QValueList<Page>::Iterator it = m_lstPages.begin();
00469     for( ; it != m_lstPages.end(); ++it )
00470     {
00471       if( (*it).m_pView == v )
00472         switchToPage(it);
00473     }
00474   }
00475 }
00476 
00477 void KoShellWindow::switchToPage( QValueList<Page>::Iterator it )
00478 {
00479   // Select new active page (view)
00480   m_activePage = it;
00481   KoView *v = (*m_activePage).m_pView;
00482 
00483   kdDebug() << " setting active part to " << (*m_activePage).m_pDoc << endl;
00484   // Make it active (GUI etc.)
00485   partManager()->setActivePart( (*m_activePage).m_pDoc, v );
00486   // Change current document
00487   QPtrList<KoView> views;
00488   views.append(v);
00489   setRootDocumentDirect( (*m_activePage).m_pDoc, views );
00490   // Select the item in the sidebar
00491   m_pSidebar->group(m_grpDocuments)->setSelected((*m_activePage).m_id,true);
00492   // Raise the new page
00493   m_pFrame->showPage( v );
00494   // Fix caption and set focus to the new view
00495   updateCaption();
00496   v->setFocus();
00497 
00498   partSpecificHelpAction->setEnabled(true);
00499   partSpecificHelpAction->setText(i18n("%1 Handbook").arg((*m_activePage).m_pDoc->instance()->aboutData()->programName()));
00500 }
00501 
00502 void KoShellWindow::slotFileNew()
00503 {
00504     m_documentEntry = KoPartSelectDia::selectPart( this );
00505     if ( m_documentEntry.isEmpty() )
00506       return;
00507     KoDocument* newdoc = m_documentEntry.createDoc();
00508     if ( !newdoc )
00509         return;
00510     if ( !newdoc->showEmbedInitDialog( this ) )
00511     {
00512       delete newdoc;
00513       return;
00514     }
00515 
00516     partManager()->addPart( newdoc, false );
00517     setRootDocument( newdoc );
00518     m_tabCloseButton->show();
00519 }
00520 
00521 void KoShellWindow::slotFileOpen()
00522 {
00523     KFileDialog *dialog=new KFileDialog(QString::null, QString::null, 0L, "file dialog", true);
00524     if (!isImporting())
00525         dialog->setCaption( i18n("Open Document") );
00526     else
00527         dialog->setCaption( i18n("Import Document") );
00528     dialog->setMimeFilter( KoFilterManager::mimeFilter() );
00529 
00530     KURL url;
00531     if(dialog->exec()==QDialog::Accepted) {
00532         url=dialog->selectedURL();
00533         recentAction()->addURL( url );
00534         if ( url.isLocalFile() )
00535             KRecentDocument::add(url.path(-1));
00536         else
00537             KRecentDocument::add(url.url(-1), true);
00538     }
00539     else
00540         return;
00541 
00542     delete dialog;
00543     if ( url.isEmpty() )
00544         return;
00545 
00546     (void) openDocumentInternal( url );
00547     m_tabCloseButton->show();
00548 }
00549 
00550 void KoShellWindow::slotFileClose()
00551 {
00552   // reimplemented to avoid closing the window when we have docs opened
00553 
00554   // No docs at all ?
00555   if ( m_lstPages.count() == 0 )
00556     close(); // close window
00557   else
00558     closeDocument(); // close only doc
00559 
00560   if ( m_pFrame->count() == 0 )
00561     m_tabCloseButton->hide();
00562 }
00563 
00564 void KoShellWindow::closeDocument()
00565 {
00566   // Set the root document to the current one - so that queryClose acts on it
00567   assert( m_activePage != m_lstPages.end() );
00568   assert( rootDocument() == (*m_activePage).m_pDoc );
00569 
00570   // First do the standard queryClose
00571   kdDebug() << "KoShellWindow::closeDocument calling standard queryClose" << endl;
00572   if ( KoMainWindow::queryClose() )
00573   {
00574     kdDebug() << "Ok for closing document" << endl;
00575     m_pSidebar->removeItem(m_grpDocuments, (*m_activePage).m_id ); //remove the document from the sidebar
00576     (*m_activePage).m_pDoc->removeShell(this);
00577     Page oldPage = (*m_activePage); // make a copy of the struct
00578     m_lstPages.remove( m_activePage );
00579     m_activePage = m_lstPages.end(); // no active page right now
00580     m_pSidebar->group(m_grpDocuments)->setSelected((*m_activePage).m_id, true); //select the new document in the sidebar
00581 
00582     kdDebug() << "m_lstPages has " << m_lstPages.count() << " documents" << endl;
00583     if ( m_lstPages.count() > 0 )
00584     {
00585       kdDebug() << "Activate the document behind" << endl;
00586       switchToPage( m_lstPages.fromLast() );
00587     }
00588     else
00589     {
00590       kdDebug() << "Revert to initial state (no docs)" << endl;
00591       setRootDocument( 0L );
00592       partManager()->setActivePart( 0L, 0L );
00593       mnuSaveAll->setEnabled(false);
00594       partSpecificHelpAction->setEnabled(false);
00595       partSpecificHelpAction->setText(i18n("Part Handbook"));
00596     }
00597 
00598     // Now delete the old view and page
00599     // Don't do it before, because setActivePart will call slotActivePartChanged,
00600     // which needs the old view (to unplug it and its plugins)
00601     delete oldPage.m_pView;
00602     if ( oldPage.m_pDoc->viewCount() <= 1 )
00603       delete oldPage.m_pDoc;
00604 
00605   }
00606   kdDebug() << "m_lstPages has " << m_lstPages.count() << " documents" << endl;
00607 }
00608 
00609 bool KoShellWindow::queryClose()
00610 {
00611   // Save current doc and views
00612   QPtrList<KoView> currentViews;
00613   KoDocument * currentDoc = 0L;
00614   bool ok = true;
00615   if (m_activePage != m_lstPages.end())
00616   {
00617       currentDoc = (*m_activePage).m_pDoc;
00618       currentViews.append((*m_activePage).m_pView);
00619 
00620       // This one is called by slotFileQuit and by the X button.
00621       // We have to check for unsaved docs...
00622       QValueList<Page>::Iterator it = m_lstPages.begin();
00623       for( ; it != m_lstPages.end(); ++it )
00624       {
00625           // This is quite a HACK
00626           // We should ask ourselves, to get a better dialog box
00627           setRootDocumentDirect( (*it).m_pDoc, QPtrList<KoView>() );
00628           // Test if we can close this doc
00629           if ( !KoMainWindow::queryClose() )
00630           {
00631               ok = false; // No
00632               break; // abort
00633           }
00634       }
00635 
00636   // Restore current doc and views
00637   setRootDocumentDirect( currentDoc, currentViews );
00638   }
00639   return ok;
00640 }
00641 
00642 /*
00643 // Should this be an additional action in the File menu ?
00644 bool KoShellWindow::saveAllPages()
00645 {
00646   // TODO
00647   return false;
00648 }
00649 */
00650 
00651 void KoShellWindow::saveSettings()
00652 {
00653   KoShellSettings::setSidebarWidth( m_pLayout->sizes().first() );
00654   KoShellSettings::writeConfig();
00655 }
00656 
00657 QString KoShellWindow::configFile() const
00658 {
00659   //return readConfigFile( locate( "data", "koshell/koshell_shell.rc" ) );
00660   return QString::null; // use UI standards only for now
00661 }
00662 
00663 void KoShellWindow::tab_contextMenu(QWidget * w,const QPoint &p)
00664 {
00665   KPopupMenu menu;
00666   KIconLoader il;
00667   int const mnuSave = menu.insertItem( il.loadIconSet( "filesave", KIcon::Small ), i18n("Save") );
00668   int const mnuClose = menu.insertItem( il.loadIcon( "fileclose", KIcon::Small ), i18n("Close") );
00669   
00670   int tabnr = m_pFrame->indexOf( w );
00671   Page page = m_lstPages[tabnr];
00672   // disable save if there's nothing to save
00673   if ( !page.m_pDoc->isModified() )
00674     menu.setItemEnabled( mnuSave, false );
00675   
00676   // show menu
00677   int const choice = menu.exec(p);
00678 
00679   if( choice == mnuClose )
00680   {
00681     const int index = m_pFrame->currentPageIndex();
00682     m_pFrame->setCurrentPage( tabnr );
00683     slotFileClose();
00684     if ( index > m_pFrame->currentPageIndex() )
00685       m_pFrame->setCurrentPage(index-1);
00686     else
00687       m_pFrame->setCurrentPage(index);
00688   }
00689   else if ( choice == mnuSave )
00690   {
00691       page.m_pView->shell()->slotFileSave();
00692   }
00693 }
00694 
00695 void KoShellWindow::slotConfigureKeys()
00696 {
00697   KoView *view = rootView();
00698   KKeyDialog dlg( this );
00699   dlg.insert( actionCollection() );
00700   if ( view )
00701      dlg.insert( view->actionCollection() );
00702   if ( rootDocument() )
00703     dlg.insert( rootDocument()->actionCollection() );
00704   dlg.configure();
00705 }
00706 
00707 void KoShellWindow::createShellGUI( bool  )
00708 {
00709     guiFactory()->addClient( m_client );
00710 }
00711 
00712 void KoShellWindow::showPartSpecificHelp()
00713 {
00714   if((m_activePage == m_lstPages.end()) || ((*m_activePage).m_pDoc == 0))
00715     return;
00716 
00717   kapp->invokeHelp("", (*m_activePage).m_pDoc->instance()->aboutData()->appName(), "");
00718 }
00719 
00720 
00722 KoShellGUIClient::KoShellGUIClient( KoShellWindow *window ) : KXMLGUIClient()
00723 {
00724   setXMLFile( "koshellui.rc", true, true );
00725   window->mnuSaveAll = new KAction( i18n("Save All"), 0, window, SLOT( saveAll() ), actionCollection(), "save_all" );
00726   window->mnuSaveAll->setEnabled(false);
00727   window->partSpecificHelpAction = new KAction(i18n("Part Handbook"), "contents", 0, window, SLOT(showPartSpecificHelp()),
00728                                                actionCollection(), "partSpecificHelp");
00729   window->partSpecificHelpAction->setEnabled(false);
00730 }
00731 
00732 #include "koshell_shell.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys