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   if ( !newdoc ) {
00204       if ( tmpFile ) {
00205         tmpFile->unlink();
00206         delete tmpFile;
00207       }
00208       return false;
00209   }
00210 
00211   connect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00212   connect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted()));
00213   connect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & )));
00214   newdoc->addShell( this ); // used by openURL
00215   bool openRet = (!isImporting ()) ? newdoc->openURL(tmpUrl) : newdoc->import(tmpUrl);
00216   if ( !openRet )
00217   {
00218       newdoc->removeShell(this);
00219       delete newdoc;
00220       if ( tmpFile ) {
00221         tmpFile->unlink();
00222         delete tmpFile;
00223       }
00224       return false;
00225   }
00226 
00227   if ( tmpFile ) {
00228     //if the loaded file has been a temporary file
00229     //we need to correct a few document settings
00230     //see description of bug #77574 for additional information
00231 
00232     //correct (output) mime type: we need to set it to the non-native format
00233     //to make sure the user knows about saving to a non-native mime type
00234     //setConfirmNonNativeSave is set to true below
00235     newdoc->setMimeType( mimeType->name().latin1() );
00236     newdoc->setOutputMimeType( mimeType->name().latin1() );
00237 
00238     //the next time the user saves the document he should be warned
00239     //because of mime type settings done above;
00240     newdoc->setConfirmNonNativeSave(true,true); //exporting,warn_on
00241     newdoc->setConfirmNonNativeSave(false,true); //save/save as,warn_on
00242 
00243     //correct document file (should point to URL)
00244     newdoc->setFile( url.path() );
00245 
00246     //correct document URL
00247     newdoc->setURL( url );
00248 
00249     //update caption to represent the correct URL in the window titlebar
00250     updateCaption();
00251 
00252     tmpFile->unlink();
00253     delete tmpFile;
00254   }
00255   return true;
00256 }
00257 
00258 void KoShellWindow::slotSidebarItemClicked( QIconViewItem *item )
00259 {
00260   //kdDebug() << "slotSidebarItemClicked called!" << endl;
00261   if( item != 0 )
00262   {
00263     int index = item->index();
00264   
00265     // Create new document from a KoDocumentEntry
00266     m_documentEntry = m_mapComponents[ index ];
00267     KoDocument *doc = m_documentEntry.createDoc();
00268     if (doc)
00269     {
00270         // koshell isn't starting, but this is like starting a new app:
00271         // offer both "open existing file" and "open new file".
00272         if ( doc->showEmbedInitDialog( this ) )
00273         {
00274             partManager()->addPart( doc, false );
00275             setRootDocument( doc );
00276         }
00277         else
00278             delete doc;
00279     }
00280   }
00281 }
00282 
00283 // Separate from openDocument to handle async loading (remote URLs)
00284 void KoShellWindow::slotKSLoadCompleted()
00285 {
00286     KoDocument* newdoc = (KoDocument *)(sender());
00287 
00288     // KoDocument::import() calls resetURL() too late...
00289     // ...setRootDocument will show the URL...
00290     // So let's stop this from happening and the user will never know :)
00291     if (isImporting()) newdoc->resetURL ();
00292 
00293     partManager()->addPart( newdoc, false );
00294     setRootDocument( newdoc );
00295     disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00296     disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted()));
00297     disconnect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & )));
00298 }
00299 
00300 void KoShellWindow::slotKSLoadCanceled( const QString & errMsg )
00301 {
00302     KMessageBox::error( this, errMsg );
00303     // ... can't delete the document, it's the one who emitted the signal...
00304     // ###### FIXME: This can be done in 3.0 with deleteLater, I assume (Werner)
00305 
00306     KoDocument* newdoc = (KoDocument *)(sender());
00307     disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int)));
00308     disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted()));
00309     disconnect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & )));
00310 }
00311 
00312 void KoShellWindow::saveAll()
00313 {
00314   KoView *currentView = (*m_activePage).m_pView;
00315   for (QValueList<Page>::iterator it=m_lstPages.begin(); it != m_lstPages.end(); ++it)
00316   {
00317     if ( (*it).m_pDoc->isModified() )
00318     {
00319       m_pFrame->showPage( (*it).m_pView );
00320       (*it).m_pView->shell()->slotFileSave();
00321       if ( (*it).m_pDoc->isModified() )
00322         break;
00323     }
00324   }
00325   m_pFrame->showPage( currentView );
00326 }
00327 
00328 void KoShellWindow::setRootDocument( KoDocument * doc )
00329 {
00330   kdDebug() << "KoShellWindow::setRootDocument this=" << this << " doc=" << doc << endl;
00331   // We do things quite differently from KoMainWindow::setRootDocument
00332   // This one is called with doc != 0 when a new doc is created
00333   // and with 0L after they have all been removed.
00334   // We use setRootDocumentDirect to switch the 'root doc' known by KoMainWindow.
00335 
00336   if ( doc )
00337   {
00338     if ( !doc->shells().contains( this ) )
00339         doc->addShell( this );
00340 
00341     KoView *v = doc->createView(this);
00342     QPtrList<KoView> views;
00343     views.append(v);
00344     setRootDocumentDirect( doc, views );
00345     
00346     v->setGeometry( 0, 0, m_pFrame->width(), m_pFrame->height() );
00347     v->setPartManager( partManager() );
00348     m_pFrame->addTab( v, KGlobal::iconLoader()->loadIcon( m_documentEntry.service()->icon(), KIcon::Small ), i18n("Untitled") );
00349     
00350     // Create a new page for this doc
00351     Page page;
00352     page.m_pDoc = doc;
00353     page.m_pView = v;
00354     // insert the new document in the sidebar
00355     page.m_id = m_pSidebar->insertItem( m_grpDocuments,
00356                                        m_documentEntry.service()->icon(),
00357                                        i18n("Untitled"));
00358     m_lstPages.append( page );
00359     v->show();
00360 
00361     switchToPage( m_lstPages.fromLast() );
00362     mnuSaveAll->setEnabled(true);
00363   } else
00364   {
00365     setRootDocumentDirect( 0L, QPtrList<KoView>() );
00366     m_activePage = m_lstPages.end();
00367     KoMainWindow::updateCaption();
00368   }
00369 }
00370 
00371 void KoShellWindow::slotNewDocumentName()
00372 {
00373     updateCaption();
00374 }
00375 
00376 void KoShellWindow::updateCaption()
00377 {
00378     //kdDebug() << "KoShellWindow::updateCaption() rootDoc=" << rootDocument() << endl;
00379     KoMainWindow::updateCaption();
00380     // Let's take this opportunity for setting a correct name for the icon
00381     // in koolbar
00382     QValueList<Page>::Iterator it = m_lstPages.begin();
00383     for( ; it != m_lstPages.end() ; ++it )
00384     {
00385       if ( (*it).m_pDoc == rootDocument() )
00386       {
00387         //kdDebug() << "updateCaption called for " << rootDocument() << endl;
00388         // Get caption from document info (title(), in about page)
00389         QString name;
00390         if ( rootDocument()->documentInfo() )
00391         {
00392             name = rootDocument()->documentInfo()->title();
00393         }
00394         if ( name.isEmpty() )
00395             // Fall back to document URL
00396             name = rootDocument()->url().fileName();
00397 
00398         if ( !name.isEmpty() ) // else keep Untitled
00399         {
00400           if ( name.length() > 20 )
00401           {
00402             name.truncate( 17 );
00403             name += "...";
00404           }
00405           m_pFrame->changeTab( m_pFrame->currentPage(), name );
00406           m_pSidebar->renameItem(m_grpDocuments, (*m_activePage).m_id, name); //remove the document from the sidebar
00407         }
00408 
00409         return;
00410       }
00411     }
00412 }
00413 
00414 
00415 void KoShellWindow::slotSidebar_Part(int _item)
00416 {
00417   //kdDebug() << "Component part choosed:" << _item << endl;
00418   kapp->setOverrideCursor( QCursor(Qt::WaitCursor) );
00419   m_documentEntry = m_mapComponents[ _item ];
00420   kdDebug() << m_documentEntry.service() << endl;
00421   kdDebug() << m_documentEntry.name() << endl;
00422   KoDocument *doc = m_documentEntry.createDoc();
00423   kapp->restoreOverrideCursor();
00424   if (doc)
00425   {
00426     if ( doc->showEmbedInitDialog( this ) )
00427     {
00428       partManager()->addPart( doc, false );
00429       setRootDocument( doc );
00430       m_tabCloseButton->show();
00431     }
00432     else
00433       delete doc;
00434   }
00435 }
00436 
00437 void KoShellWindow::slotSidebar_Document(int _item)
00438 {
00439     // Switch to an existing document
00440   if ( m_activePage != m_lstPages.end() &&
00441        (*m_activePage).m_id == _item )
00442     return;
00443     
00444   QValueList<Page>::Iterator it = m_lstPages.begin();
00445   while( it != m_lstPages.end() )
00446   {
00447     if ( (*it).m_id == _item )
00448     {
00449       switchToPage( it );
00450       return;
00451     }
00452     ++it;
00453   }
00454 }
00455 
00456 void KoShellWindow::slotShowSidebar()
00457 {
00458   if( m_pSidebar->isShown() )
00459   {
00460     m_pSidebar->hide();
00461     m_pComponentsLabel->hide();
00462   }
00463   else
00464   {
00465     m_pSidebar->show();
00466     m_pComponentsLabel->show();
00467   }
00468 }
00469 
00470 void KoShellWindow::slotUpdatePart( QWidget* widget )
00471 {
00472   KoView* v = dynamic_cast<KoView*>(widget);
00473   if ( v != 0 ) 
00474   {
00475     QValueList<Page>::Iterator it = m_lstPages.begin();
00476     for( ; it != m_lstPages.end(); ++it )
00477     {
00478       if( (*it).m_pView == v )
00479         switchToPage(it);
00480     }
00481   }
00482 }
00483 
00484 void KoShellWindow::switchToPage( QValueList<Page>::Iterator it )
00485 {
00486   // Select new active page (view)
00487   m_activePage = it;
00488   KoView *v = (*m_activePage).m_pView;
00489 
00490   kdDebug() << " setting active part to " << (*m_activePage).m_pDoc << endl;
00491   // Make it active (GUI etc.)
00492   partManager()->setActivePart( (*m_activePage).m_pDoc, v );
00493   // Change current document
00494   QPtrList<KoView> views;
00495   views.append(v);
00496   setRootDocumentDirect( (*m_activePage).m_pDoc, views );
00497   // Select the item in the sidebar
00498   m_pSidebar->group(m_grpDocuments)->setSelected((*m_activePage).m_id,true);
00499   // Raise the new page
00500   m_pFrame->showPage( v );
00501   // Fix caption and set focus to the new view
00502   updateCaption();
00503   v->setFocus();
00504 
00505   partSpecificHelpAction->setEnabled(true);
00506   partSpecificHelpAction->setText(i18n("%1 Handbook").arg((*m_activePage).m_pDoc->instance()->aboutData()->programName()));
00507 }
00508 
00509 void KoShellWindow::slotFileNew()
00510 {
00511     m_documentEntry = KoPartSelectDia::selectPart( this );
00512     if ( m_documentEntry.isEmpty() )
00513       return;
00514     KoDocument* newdoc = m_documentEntry.createDoc();
00515     if ( !newdoc )
00516         return;
00517     if ( !newdoc->showEmbedInitDialog( this ) )
00518     {
00519       delete newdoc;
00520       return;
00521     }
00522 
00523     partManager()->addPart( newdoc, false );
00524     setRootDocument( newdoc );
00525     m_tabCloseButton->show();
00526 }
00527 
00528 void KoShellWindow::slotFileOpen()
00529 {
00530     KFileDialog *dialog=new KFileDialog(QString::null, QString::null, 0L, "file dialog", true);
00531     if (!isImporting())
00532         dialog->setCaption( i18n("Open Document") );
00533     else
00534         dialog->setCaption( i18n("Import Document") );
00535     dialog->setMimeFilter( KoFilterManager::mimeFilter() );
00536 
00537     KURL url;
00538     if(dialog->exec()==QDialog::Accepted) {
00539         url=dialog->selectedURL();
00540         recentAction()->addURL( url );
00541         if ( url.isLocalFile() )
00542             KRecentDocument::add(url.path(-1));
00543         else
00544             KRecentDocument::add(url.url(-1), true);
00545     }
00546     else
00547         return;
00548 
00549     delete dialog;
00550     if ( url.isEmpty() )
00551         return;
00552 
00553     (void) openDocumentInternal( url );
00554     m_tabCloseButton->show();
00555 }
00556 
00557 void KoShellWindow::slotFileClose()
00558 {
00559   // reimplemented to avoid closing the window when we have docs opened
00560 
00561   // No docs at all ?
00562   if ( m_lstPages.count() == 0 )
00563     close(); // close window
00564   else
00565     closeDocument(); // close only doc
00566 
00567   if ( m_pFrame->count() == 0 )
00568     m_tabCloseButton->hide();
00569 }
00570 
00571 void KoShellWindow::closeDocument()
00572 {
00573   // Set the root document to the current one - so that queryClose acts on it
00574   assert( m_activePage != m_lstPages.end() );
00575   assert( rootDocument() == (*m_activePage).m_pDoc );
00576 
00577   // First do the standard queryClose
00578   kdDebug() << "KoShellWindow::closeDocument calling standard queryClose" << endl;
00579   if ( KoMainWindow::queryClose() )
00580   {
00581     kdDebug() << "Ok for closing document" << endl;
00582     m_pSidebar->removeItem(m_grpDocuments, (*m_activePage).m_id ); //remove the document from the sidebar
00583     (*m_activePage).m_pDoc->removeShell(this);
00584     Page oldPage = (*m_activePage); // make a copy of the struct
00585     m_lstPages.remove( m_activePage );
00586     m_activePage = m_lstPages.end(); // no active page right now
00587     m_pSidebar->group(m_grpDocuments)->setSelected((*m_activePage).m_id, true); //select the new document in the sidebar
00588 
00589     kdDebug() << "m_lstPages has " << m_lstPages.count() << " documents" << endl;
00590     if ( m_lstPages.count() > 0 )
00591     {
00592       kdDebug() << "Activate the document behind" << endl;
00593       switchToPage( m_lstPages.fromLast() );
00594     }
00595     else
00596     {
00597       kdDebug() << "Revert to initial state (no docs)" << endl;
00598       setRootDocument( 0L );
00599       partManager()->setActivePart( 0L, 0L );
00600       mnuSaveAll->setEnabled(false);
00601       partSpecificHelpAction->setEnabled(false);
00602       partSpecificHelpAction->setText(i18n("Part Handbook"));
00603     }
00604 
00605     // Now delete the old view and page
00606     // Don't do it before, because setActivePart will call slotActivePartChanged,
00607     // which needs the old view (to unplug it and its plugins)
00608     delete oldPage.m_pView;
00609     if ( oldPage.m_pDoc->viewCount() <= 1 )
00610       delete oldPage.m_pDoc;
00611 
00612   }
00613   kdDebug() << "m_lstPages has " << m_lstPages.count() << " documents" << endl;
00614 }
00615 
00616 bool KoShellWindow::queryClose()
00617 {
00618   // Save current doc and views
00619   QPtrList<KoView> currentViews;
00620   KoDocument * currentDoc = 0L;
00621   bool ok = true;
00622   if (m_activePage != m_lstPages.end())
00623   {
00624       currentDoc = (*m_activePage).m_pDoc;
00625       currentViews.append((*m_activePage).m_pView);
00626 
00627       // This one is called by slotFileQuit and by the X button.
00628       // We have to check for unsaved docs...
00629       QValueList<Page>::Iterator it = m_lstPages.begin();
00630       for( ; it != m_lstPages.end(); ++it )
00631       {
00632           // This is quite a HACK
00633           // We should ask ourselves, to get a better dialog box
00634           setRootDocumentDirect( (*it).m_pDoc, QPtrList<KoView>() );
00635           // Test if we can close this doc
00636           if ( !KoMainWindow::queryClose() )
00637           {
00638               ok = false; // No
00639               break; // abort
00640           }
00641       }
00642 
00643   // Restore current doc and views
00644   setRootDocumentDirect( currentDoc, currentViews );
00645   }
00646   return ok;
00647 }
00648 
00649 /*
00650 // Should this be an additional action in the File menu ?
00651 bool KoShellWindow::saveAllPages()
00652 {
00653   // TODO
00654   return false;
00655 }
00656 */
00657 
00658 void KoShellWindow::saveSettings()
00659 {
00660   KoShellSettings::setSidebarWidth( m_pLayout->sizes().first() );
00661   KoShellSettings::writeConfig();
00662 }
00663 
00664 QString KoShellWindow::configFile() const
00665 {
00666   //return readConfigFile( locate( "data", "koshell/koshell_shell.rc" ) );
00667   return QString::null; // use UI standards only for now
00668 }
00669 
00670 void KoShellWindow::tab_contextMenu(QWidget * w,const QPoint &p)
00671 {
00672   KPopupMenu menu;
00673   KIconLoader il;
00674   int const mnuSave = menu.insertItem( il.loadIconSet( "filesave", KIcon::Small ), i18n("Save") );
00675   int const mnuClose = menu.insertItem( il.loadIcon( "fileclose", KIcon::Small ), i18n("Close") );
00676   
00677   int tabnr = m_pFrame->indexOf( w );
00678   Page page = m_lstPages[tabnr];
00679   // disable save if there's nothing to save
00680   if ( !page.m_pDoc->isModified() )
00681     menu.setItemEnabled( mnuSave, false );
00682   
00683   // show menu
00684   int const choice = menu.exec(p);
00685 
00686   if( choice == mnuClose )
00687   {
00688     const int index = m_pFrame->currentPageIndex();
00689     m_pFrame->setCurrentPage( tabnr );
00690     slotFileClose();
00691     if ( index > m_pFrame->currentPageIndex() )
00692       m_pFrame->setCurrentPage(index-1);
00693     else
00694       m_pFrame->setCurrentPage(index);
00695   }
00696   else if ( choice == mnuSave )
00697   {
00698       page.m_pView->shell()->slotFileSave();
00699   }
00700 }
00701 
00702 void KoShellWindow::slotConfigureKeys()
00703 {
00704   KoView *view = rootView();
00705   KKeyDialog dlg( this );
00706   dlg.insert( actionCollection() );
00707   if ( view )
00708      dlg.insert( view->actionCollection() );
00709   if ( rootDocument() )
00710     dlg.insert( rootDocument()->actionCollection() );
00711   dlg.configure();
00712 }
00713 
00714 void KoShellWindow::createShellGUI( bool  )
00715 {
00716     guiFactory()->addClient( m_client );
00717 }
00718 
00719 void KoShellWindow::showPartSpecificHelp()
00720 {
00721   if((m_activePage == m_lstPages.end()) || ((*m_activePage).m_pDoc == 0))
00722     return;
00723 
00724   kapp->invokeHelp("", (*m_activePage).m_pDoc->instance()->aboutData()->appName(), "");
00725 }
00726 
00727 
00729 KoShellGUIClient::KoShellGUIClient( KoShellWindow *window ) : KXMLGUIClient()
00730 {
00731   setXMLFile( "koshellui.rc", true, true );
00732   window->mnuSaveAll = new KAction( i18n("Save All"), 0, window, SLOT( saveAll() ), actionCollection(), "save_all" );
00733   window->mnuSaveAll->setEnabled(false);
00734   window->partSpecificHelpAction = new KAction(i18n("Part Handbook"), "contents", 0, window, SLOT(showPartSpecificHelp()),
00735                                                actionCollection(), "partSpecificHelp");
00736   window->partSpecificHelpAction->setEnabled(false);
00737 }
00738 
00739 #include "koshell_shell.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys