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