• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

KParts

  • kparts
part.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
3  (C) 1999-2005 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 "part.h"
22 #include <kprotocolinfo.h>
23 #include "event.h"
24 #include "plugin.h"
25 #include "mainwindow.h"
26 #include "partmanager.h"
27 #include "browserextension.h"
28 
29 #include <QtGui/QApplication>
30 #include <QtCore/QFile>
31 #include <QtCore/QFileInfo>
32 #include <QtGui/QPainter>
33 #include <QtCore/QPoint>
34 
35 #include <kdirnotify.h>
36 #include <kfiledialog.h>
37 #include <kcomponentdata.h>
38 #include <kio/job.h>
39 #include <kio/jobuidelegate.h>
40 #include <klocale.h>
41 #include <kmessagebox.h>
42 #include <kstandarddirs.h>
43 #include <ktemporaryfile.h>
44 #include <kxmlguifactory.h>
45 
46 #include <stdio.h>
47 #include <unistd.h>
48 #include <assert.h>
49 #include <kdebug.h>
50 #include <kiconloader.h>
51 
52 using namespace KParts;
53 
54 namespace KParts
55 {
56 
57 class PartBasePrivate
58 {
59 public:
60  Q_DECLARE_PUBLIC(PartBase)
61 
62  PartBasePrivate(PartBase *q): q_ptr(q)
63  {
64  m_pluginLoadingMode = PartBase::LoadPlugins;
65  m_pluginInterfaceVersion = 0;
66  m_obj = 0;
67  }
68 
69  virtual ~PartBasePrivate()
70  {
71  }
72 
73  PartBase *q_ptr;
74  PartBase::PluginLoadingMode m_pluginLoadingMode;
75  int m_pluginInterfaceVersion;
76  QObject *m_obj;
77 };
78 
79 class PartPrivate: public PartBasePrivate
80 {
81 public:
82  Q_DECLARE_PUBLIC(Part)
83 
84  PartPrivate(Part *q)
85  : PartBasePrivate(q),
86  m_iconLoader(0),
87  m_bSelectable(true),
88  m_autoDeleteWidget(true),
89  m_autoDeletePart(true),
90  m_manager(0)
91  {
92  }
93 
94  ~PartPrivate()
95  {
96  }
97 
98  KIconLoader* m_iconLoader;
99  bool m_bSelectable;
100  bool m_autoDeleteWidget;
101  bool m_autoDeletePart;
102  PartManager * m_manager;
103  QPointer<QWidget> m_widget;
104 };
105 
106 }
107 
108 PartBase::PartBase()
109  : d_ptr(new PartBasePrivate(this))
110 {
111 }
112 
113 PartBase::PartBase(PartBasePrivate &dd)
114  : d_ptr(&dd)
115 {
116 }
117 
118 PartBase::~PartBase()
119 {
120  delete d_ptr;
121 }
122 
123 void PartBase::setPartObject( QObject *obj )
124 {
125  Q_D(PartBase);
126 
127  d->m_obj = obj;
128 }
129 
130 QObject *PartBase::partObject() const
131 {
132  Q_D(const PartBase);
133 
134  return d->m_obj;
135 }
136 
137 void PartBase::setComponentData(const KComponentData &componentData)
138 {
139  setComponentData(componentData, true);
140 }
141 
142 void PartBase::setComponentData(const KComponentData &componentData, bool bLoadPlugins)
143 {
144  Q_D(PartBase);
145 
146  KXMLGUIClient::setComponentData(componentData);
147  KGlobal::locale()->insertCatalog(componentData.catalogName());
148  // install 'instancename'data resource type
149  KGlobal::dirs()->addResourceType(QString(componentData.componentName() + "data").toUtf8(),
150  "data", componentData.componentName());
151  if (bLoadPlugins) {
152  loadPlugins(d->m_obj, this, componentData);
153  }
154 }
155 
156 void PartBase::loadPlugins(QObject *parent, KXMLGUIClient *parentGUIClient, const KComponentData &instance)
157 {
158  Q_D(PartBase);
159 
160  if( d->m_pluginLoadingMode != DoNotLoadPlugins )
161  Plugin::loadPlugins( parent, parentGUIClient, instance, d->m_pluginLoadingMode == LoadPlugins, d->m_pluginInterfaceVersion );
162 }
163 
164 void PartBase::setPluginLoadingMode( PluginLoadingMode loadingMode )
165 {
166  Q_D(PartBase);
167 
168  d->m_pluginLoadingMode = loadingMode;
169 }
170 
171 void KParts::PartBase::setPluginInterfaceVersion( int version )
172 {
173  Q_D(PartBase);
174 
175  d->m_pluginInterfaceVersion = version;
176 }
177 
178 Part::Part( QObject *parent )
179  : QObject( parent ), PartBase( *new PartPrivate(this) )
180 {
181  PartBase::setPartObject( this );
182 }
183 
184 Part::Part(PartPrivate &dd, QObject *parent)
185  : QObject( parent ), PartBase( dd )
186 {
187  PartBase::setPartObject( this );
188 }
189 
190 Part::~Part()
191 {
192  Q_D(Part);
193 
194  //kDebug(1000) << this;
195 
196  if ( d->m_widget )
197  {
198  // We need to disconnect first, to avoid calling it !
199  disconnect( d->m_widget, SIGNAL(destroyed()),
200  this, SLOT(slotWidgetDestroyed()) );
201  }
202 
203  if ( d->m_manager )
204  d->m_manager->removePart(this);
205 
206  if ( d->m_widget && d->m_autoDeleteWidget )
207  {
208  kDebug(1000) << "deleting widget" << d->m_widget << d->m_widget->objectName();
209  delete static_cast<QWidget*>(d->m_widget);
210  }
211 
212  delete d->m_iconLoader;
213 }
214 
215 void Part::embed( QWidget * parentWidget )
216 {
217  if ( widget() )
218  {
219  widget()->setParent( parentWidget, 0 );
220  widget()->setGeometry( 0, 0, widget()->width(), widget()->height() );
221  widget()->show();
222  }
223 }
224 
225 QWidget *Part::widget()
226 {
227  Q_D(Part);
228 
229  return d->m_widget;
230 }
231 
232 void Part::setAutoDeleteWidget(bool autoDeleteWidget)
233 {
234  Q_D(Part);
235  d->m_autoDeleteWidget = autoDeleteWidget;
236 }
237 
238 void Part::setAutoDeletePart(bool autoDeletePart)
239 {
240  Q_D(Part);
241  d->m_autoDeletePart = autoDeletePart;
242 }
243 
244 
245 
246 KIconLoader* Part::iconLoader()
247 {
248  Q_D(Part);
249 
250  if (!d->m_iconLoader) {
251  Q_ASSERT(componentData().isValid());
252  d->m_iconLoader = new KIconLoader( componentData() );
253  }
254  return d->m_iconLoader;
255 }
256 
257 void Part::setManager( PartManager *manager )
258 {
259  Q_D(Part);
260 
261  d->m_manager = manager;
262 }
263 
264 PartManager *Part::manager() const
265 {
266  Q_D(const Part);
267 
268  return d->m_manager;
269 }
270 
271 Part *Part::hitTest( QWidget *widget, const QPoint & )
272 {
273  Q_D(Part);
274 
275  if ( (QWidget *)d->m_widget != widget )
276  return 0;
277 
278  return this;
279 }
280 
281 void Part::setWidget( QWidget *widget )
282 {
283  Q_D(Part);
284  d->m_widget = widget;
285  connect( d->m_widget, SIGNAL(destroyed()),
286  this, SLOT(slotWidgetDestroyed()), Qt::UniqueConnection );
287 }
288 
289 void Part::setSelectable( bool selectable )
290 {
291  Q_D(Part);
292 
293  d->m_bSelectable = selectable;
294 }
295 
296 bool Part::isSelectable() const
297 {
298  Q_D(const Part);
299 
300  return d->m_bSelectable;
301 }
302 
303 void Part::customEvent( QEvent *ev )
304 {
305  if ( PartActivateEvent::test( ev ) )
306  {
307  partActivateEvent( static_cast<PartActivateEvent *>(ev) );
308  return;
309  }
310 
311  if ( PartSelectEvent::test( ev ) )
312  {
313  partSelectEvent( static_cast<PartSelectEvent *>(ev) );
314  return;
315  }
316 
317  if ( GUIActivateEvent::test( ev ) )
318  {
319  guiActivateEvent( static_cast<GUIActivateEvent *>(ev) );
320  return;
321  }
322 
323  QObject::customEvent( ev );
324 }
325 
326 void Part::partActivateEvent( PartActivateEvent * )
327 {
328 }
329 
330 void Part::partSelectEvent( PartSelectEvent * )
331 {
332 }
333 
334 void Part::guiActivateEvent( GUIActivateEvent * )
335 {
336 }
337 
338 QWidget *Part::hostContainer( const QString &containerName )
339 {
340  if ( !factory() )
341  return 0;
342 
343  return factory()->container( containerName, this );
344 }
345 
346 void Part::slotWidgetDestroyed()
347 {
348  Q_D(Part);
349 
350  d->m_widget = 0;
351  if (d->m_autoDeletePart) {
352  kDebug(1000) << "deleting part" << objectName();
353  delete this; // ouch, this should probably be deleteLater()
354  }
355 }
356 
357 void Part::loadPlugins()
358 {
359  PartBase::loadPlugins(this, this, componentData());
360 }
361 
363 
364 namespace KParts
365 {
366 
367 class ReadOnlyPartPrivate: public PartPrivate
368 {
369 public:
370  Q_DECLARE_PUBLIC(ReadOnlyPart)
371 
372  ReadOnlyPartPrivate(ReadOnlyPart *q): PartPrivate(q)
373  {
374  m_job = 0;
375  m_statJob = 0;
376  m_uploadJob = 0;
377  m_showProgressInfo = true;
378  m_saveOk = false;
379  m_waitForSave = false;
380  m_duringSaveAs = false;
381  m_bTemp = false;
382  m_bAutoDetectedMime = false;
383  }
384 
385  ~ReadOnlyPartPrivate()
386  {
387  }
388 
389  void _k_slotJobFinished( KJob * job );
390  void _k_slotStatJobFinished(KJob * job);
391  void _k_slotGotMimeType(KIO::Job *job, const QString &mime);
392  bool openLocalFile();
393  void openRemoteFile();
394 
395  KIO::FileCopyJob * m_job;
396  KIO::StatJob * m_statJob;
397  KIO::FileCopyJob * m_uploadJob;
398  KUrl m_originalURL; // for saveAs
399  QString m_originalFilePath; // for saveAs
400  bool m_showProgressInfo : 1;
401  bool m_saveOk : 1;
402  bool m_waitForSave : 1;
403  bool m_duringSaveAs : 1;
404 
408  bool m_bTemp: 1;
409 
410  // whether the mimetype in the arguments was detected by the part itself
411  bool m_bAutoDetectedMime : 1;
412 
416  KUrl m_url;
417 
421  QString m_file;
422 
423  OpenUrlArguments m_arguments;
424 };
425 
426 class ReadWritePartPrivate: public ReadOnlyPartPrivate
427 {
428 public:
429  Q_DECLARE_PUBLIC(ReadWritePart)
430 
431  ReadWritePartPrivate(ReadWritePart *q): ReadOnlyPartPrivate(q)
432  {
433  m_bModified = false;
434  m_bReadWrite = true;
435  m_bClosing = false;
436  }
437 
438  void _k_slotUploadFinished( KJob * job );
439 
440  void prepareSaving();
441 
442  bool m_bModified;
443  bool m_bReadWrite;
444  bool m_bClosing;
445  QEventLoop m_eventLoop;
446 };
447 
448 }
449 
450 ReadOnlyPart::ReadOnlyPart( QObject *parent )
451  : Part( *new ReadOnlyPartPrivate(this), parent )
452 {
453 }
454 
455 ReadOnlyPart::ReadOnlyPart( ReadOnlyPartPrivate &dd, QObject *parent )
456  : Part( dd, parent )
457 {
458 }
459 
460 ReadOnlyPart::~ReadOnlyPart()
461 {
462  ReadOnlyPart::closeUrl();
463 }
464 
465 KUrl ReadOnlyPart::url() const
466 {
467  Q_D(const ReadOnlyPart);
468 
469  return d->m_url;
470 }
471 
472 void ReadOnlyPart::setUrl(const KUrl &url)
473 {
474  Q_D(ReadOnlyPart);
475 
476  d->m_url = url;
477 }
478 
479 QString ReadOnlyPart::localFilePath() const
480 {
481  Q_D(const ReadOnlyPart);
482 
483  return d->m_file;
484 }
485 
486 void ReadOnlyPart::setLocalFilePath( const QString &localFilePath )
487 {
488  Q_D(ReadOnlyPart);
489 
490  d->m_file = localFilePath;
491 }
492 
493 #ifndef KDE_NO_DEPRECATED
494 bool ReadOnlyPart::isLocalFileTemporary() const
495 {
496  Q_D(const ReadOnlyPart);
497 
498  return d->m_bTemp;
499 }
500 #endif
501 
502 #ifndef KDE_NO_DEPRECATED
503 void ReadOnlyPart::setLocalFileTemporary( bool temp )
504 {
505  Q_D(ReadOnlyPart);
506 
507  d->m_bTemp = temp;
508 }
509 #endif
510 
511 void ReadOnlyPart::setProgressInfoEnabled( bool show )
512 {
513  Q_D(ReadOnlyPart);
514 
515  d->m_showProgressInfo = show;
516 }
517 
518 bool ReadOnlyPart::isProgressInfoEnabled() const
519 {
520  Q_D(const ReadOnlyPart);
521 
522  return d->m_showProgressInfo;
523 }
524 
525 #ifndef KDE_NO_COMPAT
526 void ReadOnlyPart::showProgressInfo( bool show )
527 {
528  Q_D(ReadOnlyPart);
529 
530  d->m_showProgressInfo = show;
531 }
532 #endif
533 
534 bool ReadOnlyPart::openUrl( const KUrl &url )
535 {
536  Q_D(ReadOnlyPart);
537 
538  if ( !url.isValid() )
539  return false;
540  if (d->m_bAutoDetectedMime) {
541  d->m_arguments.setMimeType(QString());
542  d->m_bAutoDetectedMime = false;
543  }
544  OpenUrlArguments args = d->m_arguments;
545  if ( !closeUrl() )
546  return false;
547  d->m_arguments = args;
548  d->m_url = url;
549 
550  d->m_file.clear();
551 
552  if (d->m_url.isLocalFile()) {
553  d->m_file = d->m_url.toLocalFile();
554  return d->openLocalFile();
555  } else if (KProtocolInfo::protocolClass(url.protocol()) == ":local") {
556  // Maybe we can use a "local path", to avoid a temp copy?
557  KIO::JobFlags flags = d->m_showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo;
558  d->m_statJob = KIO::mostLocalUrl(d->m_url, flags);
559  d->m_statJob->ui()->setWindow( widget() ? widget()->topLevelWidget() : 0 );
560  connect(d->m_statJob, SIGNAL(result(KJob*)), this, SLOT(_k_slotStatJobFinished(KJob*)));
561  return true;
562  } else {
563  d->openRemoteFile();
564  return true;
565  }
566 }
567 
568 bool ReadOnlyPart::openFile()
569 {
570  kWarning(1000) << "Default implementation of ReadOnlyPart::openFile called!"
571  << metaObject()->className() << "should reimplement either openUrl or openFile.";
572  return false;
573 }
574 
575 bool ReadOnlyPartPrivate::openLocalFile()
576 {
577  Q_Q(ReadOnlyPart);
578  emit q->started( 0 );
579  m_bTemp = false;
580  // set the mimetype only if it was not already set (for example, by the host application)
581  if (m_arguments.mimeType().isEmpty()) {
582  // get the mimetype of the file
583  // using findByUrl() to avoid another string -> url conversion
584  KMimeType::Ptr mime = KMimeType::findByUrl(m_url, 0, true /* local file*/);
585  if (mime) {
586  m_arguments.setMimeType(mime->name());
587  m_bAutoDetectedMime = true;
588  }
589  }
590  const bool ret = q->openFile();
591  if (ret) {
592  emit q->setWindowCaption(m_url.prettyUrl());
593  emit q->completed();
594  } else {
595  emit q->canceled(QString());
596  }
597  return ret;
598 }
599 
600 void ReadOnlyPartPrivate::openRemoteFile()
601 {
602  Q_Q(ReadOnlyPart);
603  m_bTemp = true;
604  // Use same extension as remote file. This is important for mimetype-determination (e.g. koffice)
605  QString fileName = m_url.fileName();
606  QFileInfo fileInfo(fileName);
607  QString ext = fileInfo.completeSuffix();
608  QString extension;
609  if (!ext.isEmpty() && m_url.query().isNull()) // not if the URL has a query, e.g. cgi.pl?something
610  extension = '.'+ext; // keep the '.'
611  KTemporaryFile tempFile;
612  tempFile.setSuffix(extension);
613  tempFile.setAutoRemove(false);
614  tempFile.open();
615  m_file = tempFile.fileName();
616 
617  KUrl destURL;
618  destURL.setPath( m_file );
619  KIO::JobFlags flags = m_showProgressInfo ? KIO::DefaultFlags : KIO::HideProgressInfo;
620  flags |= KIO::Overwrite;
621  m_job = KIO::file_copy(m_url, destURL, 0600, flags);
622  m_job->ui()->setWindow(q->widget() ? q->widget()->topLevelWidget() : 0);
623  emit q->started(m_job);
624  QObject::connect(m_job, SIGNAL(result(KJob*)), q, SLOT(_k_slotJobFinished(KJob*)));
625  QObject::connect(m_job, SIGNAL(mimetype(KIO::Job*,QString)),
626  q, SLOT(_k_slotGotMimeType(KIO::Job*,QString)));
627 }
628 
629 void ReadOnlyPart::abortLoad()
630 {
631  Q_D(ReadOnlyPart);
632 
633  if ( d->m_statJob ) {
634  //kDebug(1000) << "Aborting job" << d->m_statJob;
635  d->m_statJob->kill();
636  d->m_statJob = 0;
637  }
638  if ( d->m_job ) {
639  //kDebug(1000) << "Aborting job" << d->m_job;
640  d->m_job->kill();
641  d->m_job = 0;
642  }
643 }
644 
645 bool ReadOnlyPart::closeUrl()
646 {
647  Q_D(ReadOnlyPart);
648 
649  abortLoad(); //just in case
650 
651  d->m_arguments = KParts::OpenUrlArguments();
652 
653  if ( d->m_bTemp )
654  {
655  QFile::remove( d->m_file );
656  d->m_bTemp = false;
657  }
658  // It always succeeds for a read-only part,
659  // but the return value exists for reimplementations
660  // (e.g. pressing cancel for a modified read-write part)
661  return true;
662 }
663 
664 void ReadOnlyPartPrivate::_k_slotStatJobFinished(KJob * job)
665 {
666  Q_ASSERT(job == m_statJob);
667  m_statJob = 0;
668 
669  // We could emit canceled on error, but we haven't even emitted started yet,
670  // this could maybe confuse some apps? So for now we'll just fallback to KIO::get
671  // and error again. Well, maybe this even helps with wrong stat results.
672  if (!job->error()) {
673  const KUrl localUrl = static_cast<KIO::StatJob*>(job)->mostLocalUrl();
674  if (localUrl.isLocalFile()) {
675  m_file = localUrl.toLocalFile();
676  (void)openLocalFile();
677  return;
678  }
679  }
680  openRemoteFile();
681 }
682 
683 void ReadOnlyPartPrivate::_k_slotJobFinished( KJob * job )
684 {
685  Q_Q(ReadOnlyPart);
686 
687  assert( job == m_job );
688  m_job = 0;
689  if (job->error())
690  emit q->canceled( job->errorString() );
691  else
692  {
693  if ( q->openFile() ) {
694  emit q->setWindowCaption( m_url.prettyUrl() );
695  emit q->completed();
696  } else emit q->canceled(QString());
697  }
698 }
699 
700 void ReadOnlyPartPrivate::_k_slotGotMimeType(KIO::Job *job, const QString &mime)
701 {
702  kDebug(1000) << mime;
703  Q_ASSERT(job == m_job); Q_UNUSED(job)
704  // set the mimetype only if it was not already set (for example, by the host application)
705  if (m_arguments.mimeType().isEmpty()) {
706  m_arguments.setMimeType(mime);
707  m_bAutoDetectedMime = true;
708  }
709 }
710 
711 void ReadOnlyPart::guiActivateEvent( GUIActivateEvent * event )
712 {
713  Q_D(ReadOnlyPart);
714 
715  if (event->activated())
716  {
717  if (!d->m_url.isEmpty())
718  {
719  kDebug(1000) << d->m_url;
720  emit setWindowCaption( d->m_url.prettyUrl() );
721  } else emit setWindowCaption( "" );
722  }
723 }
724 
725 bool ReadOnlyPart::openStream( const QString& mimeType, const KUrl& url )
726 {
727  Q_D(ReadOnlyPart);
728 
729  OpenUrlArguments args = d->m_arguments;
730  if ( !closeUrl() )
731  return false;
732  d->m_arguments = args;
733  d->m_url = url;
734  return doOpenStream( mimeType );
735 }
736 
737 bool ReadOnlyPart::writeStream( const QByteArray& data )
738 {
739  return doWriteStream( data );
740 }
741 
742 bool ReadOnlyPart::closeStream()
743 {
744  return doCloseStream();
745 }
746 
747 BrowserExtension* ReadOnlyPart::browserExtension() const
748 {
749  return findChild<KParts::BrowserExtension *>();
750 }
751 
752 void KParts::ReadOnlyPart::setArguments(const OpenUrlArguments& arguments)
753 {
754  Q_D(ReadOnlyPart);
755  d->m_arguments = arguments;
756  d->m_bAutoDetectedMime = arguments.mimeType().isEmpty();
757 }
758 
759 OpenUrlArguments KParts::ReadOnlyPart::arguments() const
760 {
761  Q_D(const ReadOnlyPart);
762  return d->m_arguments;
763 }
764 
766 
767 
768 ReadWritePart::ReadWritePart( QObject *parent )
769  : ReadOnlyPart( *new ReadWritePartPrivate(this), parent )
770 {
771 }
772 
773 ReadWritePart::~ReadWritePart()
774 {
775  // parent destructor will delete temp file
776  // we can't call our own closeUrl() here, because
777  // "cancel" wouldn't cancel anything. We have to assume
778  // the app called closeUrl() before destroying us.
779 }
780 
781 void ReadWritePart::setReadWrite( bool readwrite )
782 {
783  Q_D(ReadWritePart);
784 
785  // Perhaps we should check isModified here and issue a warning if true
786  d->m_bReadWrite = readwrite;
787 }
788 
789 void ReadWritePart::setModified( bool modified )
790 {
791  Q_D(ReadWritePart);
792 
793  kDebug(1000) << "setModified(" << (modified ? "true" : "false") << ")";
794  if ( !d->m_bReadWrite && modified )
795  {
796  kError(1000) << "Can't set a read-only document to 'modified' !" << endl;
797  return;
798  }
799  d->m_bModified = modified;
800 }
801 
802 void ReadWritePart::setModified()
803 {
804  setModified( true );
805 }
806 
807 bool ReadWritePart::queryClose()
808 {
809  Q_D(ReadWritePart);
810 
811  if ( !isReadWrite() || !isModified() )
812  return true;
813 
814  QString docName = url().fileName();
815  if (docName.isEmpty()) docName = i18n( "Untitled" );
816 
817  QWidget *parentWidget=widget();
818  if(!parentWidget) parentWidget=QApplication::activeWindow();
819 
820  int res = KMessageBox::warningYesNoCancel( parentWidget,
821  i18n( "The document \"%1\" has been modified.\n"
822  "Do you want to save your changes or discard them?" , docName ),
823  i18n( "Close Document" ), KStandardGuiItem::save(), KStandardGuiItem::discard() );
824 
825  bool abortClose=false;
826  bool handled=false;
827 
828  switch(res) {
829  case KMessageBox::Yes :
830  sigQueryClose(&handled,&abortClose);
831  if (!handled)
832  {
833  if (d->m_url.isEmpty())
834  {
835  KUrl url = KFileDialog::getSaveUrl(KUrl(), QString(), parentWidget);
836  if (url.isEmpty())
837  return false;
838 
839  saveAs( url );
840  }
841  else
842  {
843  save();
844  }
845  } else if (abortClose) return false;
846  return waitSaveComplete();
847  case KMessageBox::No :
848  return true;
849  default : // case KMessageBox::Cancel :
850  return false;
851  }
852 }
853 
854 bool ReadWritePart::closeUrl()
855 {
856  abortLoad(); //just in case
857  if ( isReadWrite() && isModified() )
858  {
859  if (!queryClose())
860  return false;
861  }
862  // Not modified => ok and delete temp file.
863  return ReadOnlyPart::closeUrl();
864 }
865 
866 bool ReadWritePart::closeUrl( bool promptToSave )
867 {
868  return promptToSave ? closeUrl() : ReadOnlyPart::closeUrl();
869 }
870 
871 bool ReadWritePart::save()
872 {
873  Q_D(ReadWritePart);
874 
875  d->m_saveOk = false;
876  if ( d->m_file.isEmpty() ) // document was created empty
877  d->prepareSaving();
878  if( saveFile() )
879  return saveToUrl();
880  else
881  emit canceled(QString());
882  return false;
883 }
884 
885 bool ReadWritePart::saveAs( const KUrl & kurl )
886 {
887  Q_D(ReadWritePart);
888 
889  if (!kurl.isValid())
890  {
891  kError(1000) << "saveAs: Malformed URL " << kurl.url() << endl;
892  return false;
893  }
894  d->m_duringSaveAs = true;
895  d->m_originalURL = d->m_url;
896  d->m_originalFilePath = d->m_file;
897  d->m_url = kurl; // Store where to upload in saveToURL
898  d->prepareSaving();
899  bool result = save(); // Save local file and upload local file
900  if (result) {
901  emit setWindowCaption( d->m_url.prettyUrl() );
902  } else {
903  d->m_url = d->m_originalURL;
904  d->m_file = d->m_originalFilePath;
905  d->m_duringSaveAs = false;
906  d->m_originalURL = KUrl();
907  d->m_originalFilePath.clear();
908  }
909 
910  return result;
911 }
912 
913 // Set m_file correctly for m_url
914 void ReadWritePartPrivate::prepareSaving()
915 {
916  // Local file
917  if ( m_url.isLocalFile() )
918  {
919  if ( m_bTemp ) // get rid of a possible temp file first
920  { // (happens if previous url was remote)
921  QFile::remove( m_file );
922  m_bTemp = false;
923  }
924  m_file = m_url.toLocalFile();
925  }
926  else
927  { // Remote file
928  // We haven't saved yet, or we did but locally - provide a temp file
929  if ( m_file.isEmpty() || !m_bTemp )
930  {
931  KTemporaryFile tempFile;
932  tempFile.setAutoRemove(false);
933  tempFile.open();
934  m_file = tempFile.fileName();
935  m_bTemp = true;
936  }
937  // otherwise, we already had a temp file
938  }
939 }
940 
941 bool ReadWritePart::saveToUrl()
942 {
943  Q_D(ReadWritePart);
944 
945  if ( d->m_url.isLocalFile() )
946  {
947  setModified( false );
948  emit completed();
949  // if m_url is a local file there won't be a temp file -> nothing to remove
950  assert( !d->m_bTemp );
951  d->m_saveOk = true;
952  d->m_duringSaveAs = false;
953  d->m_originalURL = KUrl();
954  d->m_originalFilePath.clear();
955  return true; // Nothing to do
956  }
957  else
958  {
959  if (d->m_uploadJob)
960  {
961  QFile::remove(d->m_uploadJob->srcUrl().toLocalFile());
962  d->m_uploadJob->kill();
963  d->m_uploadJob = 0;
964  }
965  KTemporaryFile *tempFile = new KTemporaryFile();
966  tempFile->open();
967  QString uploadFile = tempFile->fileName();
968  delete tempFile;
969  KUrl uploadUrl;
970  uploadUrl.setPath( uploadFile );
971  // Create hardlink
972  if (::link(QFile::encodeName(d->m_file), QFile::encodeName(uploadFile)) != 0)
973  {
974  // Uh oh, some error happened.
975  return false;
976  }
977  d->m_uploadJob = KIO::file_move( uploadUrl, d->m_url, -1, KIO::Overwrite );
978  d->m_uploadJob->ui()->setWindow( widget() ? widget()->topLevelWidget() : 0 );
979  connect( d->m_uploadJob, SIGNAL(result(KJob*)), this, SLOT(_k_slotUploadFinished(KJob*)) );
980  return true;
981  }
982 }
983 
984 void ReadWritePartPrivate::_k_slotUploadFinished( KJob * )
985 {
986  Q_Q(ReadWritePart);
987 
988  if (m_uploadJob->error())
989  {
990  QFile::remove(m_uploadJob->srcUrl().toLocalFile());
991  QString error = m_uploadJob->errorString();
992  m_uploadJob = 0;
993  if (m_duringSaveAs) {
994  m_url = m_originalURL;
995  m_file = m_originalFilePath;
996  }
997  emit q->canceled( error );
998  }
999  else
1000  {
1001  KUrl dirUrl( m_url );
1002  dirUrl.setPath( dirUrl.directory() );
1003  ::org::kde::KDirNotify::emitFilesAdded( dirUrl.url() );
1004 
1005  m_uploadJob = 0;
1006  q->setModified( false );
1007  emit q->completed();
1008  m_saveOk = true;
1009  }
1010  m_duringSaveAs = false;
1011  m_originalURL = KUrl();
1012  m_originalFilePath.clear();
1013  if (m_waitForSave) {
1014  m_eventLoop.quit();
1015  }
1016 }
1017 
1018 bool ReadWritePart::isReadWrite() const
1019 {
1020  Q_D(const ReadWritePart);
1021 
1022  return d->m_bReadWrite;
1023 }
1024 
1025 bool ReadWritePart::isModified() const
1026 {
1027  Q_D(const ReadWritePart);
1028 
1029  return d->m_bModified;
1030 }
1031 
1032 bool ReadWritePart::waitSaveComplete()
1033 {
1034  Q_D(ReadWritePart);
1035 
1036  if (!d->m_uploadJob)
1037  return d->m_saveOk;
1038 
1039  d->m_waitForSave = true;
1040 
1041  d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
1042 
1043  d->m_waitForSave = false;
1044 
1045  return d->m_saveOk;
1046 }
1047 
1049 
1050 class KParts::OpenUrlArgumentsPrivate : public QSharedData
1051 {
1052 public:
1053  OpenUrlArgumentsPrivate()
1054  : reload(false),
1055  actionRequestedByUser(true),
1056  xOffset(0),
1057  yOffset(0),
1058  mimeType(),
1059  metaData()
1060  {}
1061  bool reload;
1062  bool actionRequestedByUser;
1063  int xOffset;
1064  int yOffset;
1065  QString mimeType;
1066  QMap<QString, QString> metaData;
1067 };
1068 
1069 KParts::OpenUrlArguments::OpenUrlArguments()
1070  : d(new OpenUrlArgumentsPrivate)
1071 {
1072 }
1073 
1074 KParts::OpenUrlArguments::OpenUrlArguments(const OpenUrlArguments &other)
1075  : d(other.d)
1076 {
1077 }
1078 
1079 KParts::OpenUrlArguments & KParts::OpenUrlArguments::operator=( const OpenUrlArguments &other)
1080 {
1081  d = other.d;
1082  return *this;
1083 }
1084 
1085 KParts::OpenUrlArguments::~OpenUrlArguments()
1086 {
1087 }
1088 
1089 bool KParts::OpenUrlArguments::reload() const
1090 {
1091  return d->reload;
1092 }
1093 
1094 void KParts::OpenUrlArguments::setReload(bool b)
1095 {
1096  d->reload = b;
1097 }
1098 
1099 int KParts::OpenUrlArguments::xOffset() const
1100 {
1101  return d->xOffset;
1102 }
1103 
1104 void KParts::OpenUrlArguments::setXOffset(int x)
1105 {
1106  d->xOffset = x;
1107 }
1108 
1109 int KParts::OpenUrlArguments::yOffset() const
1110 {
1111  return d->yOffset;
1112 }
1113 
1114 void KParts::OpenUrlArguments::setYOffset(int y)
1115 {
1116  d->yOffset = y;
1117 }
1118 
1119 QString KParts::OpenUrlArguments::mimeType() const
1120 {
1121  return d->mimeType;
1122 }
1123 
1124 void KParts::OpenUrlArguments::setMimeType(const QString& mime)
1125 {
1126  d->mimeType = mime;
1127 }
1128 
1129 QMap<QString, QString> & KParts::OpenUrlArguments::metaData()
1130 {
1131  return d->metaData;
1132 }
1133 
1134 const QMap<QString, QString> & KParts::OpenUrlArguments::metaData() const
1135 {
1136  return d->metaData;
1137 }
1138 
1139 bool KParts::OpenUrlArguments::actionRequestedByUser() const
1140 {
1141  return d->actionRequestedByUser;
1142 }
1143 
1144 void KParts::OpenUrlArguments::setActionRequestedByUser(bool userRequested)
1145 {
1146  d->actionRequestedByUser = userRequested;
1147 }
1148 
1149 #include "part.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Dec 7 2012 16:11:52 by doxygen 1.8.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KParts

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

kdelibs-4.8.5 API Reference

Skip menu "kdelibs-4.8.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal