• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kparts
 

kparts

  • kparts
part.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
3  (C) 1999 David Faure <faure@kde.org>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include <kparts/part.h>
22 #include <kparts/event.h>
23 #include <kparts/plugin.h>
24 #include <kparts/mainwindow.h>
25 #include <kparts/partmanager.h>
26 
27 #include <tqapplication.h>
28 #include <tqfile.h>
29 #include <tqpoint.h>
30 #include <tqpointarray.h>
31 #include <tqpainter.h>
32 #include <tqtextstream.h>
33 #include <tqfileinfo.h>
34 
35 #include <kinstance.h>
36 #include <klocale.h>
37 #include <ktempfile.h>
38 #include <kmessagebox.h>
39 #include <kio/job.h>
40 #include <kstandarddirs.h>
41 #include <kfiledialog.h>
42 #include <kdirnotify_stub.h>
43 
44 #include <stdio.h>
45 #include <unistd.h>
46 #include <assert.h>
47 #include <kdebug.h>
48 
49 template class TQPtrList<KXMLGUIClient>;
50 
51 using namespace KParts;
52 
53 namespace KParts
54 {
55 
56 class PartBasePrivate
57 {
58 public:
59  PartBasePrivate()
60  {
61  m_pluginLoadingMode = PartBase::LoadPlugins;
62  }
63  ~PartBasePrivate()
64  {
65  }
66  PartBase::PluginLoadingMode m_pluginLoadingMode;
67 };
68 
69 class PartPrivate
70 {
71 public:
72  PartPrivate()
73  {
74  m_bSelectable = true;
75  }
76  ~PartPrivate()
77  {
78  }
79 
80  bool m_bSelectable;
81 };
82 }
83 
84 PartBase::PartBase()
85 {
86  d = new PartBasePrivate;
87  m_obj = 0L;
88 }
89 
90 PartBase::~PartBase()
91 {
92  delete d;
93 }
94 
95 void PartBase::setPartObject( TQObject *obj )
96 {
97  m_obj = obj;
98 }
99 
100 TQObject *PartBase::partObject() const
101 {
102  return m_obj;
103 }
104 
105 void PartBase::setInstance( KInstance *inst )
106 {
107  setInstance( inst, true );
108 }
109 
110 void PartBase::setInstance( KInstance *inst, bool bLoadPlugins )
111 {
112  KXMLGUIClient::setInstance( inst );
113  KGlobal::locale()->insertCatalogue( inst->instanceName() );
114  // install 'instancename'data resource type
115  KGlobal::dirs()->addResourceType( inst->instanceName() + "data",
116  KStandardDirs::kde_default( "data" )
117  + TQString::fromLatin1( inst->instanceName() ) + '/' );
118  if ( bLoadPlugins )
119  loadPlugins( m_obj, this, instance() );
120 }
121 
122 void PartBase::loadPlugins( TQObject *parent, KXMLGUIClient *parentGUIClient, KInstance *instance )
123 {
124  if( d->m_pluginLoadingMode != DoNotLoadPlugins )
125  Plugin::loadPlugins( parent, parentGUIClient, instance, d->m_pluginLoadingMode == LoadPlugins );
126 }
127 
128 void PartBase::setPluginLoadingMode( PluginLoadingMode loadingMode )
129 {
130  d->m_pluginLoadingMode = loadingMode;
131 }
132 
133 Part::Part( TQObject *parent, const char* name )
134  : TQObject( parent, name )
135 {
136  d = new PartPrivate;
137  m_widget = 0L;
138  m_manager = 0L;
139  PartBase::setPartObject( this );
140 }
141 
142 Part::~Part()
143 {
144  kdDebug(1000) << "Part::~Part " << this << endl;
145 
146  if ( m_widget )
147  {
148  // We need to disconnect first, to avoid calling it !
149  disconnect( m_widget, TQT_SIGNAL( destroyed() ),
150  this, TQT_SLOT( slotWidgetDestroyed() ) );
151  }
152 
153  if ( m_manager )
154  m_manager->removePart(this);
155 
156  if ( m_widget )
157  {
158  kdDebug(1000) << "deleting widget " << m_widget << " " << m_widget->name() << endl;
159  delete (TQWidget*) m_widget;
160  }
161 
162  delete d;
163 }
164 
165 void Part::embed( TQWidget * parentWidget )
166 {
167  if ( widget() )
168  widget()->reparent( parentWidget, 0, TQPoint( 0, 0 ), true );
169 }
170 
171 TQWidget *Part::widget()
172 {
173  return m_widget;
174 }
175 
176 void Part::setManager( PartManager *manager )
177 {
178  m_manager = manager;
179 }
180 
181 PartManager *Part::manager() const
182 {
183  return m_manager;
184 }
185 
186 Part *Part::hitTest( TQWidget *widget, const TQPoint & )
187 {
188  if ( (TQWidget *)m_widget != widget )
189  return 0L;
190 
191  return this;
192 }
193 
194 void Part::setWidget( TQWidget *widget )
195 {
196  assert ( !m_widget ); // otherwise we get two connects
197  m_widget = widget;
198  connect( m_widget, TQT_SIGNAL( destroyed() ),
199  this, TQT_SLOT( slotWidgetDestroyed() ) );
200 
201  // Tell the actionCollection() which widget its
202  // action shortcuts should be connected to.
203  actionCollection()->setWidget( widget );
204 
205  // Since KParts objects are XML-based, shortcuts should
206  // be connected to the widget when the XML settings
207  // are processed, rather than on KAction construction.
208  actionCollection()->setAutoConnectShortcuts( false );
209 }
210 
211 void Part::setSelectable( bool selectable )
212 {
213  d->m_bSelectable = selectable;
214 }
215 
216 bool Part::isSelectable() const
217 {
218  return d->m_bSelectable;
219 }
220 
221 void Part::customEvent( TQCustomEvent *event )
222 {
223  if ( PartActivateEvent::test( event ) )
224  {
225  partActivateEvent( (PartActivateEvent *)event );
226  return;
227  }
228 
229  if ( PartSelectEvent::test( event ) )
230  {
231  partSelectEvent( (PartSelectEvent *)event );
232  return;
233  }
234 
235  if ( GUIActivateEvent::test( event ) )
236  {
237  guiActivateEvent( (GUIActivateEvent *)event );
238  return;
239  }
240 
241  TQObject::customEvent( event );
242 }
243 
244 void Part::partActivateEvent( PartActivateEvent * )
245 {
246 }
247 
248 void Part::partSelectEvent( PartSelectEvent * )
249 {
250 }
251 
252 void Part::guiActivateEvent( GUIActivateEvent * )
253 {
254 }
255 
256 TQWidget *Part::hostContainer( const TQString &containerName )
257 {
258  if ( !factory() )
259  return 0L;
260 
261  return factory()->container( containerName, this );
262 }
263 
264 void Part::slotWidgetDestroyed()
265 {
266  kdDebug(1000) << "KPart::slotWidgetDestroyed(), deleting part " << name() << endl;
267  m_widget = 0;
268  delete this;
269 }
270 
272 
273 namespace KParts
274 {
275 
276 class ReadOnlyPartPrivate
277 {
278 public:
279  ReadOnlyPartPrivate()
280  {
281  m_job = 0L;
282  m_uploadJob = 0L;
283  m_showProgressInfo = true;
284  m_saveOk = false;
285  m_waitForSave = false;
286  m_duringSaveAs = false;
287  }
288  ~ReadOnlyPartPrivate()
289  {
290  }
291 
292  KIO::FileCopyJob * m_job;
293  KIO::FileCopyJob * m_uploadJob;
294  KURL m_originalURL; // for saveAs
295  TQString m_originalFilePath; // for saveAs
296  bool m_showProgressInfo : 1;
297  bool m_saveOk : 1;
298  bool m_waitForSave : 1;
299  bool m_duringSaveAs : 1;
300 };
301 
302 }
303 
304 ReadOnlyPart::ReadOnlyPart( TQObject *parent, const char *name )
305  : Part( parent, name ), m_bTemp( false )
306 {
307  d = new ReadOnlyPartPrivate;
308 }
309 
310 ReadOnlyPart::~ReadOnlyPart()
311 {
312  ReadOnlyPart::closeURL();
313  delete d;
314 }
315 
316 void ReadOnlyPart::setProgressInfoEnabled( bool show )
317 {
318  d->m_showProgressInfo = show;
319 }
320 
321 bool ReadOnlyPart::isProgressInfoEnabled() const
322 {
323  return d->m_showProgressInfo;
324 }
325 
326 #ifndef KDE_NO_COMPAT
327 void ReadOnlyPart::showProgressInfo( bool show )
328 {
329  d->m_showProgressInfo = show;
330 }
331 #endif
332 
333 bool ReadOnlyPart::openURL( const KURL &url )
334 {
335  if ( !url.isValid() )
336  return false;
337  if ( !closeURL() )
338  return false;
339  m_url = url;
340  if ( m_url.isLocalFile() )
341  {
342  emit started( 0 );
343  m_file = m_url.path();
344  bool ret = openFile();
345  if (ret)
346  {
347  emit completed();
348  emit setWindowCaption( m_url.prettyURL() );
349  };
350  return ret;
351  }
352  else
353  {
354  m_bTemp = true;
355  // Use same extension as remote file. This is important for mimetype-determination (e.g. koffice)
356  TQString fileName = url.fileName();
357  TQFileInfo fileInfo(fileName);
358  TQString ext = fileInfo.extension();
359  TQString extension;
360  if ( !ext.isEmpty() && url.query().isNull() ) // not if the URL has a query, e.g. cgi.pl?something
361  extension = "."+ext; // keep the '.'
362  KTempFile tempFile( TQString::null, extension );
363  m_file = tempFile.name();
364 
365  KURL destURL;
366  destURL.setPath( m_file );
367  d->m_job = KIO::file_copy( m_url, destURL, 0600, true, false, d->m_showProgressInfo );
368  d->m_job->setWindow( widget() ? widget()->topLevelWidget() : 0 );
369  emit started( d->m_job );
370  connect( d->m_job, TQT_SIGNAL( result( KIO::Job * ) ), this, TQT_SLOT( slotJobFinished ( KIO::Job * ) ) );
371  return true;
372  }
373 }
374 
375 void ReadOnlyPart::abortLoad()
376 {
377  if ( d->m_job )
378  {
379  //kdDebug(1000) << "Aborting job " << d->m_job << endl;
380  d->m_job->kill();
381  d->m_job = 0;
382  }
383 }
384 
385 bool ReadOnlyPart::closeURL()
386 {
387  abortLoad(); //just in case
388 
389  if ( m_bTemp )
390  {
391  unlink( TQFile::encodeName(m_file) );
392  m_bTemp = false;
393  }
394  // It always succeeds for a read-only part,
395  // but the return value exists for reimplementations
396  // (e.g. pressing cancel for a modified read-write part)
397  return true;
398 }
399 
400 void ReadOnlyPart::slotJobFinished( KIO::Job * job )
401 {
402  kdDebug(1000) << "ReadOnlyPart::slotJobFinished" << endl;
403  assert( job == d->m_job );
404  d->m_job = 0;
405  if (job->error())
406  emit canceled( job->errorString() );
407  else
408  {
409  if ( openFile() )
410  emit setWindowCaption( m_url.prettyURL() );
411  emit completed();
412  }
413 }
414 
415 void ReadOnlyPart::guiActivateEvent( GUIActivateEvent * event )
416 {
417  if (event->activated())
418  {
419  if (!m_url.isEmpty())
420  {
421  kdDebug(1000) << "ReadOnlyPart::guiActivateEvent -> " << m_url.prettyURL() << endl;
422  emit setWindowCaption( m_url.prettyURL() );
423  } else emit setWindowCaption( "" );
424  }
425 }
426 
427 bool ReadOnlyPart::openStream( const TQString& mimeType, const KURL& url )
428 {
429  if ( !closeURL() )
430  return false;
431  m_url = url;
432  return doOpenStream( mimeType );
433 }
434 
435 bool ReadOnlyPart::writeStream( const TQByteArray& data )
436 {
437  return doWriteStream( data );
438 }
439 
440 bool ReadOnlyPart::closeStream()
441 {
442  return doCloseStream();
443 }
444 
446 
447 ReadWritePart::ReadWritePart( TQObject *parent, const char *name )
448  : ReadOnlyPart( parent, name ), m_bModified( false ), m_bClosing( false )
449 {
450  m_bReadWrite = true;
451 }
452 
453 ReadWritePart::~ReadWritePart()
454 {
455  // parent destructor will delete temp file
456  // we can't call our own closeURL() here, because
457  // "cancel" wouldn't cancel anything. We have to assume
458  // the app called closeURL() before destroying us.
459 }
460 
461 void ReadWritePart::setReadWrite( bool readwrite )
462 {
463  // Perhaps we should check isModified here and issue a warning if true
464  m_bReadWrite = readwrite;
465 }
466 
467 void ReadWritePart::setModified( bool modified )
468 {
469  kdDebug(1000) << "ReadWritePart::setModified( " << (modified ? "true" : "false") << ")" << endl;
470  if ( !m_bReadWrite && modified )
471  {
472  kdError(1000) << "Can't set a read-only document to 'modified' !" << endl;
473  return;
474  }
475  m_bModified = modified;
476 }
477 
478 void ReadWritePart::setModified()
479 {
480  setModified( true );
481 }
482 
483 bool ReadWritePart::queryClose()
484 {
485  if ( !isReadWrite() || !isModified() )
486  return true;
487 
488  TQString docName = url().fileName();
489  if (docName.isEmpty()) docName = i18n( "Untitled" );
490 
491  int res = KMessageBox::warningYesNoCancel( widget(),
492  i18n( "The document \"%1\" has been modified.\n"
493  "Do you want to save your changes or discard them?" ).arg( docName ),
494  i18n( "Close Document" ), KStdGuiItem::save(), KStdGuiItem::discard() );
495 
496  bool abortClose=false;
497  bool handled=false;
498 
499  switch(res) {
500  case KMessageBox::Yes :
501  sigQueryClose(&handled,&abortClose);
502  if (!handled)
503  {
504  if (m_url.isEmpty())
505  {
506  KURL url = KFileDialog::getSaveURL();
507  if (url.isEmpty())
508  return false;
509 
510  saveAs( url );
511  }
512  else
513  {
514  save();
515  }
516  } else if (abortClose) return false;
517  return waitSaveComplete();
518  case KMessageBox::No :
519  return true;
520  default : // case KMessageBox::Cancel :
521  return false;
522  }
523 }
524 
525 bool ReadWritePart::closeURL()
526 {
527  abortLoad(); //just in case
528  if ( isReadWrite() && isModified() )
529  {
530  if (!queryClose())
531  return false;
532  }
533  // Not modified => ok and delete temp file.
534  return ReadOnlyPart::closeURL();
535 }
536 
537 bool ReadWritePart::closeURL( bool promptToSave )
538 {
539  return promptToSave ? closeURL() : ReadOnlyPart::closeURL();
540 }
541 
542 bool ReadWritePart::save()
543 {
544  d->m_saveOk = false;
545  if ( m_file.isEmpty() ) // document was created empty
546  prepareSaving();
547  if( saveFile() )
548  return saveToURL();
549  else
550  emit canceled(TQString::null);
551  return false;
552 }
553 
554 bool ReadWritePart::saveAs( const KURL & kurl )
555 {
556  if (!kurl.isValid())
557  {
558  kdError(1000) << "saveAs: Malformed URL " << kurl.url() << endl;
559  return false;
560  }
561  d->m_duringSaveAs = true;
562  d->m_originalURL = m_url;
563  d->m_originalFilePath = m_file;
564  m_url = kurl; // Store where to upload in saveToURL
565  prepareSaving();
566  bool result = save(); // Save local file and upload local file
567  if (result)
568  emit setWindowCaption( m_url.prettyURL() );
569  else
570  {
571  m_url = d->m_originalURL;
572  m_file = d->m_originalFilePath;
573  d->m_duringSaveAs = false;
574  d->m_originalURL = KURL();
575  d->m_originalFilePath = TQString::null;
576  }
577 
578  return result;
579 }
580 
581 // Set m_file correctly for m_url
582 void ReadWritePart::prepareSaving()
583 {
584  // Local file
585  if ( m_url.isLocalFile() )
586  {
587  if ( m_bTemp ) // get rid of a possible temp file first
588  { // (happens if previous url was remote)
589  unlink( TQFile::encodeName(m_file) );
590  m_bTemp = false;
591  }
592  m_file = m_url.path();
593  }
594  else
595  { // Remote file
596  // We haven't saved yet, or we did but locally - provide a temp file
597  if ( m_file.isEmpty() || !m_bTemp )
598  {
599  KTempFile tempFile;
600  m_file = tempFile.name();
601  m_bTemp = true;
602  }
603  // otherwise, we already had a temp file
604  }
605 }
606 
607 bool ReadWritePart::saveToURL()
608 {
609  if ( m_url.isLocalFile() )
610  {
611  setModified( false );
612  emit completed();
613  // if m_url is a local file there won't be a temp file -> nothing to remove
614  assert( !m_bTemp );
615  d->m_saveOk = true;
616  d->m_duringSaveAs = false;
617  d->m_originalURL = KURL();
618  d->m_originalFilePath = TQString::null;
619  return true; // Nothing to do
620  }
621  else
622  {
623  if (d->m_uploadJob)
624  {
625  unlink(TQFile::encodeName(d->m_uploadJob->srcURL().path()));
626  d->m_uploadJob->kill();
627  d->m_uploadJob = 0;
628  }
629  KTempFile tempFile;
630  TQString uploadFile = tempFile.name();
631  KURL uploadUrl;
632  uploadUrl.setPath( uploadFile );
633  tempFile.unlink();
634  // Create hardlink
635  if (::link(TQFile::encodeName(m_file), TQFile::encodeName(uploadFile)) != 0)
636  {
637  // Uh oh, some error happened.
638  return false;
639  }
640  d->m_uploadJob = KIO::file_move( uploadUrl, m_url, -1, true /*overwrite*/ );
641  d->m_uploadJob->setWindow( widget() ? widget()->topLevelWidget() : 0 );
642  connect( d->m_uploadJob, TQT_SIGNAL( result( KIO::Job * ) ), this, TQT_SLOT( slotUploadFinished (KIO::Job *) ) );
643  return true;
644  }
645 }
646 
647 void ReadWritePart::slotUploadFinished( KIO::Job * )
648 {
649  if (d->m_uploadJob->error())
650  {
651  unlink(TQFile::encodeName(d->m_uploadJob->srcURL().path()));
652  TQString error = d->m_uploadJob->errorString();
653  d->m_uploadJob = 0;
654  if (d->m_duringSaveAs) {
655  m_url = d->m_originalURL;
656  m_file = d->m_originalFilePath;
657  }
658  emit canceled( error );
659  }
660  else
661  {
662  KDirNotify_stub allDirNotify("*", "KDirNotify*");
663  KURL dirUrl( m_url );
664  dirUrl.setPath( dirUrl.directory() );
665  allDirNotify.FilesAdded( dirUrl );
666 
667  d->m_uploadJob = 0;
668  setModified( false );
669  emit completed();
670  d->m_saveOk = true;
671  }
672  d->m_duringSaveAs = false;
673  d->m_originalURL = KURL();
674  d->m_originalFilePath = TQString::null;
675  if (d->m_waitForSave)
676  {
677  tqApp->exit_loop();
678  }
679 }
680 
681 // Trolls: Nothing to see here, please step away.
682 void qt_enter_modal( TQWidget *widget );
683 void qt_leave_modal( TQWidget *widget );
684 
685 bool ReadWritePart::waitSaveComplete()
686 {
687  if (!d->m_uploadJob)
688  return d->m_saveOk;
689 
690  d->m_waitForSave = true;
691 
692  TQWidget dummy(0,0,(WFlags)(WType_Dialog | WShowModal));
693  dummy.setFocusPolicy( TQ_NoFocus );
694  qt_enter_modal(&dummy);
695  tqApp->enter_loop();
696  qt_leave_modal(&dummy);
697 
698  d->m_waitForSave = false;
699 
700  return d->m_saveOk;
701 }
702 
703 #include "part.moc"
704 
705 // vim:sw=2:ts=8:et

kparts

Skip menu "kparts"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kparts

Skip menu "kparts"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kparts by doxygen 1.8.1.2
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |