koshell

koshell_shell.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
4 Copyright (C) 2000-2005 David Faure <faure@kde.org>
5 Copyright (C) 2005, 2006 Sven Lüppken <sven@kde.org>
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21*/
22
23#include <tqcursor.h>
24#include <tqsplitter.h>
25#include <tqiconview.h>
26#include <tqlabel.h>
27#include <tqvbox.h>
28
29#include <assert.h>
30
31#include "koshell_shell.h"
32#include "koshellsettings.h"
33
34#include <tdeapplication.h>
35#include <tdetempfile.h>
36#include <tdefiledialog.h>
37#include <tdelocale.h>
38#include <kdebug.h>
39#include <kiconloader.h>
40#include <kkeydialog.h>
41#include <kstandarddirs.h>
42#include <klibloader.h>
43#include <tdepopupmenu.h>
44#include <kservice.h>
45#include <tdemessagebox.h>
46#include <tderecentdocument.h>
47#include <tdeparts/partmanager.h>
48#include <tdeaction.h>
49#include <tdeversion.h>
50#include <tdeaboutdata.h>
51
52#include <KoQueryTrader.h>
53#include <KoDocumentInfo.h>
54#include <KoDocument.h>
55#include <KoView.h>
56#include <KoPartSelectDia.h>
57#include <KoFilterManager.h>
58#include <kiconloader.h>
59
60KoShellWindow::KoShellWindow()
61 : KoMainWindow( TDEGlobal::instance() )
62{
63 m_activePage = m_lstPages.end();
64
65 m_pLayout = new TQSplitter( centralWidget() );
66
67 // Setup the sidebar
68 m_pSidebar = new IconSidePane( m_pLayout );
69 m_pSidebar->setSizePolicy( TQSizePolicy( TQSizePolicy::Maximum,
70 TQSizePolicy::Preferred ) );
71 m_pSidebar->setActionCollection( actionCollection() );
72 m_grpFile = m_pSidebar->insertGroup(i18n("Components"), false, this, TQ_SLOT( slotSidebar_Part(int )));
73 m_grpDocuments = m_pSidebar->insertGroup(i18n("Documents"), true, this, TQ_SLOT(slotSidebar_Document(int)));
74 m_pLayout->setResizeMode(m_pSidebar,TQSplitter::FollowSizeHint);
75
76 // Setup the tabbar
77 m_pFrame = new KTabWidget( m_pLayout );
78 m_pFrame->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum,
79 TQSizePolicy::Preferred ) );
80 m_pFrame->setTabPosition( KTabWidget::Bottom );
81
82 m_tabCloseButton = new TQToolButton( m_pFrame );
83 connect( m_tabCloseButton, TQ_SIGNAL( clicked() ),
84 this, TQ_SLOT( slotFileClose() ) );
85 m_tabCloseButton->setIconSet( SmallIconSet( "tab_remove" ) );
86 m_tabCloseButton->adjustSize();
87 TQToolTip::add(m_tabCloseButton, i18n("Close"));
88 m_pFrame->setCornerWidget( m_tabCloseButton, BottomRight );
89 m_tabCloseButton->hide();
90
91 TQValueList<KoDocumentEntry> lstComponents = KoDocumentEntry::query(false,TQString());
92 TQValueList<KoDocumentEntry>::Iterator it = lstComponents.begin();
93 int id = 0;
94 // Get all available components
95 for( ; it != lstComponents.end(); ++it )
96 {
97 KService* service = (*it).service();
98 if ( !service->genericName().isEmpty() )
99 {
100 id = m_pSidebar->insertItem(m_grpFile, service->icon(), service->genericName());
101 }
102 else
103 {
104 continue;
105 }
106
107 m_mapComponents[ id++ ] = *it;
108 }
109
110 TQValueList<int> list;
111 list.append( KoShellSettings::sidebarWidth() );
112 list.append( this->width() - KoShellSettings::sidebarWidth() );
113 m_pLayout->setSizes( list );
114
115 connect( this, TQ_SIGNAL( documentSaved() ),
116 this, TQ_SLOT( slotNewDocumentName() ) );
117
118 connect( m_pFrame, TQ_SIGNAL( currentChanged( TQWidget* ) ),
119 this, TQ_SLOT( slotUpdatePart( TQWidget* ) ) );
120 connect( m_pFrame, TQ_SIGNAL( contextMenu(TQWidget * ,const TQPoint &)), this, TQ_SLOT( tab_contextMenu(TQWidget * ,const TQPoint &)) );
121
122 m_client = new KoShellGUIClient( this );
123 createShellGUI();
124}
125
126KoShellWindow::~KoShellWindow()
127{
128 //kdDebug() << "KoShellWindow::~KoShellWindow()" << endl;
129
130 // Set the active part to 0 (as we do in ~KoMainWindow, but this is too
131 // late for KoShell, it gets activePartChanged signals delivered to a dead
132 // KoShellWindow object).
133 partManager()->setActivePart(0);
134
135 // Destroy all documents - queryClose has made sure we saved them first
136 TQValueList<Page>::ConstIterator it = m_lstPages.begin();
137 for (; it != m_lstPages.end(); ++it )
138 {
139 (*it).m_pDoc->removeShell( this );
140 delete (*it).m_pView;
141 if ( (*it).m_pDoc->viewCount() == 0 )
142 delete (*it).m_pDoc;
143 }
144 m_lstPages.clear();
145
146 setRootDocumentDirect( 0L, TQPtrList<KoView>() ); // prevent our parent destructor from doing stupid things
147 saveSettings(); // Now save our settings before exiting
148}
149
150bool KoShellWindow::openDocumentInternal( const KURL &url, KoDocument* )
151{
152 // Here we have to distinguish two cases: The passed URL has a native
153 // KOffice mimetype. Then we query the trader and create the document.
154 // The file is loaded and everyone's happy.
155 // The second case is a non-native file. Here we have to create a
156 // filter manager, ask it to convert the file to the "closest" available
157 // KOffice part and open the temporary file.
158
159 /*if (!TDEIO::NetAccess::exists(url,true,0) )
160 {
161 KMessageBox::error(0L, i18n("The file %1 doesn't exist.").arg(url.url()) );
162 recentAction()->removeURL(url); //remove the file from the recent-opened-file-list
163 saveRecentFiles();
164 return false;
165 }*/
166
167 KMimeType::Ptr mimeType = KMimeType::findByURL( url );
168 m_documentEntry = KoDocumentEntry::queryByMimeType( mimeType->name().latin1() );
169
170 KTempFile* tmpFile = 0;
171 KURL tmpUrl( url ); // we might have to load a converted temp. file
172
173 if ( m_documentEntry.isEmpty() ) { // non-native
174 tmpFile = new KTempFile;
175
176 KoFilterManager *manager = new KoFilterManager( url.path() );
177 TQCString mimetype; // an empty mimetype means, that the "nearest"
178 KoFilter::ConversionStatus status = manager->exp0rt( tmpFile->name(), mimetype ); // KOffice part will be chosen
179 delete manager;
180
181 if ( status != KoFilter::OK || mimetype.isEmpty() ) {
182 tmpFile->unlink();
183 delete tmpFile;
184 return false;
185 }
186
187 // If the conversion was successful we get the mimetype of the
188 // chosen KOffice part back.
189 m_documentEntry = KoDocumentEntry::queryByMimeType( mimetype );
190 if ( m_documentEntry.isEmpty() ) {
191 tmpFile->unlink();
192 delete tmpFile;
193 return false;
194 }
195
196 // Open the temporary file
197 tmpUrl.setPath( tmpFile->name() );
198 }
199
200 recentAction()->addURL( url );
201
202 KoDocument* newdoc = m_documentEntry.createDoc();
203 if ( !newdoc ) {
204 if ( tmpFile ) {
205 tmpFile->unlink();
206 delete tmpFile;
207 }
208 return false;
209 }
210
211 connect(newdoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
212 connect(newdoc, TQ_SIGNAL(completed()), this, TQ_SLOT(slotKSLoadCompleted()));
213 connect(newdoc, TQ_SIGNAL(canceled( const TQString & )), this, TQ_SLOT(slotKSLoadCanceled( const TQString & )));
214 newdoc->addShell( this ); // used by openURL
215 bool openRet = (!isImporting ()) ? newdoc->openURL(tmpUrl) : newdoc->import(tmpUrl);
216 if ( !openRet )
217 {
218 newdoc->removeShell(this);
219 delete newdoc;
220 if ( tmpFile ) {
221 tmpFile->unlink();
222 delete tmpFile;
223 }
224 return false;
225 }
226
227 if ( tmpFile ) {
228 //if the loaded file has been a temporary file
229 //we need to correct a few document settings
230 //see description of bug #77574 for additional information
231
232 //correct (output) mime type: we need to set it to the non-native format
233 //to make sure the user knows about saving to a non-native mime type
234 //setConfirmNonNativeSave is set to true below
235 newdoc->setMimeType( mimeType->name().latin1() );
236 newdoc->setOutputMimeType( mimeType->name().latin1() );
237
238 //the next time the user saves the document he should be warned
239 //because of mime type settings done above;
240 newdoc->setConfirmNonNativeSave(true,true); //exporting,warn_on
241 newdoc->setConfirmNonNativeSave(false,true); //save/save as,warn_on
242
243 //correct document file (should point to URL)
244 newdoc->setFile( url.path() );
245
246 //correct document URL
247 newdoc->setURL( url );
248
249 //update caption to represent the correct URL in the window titlebar
250 updateCaption();
251
252 tmpFile->unlink();
253 delete tmpFile;
254 }
255 return true;
256}
257
258void KoShellWindow::slotSidebarItemClicked( TQIconViewItem *item )
259{
260 //kdDebug() << "slotSidebarItemClicked called!" << endl;
261 if( item != 0 )
262 {
263 int index = item->index();
264
265 // Create new document from a KoDocumentEntry
266 m_documentEntry = m_mapComponents[ index ];
267 KoDocument *doc = m_documentEntry.createDoc();
268 if (doc)
269 {
270 // koshell isn't starting, but this is like starting a new app:
271 // offer both "open existing file" and "open new file".
272 if ( doc->showEmbedInitDialog( this ) )
273 {
274 partManager()->addPart( doc, false );
275 setRootDocument( doc );
276 }
277 else
278 delete doc;
279 }
280 }
281}
282
283// Separate from openDocument to handle async loading (remote URLs)
284void KoShellWindow::slotKSLoadCompleted()
285{
286 KoDocument* newdoc = (KoDocument *)(sender());
287
288 // KoDocument::import() calls resetURL() too late...
289 // ...setRootDocument will show the URL...
290 // So let's stop this from happening and the user will never know :)
291 if (isImporting()) newdoc->resetURL ();
292
293 partManager()->addPart( newdoc, false );
294 setRootDocument( newdoc );
295 disconnect(newdoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
296 disconnect(newdoc, TQ_SIGNAL(completed()), this, TQ_SLOT(slotKSLoadCompleted()));
297 disconnect(newdoc, TQ_SIGNAL(canceled( const TQString & )), this, TQ_SLOT(slotKSLoadCanceled( const TQString & )));
298}
299
300void KoShellWindow::slotKSLoadCanceled( const TQString & errMsg )
301{
302 KMessageBox::error( this, errMsg );
303 // ... can't delete the document, it's the one who emitted the signal...
304 // ###### FIXME: This can be done in 3.0 with deleteLater, I assume (Werner)
305
306 KoDocument* newdoc = (KoDocument *)(sender());
307 disconnect(newdoc, TQ_SIGNAL(sigProgress(int)), this, TQ_SLOT(slotProgress(int)));
308 disconnect(newdoc, TQ_SIGNAL(completed()), this, TQ_SLOT(slotKSLoadCompleted()));
309 disconnect(newdoc, TQ_SIGNAL(canceled( const TQString & )), this, TQ_SLOT(slotKSLoadCanceled( const TQString & )));
310}
311
312void KoShellWindow::saveAll()
313{
314 KoView *currentView = (*m_activePage).m_pView;
315 for (TQValueList<Page>::iterator it=m_lstPages.begin(); it != m_lstPages.end(); ++it)
316 {
317 if ( (*it).m_pDoc->isModified() )
318 {
319 m_pFrame->showPage( (*it).m_pView );
320 (*it).m_pView->shell()->slotFileSave();
321 if ( (*it).m_pDoc->isModified() )
322 break;
323 }
324 }
325 m_pFrame->showPage( currentView );
326}
327
328void KoShellWindow::setRootDocument( KoDocument * doc )
329{
330 kdDebug() << "KoShellWindow::setRootDocument this=" << this << " doc=" << doc << endl;
331 // We do things quite differently from KoMainWindow::setRootDocument
332 // This one is called with doc != 0 when a new doc is created
333 // and with 0L after they have all been removed.
334 // We use setRootDocumentDirect to switch the 'root doc' known by KoMainWindow.
335
336 if ( doc )
337 {
338 if ( !doc->shells().contains( this ) )
339 doc->addShell( this );
340
341 KoView *v = doc->createView(this);
342 TQPtrList<KoView> views;
343 views.append(v);
344 setRootDocumentDirect( doc, views );
345
346 v->setGeometry( 0, 0, m_pFrame->width(), m_pFrame->height() );
347 v->setPartManager( partManager() );
348 m_pFrame->addTab( v, TDEGlobal::iconLoader()->loadIcon( m_documentEntry.service()->icon(), TDEIcon::Small ), i18n("Untitled") );
349
350 // Create a new page for this doc
351 Page page;
352 page.m_pDoc = doc;
353 page.m_pView = v;
354 // insert the new document in the sidebar
355 page.m_id = m_pSidebar->insertItem( m_grpDocuments,
356 m_documentEntry.service()->icon(),
357 i18n("Untitled"));
358 m_lstPages.append( page );
359 v->show();
360
361 switchToPage( m_lstPages.fromLast() );
362 mnuSaveAll->setEnabled(true);
363 } else
364 {
365 setRootDocumentDirect( 0L, TQPtrList<KoView>() );
366 m_activePage = m_lstPages.end();
367 KoMainWindow::updateCaption();
368 }
369}
370
371void KoShellWindow::slotNewDocumentName()
372{
373 updateCaption();
374}
375
376void KoShellWindow::updateCaption()
377{
378 //kdDebug() << "KoShellWindow::updateCaption() rootDoc=" << rootDocument() << endl;
379 KoMainWindow::updateCaption();
380 // Let's take this opportunity for setting a correct name for the icon
381 // in koolbar
382 TQValueList<Page>::Iterator it = m_lstPages.begin();
383 for( ; it != m_lstPages.end() ; ++it )
384 {
385 if ( (*it).m_pDoc == rootDocument() )
386 {
387 //kdDebug() << "updateCaption called for " << rootDocument() << endl;
388 // Get caption from document info (title(), in about page)
389 TQString name;
390 if ( rootDocument()->documentInfo() )
391 {
392 name = rootDocument()->documentInfo()->title();
393 }
394 if ( name.isEmpty() )
395 // Fall back to document URL
396 name = rootDocument()->url().fileName();
397
398 if ( !name.isEmpty() ) // else keep Untitled
399 {
400 if ( name.length() > 20 )
401 {
402 name.truncate( 17 );
403 name += "...";
404 }
405 m_pFrame->changeTab( m_pFrame->currentPage(), name );
406 m_pSidebar->renameItem(m_grpDocuments, (*m_activePage).m_id, name); //remove the document from the sidebar
407 }
408
409 return;
410 }
411 }
412}
413
414
415void KoShellWindow::slotSidebar_Part(int _item)
416{
417 //kdDebug() << "Component part choosed:" << _item << endl;
418 kapp->setOverrideCursor( TQCursor(TQt::WaitCursor) );
419 m_documentEntry = m_mapComponents[ _item ];
420 kdDebug() << m_documentEntry.service() << endl;
421 kdDebug() << m_documentEntry.name() << endl;
422 KoDocument *doc = m_documentEntry.createDoc();
423 kapp->restoreOverrideCursor();
424 if (doc)
425 {
426 if ( doc->showEmbedInitDialog( this ) )
427 {
428 partManager()->addPart( doc, false );
429 setRootDocument( doc );
430 m_tabCloseButton->show();
431 }
432 else
433 delete doc;
434 }
435}
436
437void KoShellWindow::slotSidebar_Document(int _item)
438{
439 // Switch to an existing document
440 if ( m_activePage != m_lstPages.end() &&
441 (*m_activePage).m_id == _item )
442 return;
443
444 TQValueList<Page>::Iterator it = m_lstPages.begin();
445 while( it != m_lstPages.end() )
446 {
447 if ( (*it).m_id == _item )
448 {
449 switchToPage( it );
450 return;
451 }
452 ++it;
453 }
454}
455
456void KoShellWindow::slotShowSidebar()
457{
458 if( m_pSidebar->isShown() )
459 {
460 m_pSidebar->hide();
461 m_pComponentsLabel->hide();
462 }
463 else
464 {
465 m_pSidebar->show();
466 m_pComponentsLabel->show();
467 }
468}
469
470void KoShellWindow::slotUpdatePart( TQWidget* widget )
471{
472 KoView* v = dynamic_cast<KoView*>(widget);
473 if ( v != 0 )
474 {
475 TQValueList<Page>::Iterator it = m_lstPages.begin();
476 for( ; it != m_lstPages.end(); ++it )
477 {
478 if( (*it).m_pView == v )
479 switchToPage(it);
480 }
481 }
482}
483
484void KoShellWindow::switchToPage( TQValueList<Page>::Iterator it )
485{
486 // Select new active page (view)
487 m_activePage = it;
488 KoView *v = (*m_activePage).m_pView;
489
490 kdDebug() << " setting active part to " << (*m_activePage).m_pDoc << endl;
491 // Make it active (GUI etc.)
492 partManager()->setActivePart( (*m_activePage).m_pDoc, v );
493 // Change current document
494 TQPtrList<KoView> views;
495 views.append(v);
496 setRootDocumentDirect( (*m_activePage).m_pDoc, views );
497 // Select the item in the sidebar
498 m_pSidebar->group(m_grpDocuments)->setSelected((*m_activePage).m_id,true);
499 // Raise the new page
500 m_pFrame->showPage( v );
501 // Fix caption and set focus to the new view
502 updateCaption();
503 v->setFocus();
504
505 partSpecificHelpAction->setEnabled(true);
506 partSpecificHelpAction->setText(i18n("%1 Handbook").arg((*m_activePage).m_pDoc->instance()->aboutData()->programName()));
507}
508
509void KoShellWindow::slotFileNew()
510{
511 m_documentEntry = KoPartSelectDia::selectPart( this );
512 if ( m_documentEntry.isEmpty() )
513 return;
514 KoDocument* newdoc = m_documentEntry.createDoc();
515 if ( !newdoc )
516 return;
517 if ( !newdoc->showEmbedInitDialog( this ) )
518 {
519 delete newdoc;
520 return;
521 }
522
523 partManager()->addPart( newdoc, false );
524 setRootDocument( newdoc );
525 m_tabCloseButton->show();
526}
527
528void KoShellWindow::slotFileOpen()
529{
530 KFileDialog *dialog=new KFileDialog(TQString(), TQString(), 0L, "file dialog", true);
531 if (!isImporting())
532 dialog->setCaption( i18n("Open Document") );
533 else
534 dialog->setCaption( i18n("Import Document") );
535 dialog->setMimeFilter( KoFilterManager::mimeFilter() );
536
537 KURL url;
538 if(dialog->exec()==TQDialog::Accepted) {
539 url=dialog->selectedURL();
540 recentAction()->addURL( url );
541 if ( url.isLocalFile() )
542 TDERecentDocument::add(url.path(-1));
543 else
544 TDERecentDocument::add(url.url(-1), true);
545 }
546 else
547 return;
548
549 delete dialog;
550 if ( url.isEmpty() )
551 return;
552
553 (void) openDocumentInternal( url );
554 m_tabCloseButton->show();
555}
556
557void KoShellWindow::slotFileClose()
558{
559 // reimplemented to avoid closing the window when we have docs opened
560
561 // No docs at all ?
562 if ( m_lstPages.count() == 0 )
563 close(); // close window
564 else
565 closeDocument(); // close only doc
566
567 if ( m_pFrame->count() == 0 )
568 m_tabCloseButton->hide();
569}
570
571void KoShellWindow::closeDocument()
572{
573 // Set the root document to the current one - so that queryClose acts on it
574 assert( m_activePage != m_lstPages.end() );
575 assert( rootDocument() == (*m_activePage).m_pDoc );
576
577 // First do the standard queryClose
578 kdDebug() << "KoShellWindow::closeDocument calling standard queryClose" << endl;
579 if ( KoMainWindow::queryClose() )
580 {
581 kdDebug() << "Ok for closing document" << endl;
582 m_pSidebar->removeItem(m_grpDocuments, (*m_activePage).m_id ); //remove the document from the sidebar
583 (*m_activePage).m_pDoc->removeShell(this);
584 Page oldPage = (*m_activePage); // make a copy of the struct
585 m_lstPages.remove( m_activePage );
586 m_activePage = m_lstPages.end(); // no active page right now
587 m_pSidebar->group(m_grpDocuments)->setSelected((*m_activePage).m_id, true); //select the new document in the sidebar
588
589 kdDebug() << "m_lstPages has " << m_lstPages.count() << " documents" << endl;
590 if ( m_lstPages.count() > 0 )
591 {
592 kdDebug() << "Activate the document behind" << endl;
593 switchToPage( m_lstPages.fromLast() );
594 }
595 else
596 {
597 kdDebug() << "Revert to initial state (no docs)" << endl;
598 setRootDocument( 0L );
599 partManager()->setActivePart( 0L, 0L );
600 mnuSaveAll->setEnabled(false);
601 partSpecificHelpAction->setEnabled(false);
602 partSpecificHelpAction->setText(i18n("Part Handbook"));
603 }
604
605 // Now delete the old view and page
606 // Don't do it before, because setActivePart will call slotActivePartChanged,
607 // which needs the old view (to unplug it and its plugins)
608 delete oldPage.m_pView;
609 if ( oldPage.m_pDoc->viewCount() <= 1 )
610 delete oldPage.m_pDoc;
611
612 }
613 kdDebug() << "m_lstPages has " << m_lstPages.count() << " documents" << endl;
614}
615
616bool KoShellWindow::queryClose()
617{
618 // Save current doc and views
619 TQPtrList<KoView> currentViews;
620 KoDocument * currentDoc = 0L;
621 bool ok = true;
622 if (m_activePage != m_lstPages.end())
623 {
624 currentDoc = (*m_activePage).m_pDoc;
625 currentViews.append((*m_activePage).m_pView);
626
627 // This one is called by slotFileQuit and by the X button.
628 // We have to check for unsaved docs...
629 TQValueList<Page>::Iterator it = m_lstPages.begin();
630 for( ; it != m_lstPages.end(); ++it )
631 {
632 // This is quite a HACK
633 // We should ask ourselves, to get a better dialog box
634 setRootDocumentDirect( (*it).m_pDoc, TQPtrList<KoView>() );
635 // Test if we can close this doc
636 if ( !KoMainWindow::queryClose() )
637 {
638 ok = false; // No
639 break; // abort
640 }
641 }
642
643 // Restore current doc and views
644 setRootDocumentDirect( currentDoc, currentViews );
645 }
646 return ok;
647}
648
649/*
650// Should this be an additional action in the File menu ?
651bool KoShellWindow::saveAllPages()
652{
653 // TODO
654 return false;
655}
656*/
657
658void KoShellWindow::saveSettings()
659{
660 KoShellSettings::setSidebarWidth( m_pLayout->sizes().first() );
661 KoShellSettings::writeConfig();
662}
663
664TQString KoShellWindow::configFile() const
665{
666 //return readConfigFile( locate( "data", "koshell/koshell_shell.rc" ) );
667 return TQString(); // use UI standards only for now
668}
669
670void KoShellWindow::tab_contextMenu(TQWidget * w,const TQPoint &p)
671{
672 TDEPopupMenu menu;
673 TDEIconLoader il;
674 int const mnuSave = menu.insertItem( il.loadIconSet( "document-save", TDEIcon::Small ), i18n("Save") );
675 int const mnuClose = menu.insertItem( il.loadIcon( "window-close", TDEIcon::Small ), i18n("Close") );
676
677 int tabnr = m_pFrame->indexOf( w );
678 Page page = m_lstPages[tabnr];
679 // disable save if there's nothing to save
680 if ( !page.m_pDoc->isModified() )
681 menu.setItemEnabled( mnuSave, false );
682
683 // show menu
684 int const choice = menu.exec(p);
685
686 if( choice == mnuClose )
687 {
688 const int index = m_pFrame->currentPageIndex();
689 m_pFrame->setCurrentPage( tabnr );
690 slotFileClose();
691 if ( index > m_pFrame->currentPageIndex() )
692 m_pFrame->setCurrentPage(index-1);
693 else
694 m_pFrame->setCurrentPage(index);
695 }
696 else if ( choice == mnuSave )
697 {
698 page.m_pView->shell()->slotFileSave();
699 }
700}
701
702void KoShellWindow::slotConfigureKeys()
703{
704 KoView *view = rootView();
705 KKeyDialog dlg( this );
706 dlg.insert( actionCollection() );
707 if ( view )
708 dlg.insert( view->actionCollection() );
709 if ( rootDocument() )
710 dlg.insert( rootDocument()->actionCollection() );
711 dlg.configure();
712}
713
714void KoShellWindow::createShellGUI( bool )
715{
716 guiFactory()->addClient( m_client );
717}
718
719void KoShellWindow::showPartSpecificHelp()
720{
721 if((m_activePage == m_lstPages.end()) || ((*m_activePage).m_pDoc == 0))
722 return;
723
724 kapp->invokeHelp("", (*m_activePage).m_pDoc->instance()->aboutData()->appName(), "");
725}
726
727
729KoShellGUIClient::KoShellGUIClient( KoShellWindow *window ) : KXMLGUIClient()
730{
731 setXMLFile( "koshellui.rc", true, true );
732 window->mnuSaveAll = new TDEAction( i18n("Save All"), 0, window, TQ_SLOT( saveAll() ), actionCollection(), "save_all" );
733 window->mnuSaveAll->setEnabled(false);
734 window->partSpecificHelpAction = new TDEAction(i18n("Part Handbook"), "contents", 0, window, TQ_SLOT(showPartSpecificHelp()),
735 actionCollection(), "partSpecificHelp");
736 window->partSpecificHelpAction->setEnabled(false);
737}
738
739#include "koshell_shell.moc"