00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <kparts/part.h>
00022
#include <kparts/event.h>
00023
#include <kparts/plugin.h>
00024
#include <kparts/mainwindow.h>
00025
#include <kparts/partmanager.h>
00026
00027
#include <qapplication.h>
00028
#include <qfile.h>
00029
#include <qpoint.h>
00030
#include <qpointarray.h>
00031
#include <qpainter.h>
00032
#include <qtextstream.h>
00033
#include <qfileinfo.h>
00034
00035
#include <kinstance.h>
00036
#include <klocale.h>
00037
#include <ktempfile.h>
00038
#include <kmessagebox.h>
00039
#include <kio/job.h>
00040
#include <kstandarddirs.h>
00041
#include <kfiledialog.h>
00042
#include <kdirnotify_stub.h>
00043
00044
#include <stdio.h>
00045
#include <unistd.h>
00046
#include <assert.h>
00047
#include <kdebug.h>
00048
00049
template class QPtrList<KXMLGUIClient>;
00050
00051
using namespace KParts;
00052
00053
namespace KParts
00054 {
00055
00056
class PartBasePrivate
00057 {
00058
public:
00059 PartBasePrivate()
00060 {
00061 m_pluginLoadingMode = PartBase::LoadPlugins;
00062 }
00063 ~PartBasePrivate()
00064 {
00065 }
00066 PartBase::PluginLoadingMode m_pluginLoadingMode;
00067 };
00068
00069
class PartPrivate
00070 {
00071
public:
00072 PartPrivate()
00073 {
00074 m_bSelectable =
true;
00075 }
00076 ~PartPrivate()
00077 {
00078 }
00079
00080
bool m_bSelectable;
00081 };
00082 }
00083
00084 PartBase::PartBase()
00085 {
00086 d =
new PartBasePrivate;
00087 m_obj = 0L;
00088 }
00089
00090 PartBase::~PartBase()
00091 {
00092
delete d;
00093 }
00094
00095 void PartBase::setPartObject(
QObject *obj )
00096 {
00097 m_obj = obj;
00098 }
00099
00100
QObject *PartBase::partObject()
const
00101
{
00102
return m_obj;
00103 }
00104
00105 void PartBase::setInstance(
KInstance *inst )
00106 {
00107
setInstance( inst,
true );
00108 }
00109
00110 void PartBase::setInstance(
KInstance *inst,
bool bLoadPlugins )
00111 {
00112 KXMLGUIClient::setInstance( inst );
00113
KGlobal::locale()->
insertCatalogue( inst->
instanceName() );
00114
00115
KGlobal::dirs()->
addResourceType( inst->
instanceName() +
"data",
00116 KStandardDirs::kde_default(
"data" )
00117 + QString::fromLatin1( inst->
instanceName() ) +
'/' );
00118
if ( bLoadPlugins )
00119
loadPlugins( m_obj,
this,
instance() );
00120 }
00121
00122 void PartBase::loadPlugins(
QObject *parent,
KXMLGUIClient *parentGUIClient,
KInstance *instance )
00123 {
00124
if( d->m_pluginLoadingMode !=
DoNotLoadPlugins )
00125 Plugin::loadPlugins( parent, parentGUIClient, instance, d->m_pluginLoadingMode ==
LoadPlugins );
00126 }
00127
00128 void PartBase::setPluginLoadingMode( PluginLoadingMode loadingMode )
00129 {
00130 d->m_pluginLoadingMode = loadingMode;
00131 }
00132
00133 Part::Part(
QObject *parent,
const char* name )
00134 :
QObject( parent, name )
00135 {
00136 d =
new PartPrivate;
00137 m_widget = 0L;
00138 m_manager = 0L;
00139 PartBase::setPartObject(
this );
00140 }
00141
00142 Part::~Part()
00143 {
00144
kdDebug(1000) <<
"Part::~Part " <<
this <<
endl;
00145
00146
if ( m_widget )
00147 {
00148
00149 disconnect( m_widget, SIGNAL( destroyed() ),
00150
this, SLOT( slotWidgetDestroyed() ) );
00151 }
00152
00153
if ( m_manager )
00154 m_manager->
removePart(
this);
00155
00156
if ( m_widget )
00157 {
00158
kdDebug(1000) <<
"deleting widget " << m_widget <<
" " << m_widget->name() <<
endl;
00159
delete (
QWidget*) m_widget;
00160 }
00161
00162
delete d;
00163 }
00164
00165 void Part::embed(
QWidget * parentWidget )
00166 {
00167
if (
widget() )
00168
widget()->reparent( parentWidget, 0,
QPoint( 0, 0 ),
true );
00169 }
00170
00171 QWidget *
Part::widget()
00172 {
00173
return m_widget;
00174 }
00175
00176
void Part::setManager(
PartManager *manager )
00177 {
00178 m_manager = manager;
00179 }
00180
00181 PartManager *
Part::manager()
const
00182
{
00183
return m_manager;
00184 }
00185
00186
Part *Part::hitTest(
QWidget *widget,
const QPoint & )
00187 {
00188
if ( (
QWidget *)m_widget != widget )
00189
return 0L;
00190
00191
return this;
00192 }
00193
00194 void Part::setWidget(
QWidget *widget )
00195 {
00196 assert ( !m_widget );
00197 m_widget = widget;
00198 connect( m_widget, SIGNAL( destroyed() ),
00199
this, SLOT( slotWidgetDestroyed() ) );
00200
00201
00202
00203
actionCollection()->
setWidget( widget );
00204
00205
00206
00207
00208
actionCollection()->
setAutoConnectShortcuts(
false );
00209 }
00210
00211 void Part::setSelectable(
bool selectable )
00212 {
00213 d->m_bSelectable = selectable;
00214 }
00215
00216 bool Part::isSelectable()
const
00217
{
00218
return d->m_bSelectable;
00219 }
00220
00221
void Part::customEvent(
QCustomEvent *event )
00222 {
00223
if ( PartActivateEvent::test( event ) )
00224 {
00225 partActivateEvent( (
PartActivateEvent *)event );
00226
return;
00227 }
00228
00229
if ( PartSelectEvent::test( event ) )
00230 {
00231 partSelectEvent( (
PartSelectEvent *)event );
00232
return;
00233 }
00234
00235
if ( GUIActivateEvent::test( event ) )
00236 {
00237
guiActivateEvent( (
GUIActivateEvent *)event );
00238
return;
00239 }
00240
00241 QObject::customEvent( event );
00242 }
00243
00244 void Part::partActivateEvent(
PartActivateEvent * )
00245 {
00246 }
00247
00248 void Part::partSelectEvent(
PartSelectEvent * )
00249 {
00250 }
00251
00252 void Part::guiActivateEvent(
GUIActivateEvent * )
00253 {
00254 }
00255
00256 QWidget *Part::hostContainer(
const QString &containerName )
00257 {
00258
if ( !
factory() )
00259
return 0L;
00260
00261
return factory()->
container( containerName,
this );
00262 }
00263
00264
void Part::slotWidgetDestroyed()
00265 {
00266
kdDebug(1000) <<
"KPart::slotWidgetDestroyed(), deleting part " << name() <<
endl;
00267 m_widget = 0;
00268
delete this;
00269 }
00270
00272
00273
namespace KParts
00274 {
00275
00276
class ReadOnlyPartPrivate
00277 {
00278
public:
00279 ReadOnlyPartPrivate()
00280 {
00281 m_job = 0L;
00282 m_uploadJob = 0L;
00283 m_showProgressInfo =
true;
00284 m_saveOk =
false;
00285 m_waitForSave =
false;
00286 m_duringSaveAs =
false;
00287 }
00288 ~ReadOnlyPartPrivate()
00289 {
00290 }
00291
00292
KIO::FileCopyJob * m_job;
00293
KIO::FileCopyJob * m_uploadJob;
00294
KURL m_originalURL;
00295
bool m_showProgressInfo : 1;
00296
bool m_saveOk : 1;
00297
bool m_waitForSave : 1;
00298
bool m_duringSaveAs : 1;
00299 };
00300
00301 }
00302
00303 ReadOnlyPart::ReadOnlyPart(
QObject *parent,
const char *name )
00304 :
Part( parent, name ), m_bTemp( false )
00305 {
00306 d =
new ReadOnlyPartPrivate;
00307 }
00308
00309 ReadOnlyPart::~ReadOnlyPart()
00310 {
00311
ReadOnlyPart::closeURL();
00312
delete d;
00313 }
00314
00315 void ReadOnlyPart::setProgressInfoEnabled(
bool show )
00316 {
00317 d->m_showProgressInfo = show;
00318 }
00319
00320 bool ReadOnlyPart::isProgressInfoEnabled()
const
00321
{
00322
return d->m_showProgressInfo;
00323 }
00324
00325
#ifndef KDE_NO_COMPAT
00326
void ReadOnlyPart::showProgressInfo(
bool show )
00327 {
00328 d->m_showProgressInfo = show;
00329 }
00330
#endif
00331
00332 bool ReadOnlyPart::openURL(
const KURL &url )
00333 {
00334
if ( !url.
isValid() )
00335
return false;
00336
if ( !
closeURL() )
00337
return false;
00338
m_url = url;
00339
if (
m_url.
isLocalFile() )
00340 {
00341 emit
started( 0 );
00342
m_file =
m_url.
path();
00343
bool ret =
openFile();
00344
if (ret)
00345 {
00346 emit
completed();
00347 emit setWindowCaption(
m_url.
prettyURL() );
00348 };
00349
return ret;
00350 }
00351
else
00352 {
00353
m_bTemp =
true;
00354
00355
QString fileName = url.fileName();
00356
QFileInfo fileInfo(fileName);
00357
QString ext = fileInfo.extension();
00358
QString extension;
00359
if ( !ext.isEmpty() && url.query().isNull() )
00360 extension =
"."+ext;
00361
KTempFile tempFile( QString::null, extension );
00362
m_file = tempFile.
name();
00363
00364
KURL destURL;
00365 destURL.
setPath(
m_file );
00366 d->m_job =
KIO::file_copy(
m_url, destURL, 0600,
true,
false, d->m_showProgressInfo );
00367 d->m_job->setWindow(
widget() ?
widget()->topLevelWidget() : 0 );
00368 emit
started( d->m_job );
00369 connect( d->m_job, SIGNAL( result(
KIO::Job * ) ),
this, SLOT( slotJobFinished (
KIO::Job * ) ) );
00370
return true;
00371 }
00372 }
00373
00374
void ReadOnlyPart::abortLoad()
00375 {
00376
if ( d->m_job )
00377 {
00378
00379 d->m_job->kill();
00380 d->m_job = 0;
00381 }
00382 }
00383
00384 bool ReadOnlyPart::closeURL()
00385 {
00386 abortLoad();
00387
00388
if (
m_bTemp )
00389 {
00390 unlink( QFile::encodeName(
m_file) );
00391
m_bTemp =
false;
00392 }
00393
00394
00395
00396
return true;
00397 }
00398
00399
void ReadOnlyPart::slotJobFinished(
KIO::Job * job )
00400 {
00401
kdDebug(1000) <<
"ReadOnlyPart::slotJobFinished" <<
endl;
00402 assert( job == d->m_job );
00403 d->m_job = 0;
00404
if (job->
error())
00405 emit canceled( job->
errorString() );
00406
else
00407 {
00408
if (
openFile() )
00409 emit setWindowCaption( m_url.
prettyURL() );
00410 emit
completed();
00411 }
00412 }
00413
00414 void ReadOnlyPart::guiActivateEvent(
GUIActivateEvent * event )
00415 {
00416
if (event->activated())
00417 {
00418
if (!
m_url.
isEmpty())
00419 {
00420
kdDebug(1000) <<
"ReadOnlyPart::guiActivateEvent -> " <<
m_url.
prettyURL() <<
endl;
00421 emit setWindowCaption(
m_url.
prettyURL() );
00422 }
else emit setWindowCaption(
"" );
00423 }
00424 }
00425
00426 bool ReadOnlyPart::openStream(
const QString& mimeType,
const KURL& url )
00427 {
00428
if ( !
closeURL() )
00429
return false;
00430
m_url = url;
00431
return doOpenStream( mimeType );
00432 }
00433
00434 bool ReadOnlyPart::writeStream(
const QByteArray& data )
00435 {
00436
return doWriteStream( data );
00437 }
00438
00439 bool ReadOnlyPart::closeStream()
00440 {
00441
return doCloseStream();
00442 }
00443
00445
00446 ReadWritePart::ReadWritePart(
QObject *parent,
const char *name )
00447 :
ReadOnlyPart( parent, name ), m_bModified( false ), m_bClosing( false )
00448 {
00449 m_bReadWrite =
true;
00450 }
00451
00452 ReadWritePart::~ReadWritePart()
00453 {
00454
00455
00456
00457
00458 }
00459
00460 void ReadWritePart::setReadWrite(
bool readwrite )
00461 {
00462
00463 m_bReadWrite = readwrite;
00464 }
00465
00466 void ReadWritePart::setModified(
bool modified )
00467 {
00468
kdDebug(1000) <<
"ReadWritePart::setModified( " << (modified ?
"true" :
"false") <<
")" <<
endl;
00469
if ( !m_bReadWrite && modified )
00470 {
00471
kdError(1000) <<
"Can't set a read-only document to 'modified' !" <<
endl;
00472
return;
00473 }
00474 m_bModified = modified;
00475 }
00476
00477 void ReadWritePart::setModified()
00478 {
00479
setModified(
true );
00480 }
00481
00482 bool ReadWritePart::queryClose()
00483 {
00484
if ( !
isReadWrite() || !
isModified() )
00485
return true;
00486
00487
QString docName =
url().
fileName();
00488
if (docName.isEmpty()) docName = i18n(
"Untitled" );
00489
00490
int res = KMessageBox::warningYesNoCancel(
widget(),
00491 i18n(
"The document \"%1\" has been modified.\n"
00492
"Do you want to save your changes or discard them?" ).arg( docName ),
00493 i18n(
"Close Document" ), KStdGuiItem::save(), KStdGuiItem::discard() );
00494
00495
bool abortClose=
false;
00496
bool handled=
false;
00497
00498
switch(res) {
00499
case KMessageBox::Yes :
00500
sigQueryClose(&handled,&abortClose);
00501
if (!handled)
00502 {
00503
if (m_url.
isEmpty())
00504 {
00505
KURL url = KFileDialog::getSaveURL();
00506
if (url.
isEmpty())
00507
return false;
00508
00509
saveAs( url );
00510 }
00511
else
00512 {
00513
save();
00514 }
00515 }
else if (abortClose)
return false;
00516
return waitSaveComplete();
00517
case KMessageBox::No :
00518
return true;
00519
default :
00520
return false;
00521 }
00522 }
00523
00524 bool ReadWritePart::closeURL()
00525 {
00526 abortLoad();
00527
if (
isReadWrite() &&
isModified() )
00528 {
00529
if (!
queryClose())
00530
return false;
00531 }
00532
00533
return ReadOnlyPart::closeURL();
00534 }
00535
00536 bool ReadWritePart::closeURL(
bool promptToSave )
00537 {
00538
return promptToSave ?
closeURL() :
ReadOnlyPart::closeURL();
00539 }
00540
00541 bool ReadWritePart::save()
00542 {
00543 d->m_saveOk =
false;
00544
if ( m_file.isEmpty() )
00545 prepareSaving();
00546
if(
saveFile() )
00547
return saveToURL();
00548
else
00549 emit canceled(QString::null);
00550
return false;
00551 }
00552
00553 bool ReadWritePart::saveAs(
const KURL & kurl )
00554 {
00555
if (!kurl.
isValid())
00556 {
00557
kdError(1000) <<
"saveAs: Malformed URL " << kurl.
url() <<
endl;
00558
return false;
00559 }
00560 d->m_duringSaveAs =
true;
00561 d->m_originalURL = m_url;
00562 m_url = kurl;
00563 prepareSaving();
00564
bool result =
save();
00565
if (result)
00566 emit setWindowCaption( m_url.
prettyURL() );
00567
else
00568 {
00569 m_url = d->m_originalURL;
00570 d->m_duringSaveAs =
false;
00571 d->m_originalURL =
KURL();
00572 }
00573
00574
return result;
00575 }
00576
00577
00578
void ReadWritePart::prepareSaving()
00579 {
00580
00581
if ( m_url.
isLocalFile() )
00582 {
00583
if ( m_bTemp )
00584 {
00585 unlink( QFile::encodeName(m_file) );
00586 m_bTemp =
false;
00587 }
00588 m_file = m_url.
path();
00589 }
00590
else
00591 {
00592
00593
if (
m_file.isEmpty() || !
m_bTemp )
00594 {
00595
KTempFile tempFile;
00596
m_file = tempFile.
name();
00597
m_bTemp =
true;
00598 }
00599
00600 }
00601 }
00602
00603 bool ReadWritePart::saveToURL()
00604 {
00605
if ( m_url.
isLocalFile() )
00606 {
00607
setModified(
false );
00608 emit
completed();
00609
00610 assert( !m_bTemp );
00611 d->m_saveOk =
true;
00612 d->m_duringSaveAs =
false;
00613 d->m_originalURL =
KURL();
00614
return true;
00615 }
00616
else
00617 {
00618
if (d->m_uploadJob)
00619 {
00620 unlink(QFile::encodeName(d->m_uploadJob->srcURL().path()));
00621 d->m_uploadJob->kill();
00622 d->m_uploadJob = 0;
00623 }
00624
KTempFile tempFile;
00625
QString uploadFile = tempFile.
name();
00626
KURL uploadUrl;
00627 uploadUrl.
setPath( uploadFile );
00628 tempFile.
unlink();
00629
00630
if (::link(QFile::encodeName(m_file), QFile::encodeName(uploadFile)) != 0)
00631 {
00632
00633
return false;
00634 }
00635 d->m_uploadJob =
KIO::file_move( uploadUrl, m_url, -1,
true );
00636 d->m_uploadJob->setWindow(
widget() ?
widget()->topLevelWidget() : 0 );
00637 connect( d->m_uploadJob, SIGNAL( result(
KIO::Job * ) ),
this, SLOT( slotUploadFinished (
KIO::Job *) ) );
00638
return true;
00639 }
00640 }
00641
00642
void ReadWritePart::slotUploadFinished(
KIO::Job * )
00643 {
00644
if (d->m_uploadJob->error())
00645 {
00646 unlink(QFile::encodeName(d->m_uploadJob->srcURL().path()));
00647
QString error = d->m_uploadJob->errorString();
00648 d->m_uploadJob = 0;
00649
if (d->m_duringSaveAs)
00650 m_url = d->m_originalURL;
00651 emit canceled( error );
00652 }
00653
else
00654 {
00655 KDirNotify_stub allDirNotify(
"*",
"KDirNotify*");
00656
KURL dirUrl( m_url );
00657 dirUrl.
setPath( dirUrl.
directory() );
00658 allDirNotify.FilesAdded( dirUrl );
00659
00660 d->m_uploadJob = 0;
00661
setModified(
false );
00662 emit
completed();
00663 d->m_saveOk =
true;
00664 }
00665 d->m_duringSaveAs =
false;
00666 d->m_originalURL =
KURL();
00667
if (d->m_waitForSave)
00668 {
00669 qApp->exit_loop();
00670 }
00671 }
00672
00673
00674
void qt_enter_modal(
QWidget *widget );
00675
void qt_leave_modal(
QWidget *widget );
00676
00677 bool ReadWritePart::waitSaveComplete()
00678 {
00679
if (!d->m_uploadJob)
00680
return d->m_saveOk;
00681
00682 d->m_waitForSave =
true;
00683
00684
QWidget dummy(0,0,WType_Dialog | WShowModal);
00685 dummy.setFocusPolicy( QWidget::NoFocus );
00686 qt_enter_modal(&dummy);
00687 qApp->enter_loop();
00688 qt_leave_modal(&dummy);
00689
00690 d->m_waitForSave =
false;
00691
00692
return d->m_saveOk;
00693 }
00694
00695
#include "part.moc"
00696
00697