00001
#include <sys/types.h>
00002
#include <sys/stat.h>
00003
#include <unistd.h>
00004
00005
#include <qpopupmenu.h>
00006
#include <qfile.h>
00007
#include <qlayout.h>
00008
#include <qmap.h>
00009
#include <qlabel.h>
00010
00011
#include <kmimetype.h>
00012
#include <kservice.h>
00013
#include <ktrader.h>
00014
#include <kapplication.h>
00015
#include <krun.h>
00016
#include <kdebug.h>
00017
#include <klocale.h>
00018
#include <kmessagebox.h>
00019
#include <kparts/part.h>
00020
#include <kparts/factory.h>
00021
#include <kparts/partmanager.h>
00022
#include <kparts/browserextension.h>
00023
#include <kfiledialog.h>
00024
#include <kmainwindow.h>
00025
#include <kaction.h>
00026
#include <kstatusbar.h>
00027
#include <khtml_part.h>
00028
#include <kpopupmenu.h>
00029
#include <kio/netaccess.h>
00030
#include <kdialogbase.h>
00031
#include <klineedit.h>
00032
#include <kshortcut.h>
00033
#include <kcompletion.h>
00034
#include <kdirwatch.h>
00035
#include <kdeversion.h>
00036
#include <kiconloader.h>
00037
#include <kuserprofile.h>
00038
00039
#include <ktexteditor/view.h>
00040
#include <ktexteditor/document.h>
00041
00042
#include "toplevel.h"
00043
#include "api.h"
00044
#include "core.h"
00045
#include "editorproxy.h"
00046
#include "documentationpart.h"
00047
#include "ksavealldialog.h"
00048
00049
#include "kdevproject.h"
00050
#include "urlutil.h"
00051
00052
#include "partcontroller.h"
00053
00054
#ifdef KDE_MAKE_VERSION
00055
# if KDE_VERSION < KDE_MAKE_VERSION(3,1,90)
00056
# define OLD__KDE
00057
# endif
00058
#else
00059 # define OLD__KDE
00060
#endif
00061
00062 PartController *
PartController::s_instance = 0;
00063
00064
using namespace MainWindowUtils;
00065
00066 struct HistoryEntry {
00067 KURL url;
00068 QString context;
00069
00070 HistoryEntry(
const KURL& u,
const QString& c ):
url( u ),
context( c ) {}
00071 };
00072
00073 PartController::PartController(
QWidget *parent)
00074 :
KDevPartController(parent)
00075 {
00076
dirWatcher =
new KDirWatch(
this );
00077
00078 connect(
this, SIGNAL(partRemoved(
KParts::Part*)),
this, SLOT(
updateMenuItems()));
00079 connect(
this, SIGNAL(partAdded(
KParts::Part*)),
this, SLOT(
updateMenuItems()));
00080 connect(
this, SIGNAL(activePartChanged(
KParts::Part*)),
this, SLOT(
slotActivePartChanged(
KParts::Part*)));
00081 connect(
dirWatcher, SIGNAL(
dirty(
const QString&)),
this, SLOT(
dirty(
const QString&)));
00082 connect(
this, SIGNAL(fileDirty(
const KURL& )),
this, SLOT(
slotFileDirty(
const KURL&)) );
00083
00084
m_history.setAutoDelete(
true );
00085
m_restoring =
false;
00086
setupActions();
00087 }
00088
00089
00090 PartController::~PartController()
00091 {
00092 }
00093
00094
00095 void PartController::createInstance(
QWidget *parent)
00096 {
00097
if (!
s_instance)
00098
s_instance =
new PartController(parent);
00099 }
00100
00101
00102 PartController *
PartController::getInstance()
00103 {
00104
return s_instance;
00105 }
00106
00107
00108 void PartController::setupActions()
00109 {
00110
KActionCollection *ac =
TopLevel::getInstance()->
main()->
actionCollection();
00111
00112
KAction* newAction =
KStdAction::open(
this, SLOT(
slotOpenFile()),
00113 ac,
"file_open");
00114 newAction->
setToolTip( i18n(
"Open file") );
00115 newAction->
setWhatsThis( i18n(
"<b>Open file</b><p>Opens an existing file without adding it to the project.</p>") );
00116
00117
m_openRecentAction =
KStdAction::openRecent(
this, SLOT(
slotOpenRecent(
const KURL&) ),
00118 ac,
"file_open_recent" );
00119
m_openRecentAction->
setWhatsThis(
QString(
"<b>%1</b><p>%2").arg(
beautifyToolTip(
m_openRecentAction->
text())).arg(i18n(
"Opens recently opened file.")));
00120
m_openRecentAction->
loadEntries( kapp->config(),
"RecentFiles" );
00121
00122
m_saveAllFilesAction =
new KAction(i18n(
"Save Al&l"), 0,
00123
this, SLOT(
slotSaveAllFiles()),
00124 ac,
"file_save_all");
00125
m_saveAllFilesAction->
setToolTip( i18n(
"Save all modified files") );
00126
m_saveAllFilesAction->
setWhatsThis(i18n(
"<b>Save all</b><p>Saves all modified files."));
00127
m_saveAllFilesAction->
setEnabled(
false);
00128
00129
m_revertAllFilesAction =
new KAction(i18n(
"Rever&t All"), 0,
00130
this, SLOT(
slotRevertAllFiles()),
00131 ac,
"file_revert_all");
00132
m_revertAllFilesAction->
setToolTip(i18n(
"Revert all changes"));
00133
m_revertAllFilesAction->
setWhatsThis(i18n(
"<b>Revert all</b><p>Reverts all changes in opened files. Prompts to save changes so the revert can be cancelled for each modified file."));
00134
m_revertAllFilesAction->
setEnabled(
false);
00135
00136
m_closeWindowAction =
KStdAction::close(
00137
this, SLOT(
slotCloseWindow()),
00138 ac,
"file_close");
00139
m_closeWindowAction->
setToolTip( i18n(
"Close current file") );
00140
m_closeWindowAction->
setWhatsThis(
QString(
"<b>%1</b><p>%2").arg(
beautifyToolTip(
m_closeWindowAction->
text())).arg(i18n(
"Closes current file.")));
00141
m_closeWindowAction->
setEnabled(
false);
00142
00143
m_closeAllWindowsAction =
new KAction(i18n(
"Close All"), 0,
00144
this, SLOT(
slotCloseAllWindows()),
00145 ac,
"file_close_all");
00146
m_closeAllWindowsAction->
setToolTip( i18n(
"Close all files") );
00147
m_closeAllWindowsAction->
setWhatsThis(i18n(
"<b>Close all</b><p>Close all opened files."));
00148
m_closeAllWindowsAction->
setEnabled(
false);
00149
00150
m_closeOtherWindowsAction =
new KAction(i18n(
"Close All Others"), 0,
00151
this, SLOT(
slotCloseOtherWindows()),
00152 ac,
"file_closeother");
00153
m_closeOtherWindowsAction->
setToolTip( i18n(
"Close other files") );
00154
m_closeOtherWindowsAction->
setWhatsThis(i18n(
"<b>Close all others</b><p>Close all opened files except current."));
00155
m_closeOtherWindowsAction->
setEnabled(
false);
00156
00157
m_backAction =
new KToolBarPopupAction(i18n(
"Back"),
"back", 0,
00158
this, SLOT(
slotBack()),
00159 ac,
"browser_back");
00160
m_backAction->
setEnabled(
false );
00161
m_backAction->
setToolTip(i18n(
"Back"));
00162
m_backAction->
setWhatsThis(i18n(
"<b>Back</b><p>Moves backwards one step in the <b>documentation</b> browsing history."));
00163
00164
m_switchToAction =
new KAction(i18n(
"Switch To..."),
KShortcut(
"CTRL+/"),
00165
this, SLOT(
slotSwitchTo()),
00166 ac,
"file_switchto");
00167
m_switchToAction->
setToolTip(i18n(
"Switch to"));
00168
m_switchToAction->
setWhatsThis(i18n(
"<b>Switch to</b><p>Prompts to enter the name of previously opened file to switch to."));
00169
00170
new KActionSeparator(ac,
"dummy_separator");
00171
00172 connect(
m_backAction->
popupMenu(), SIGNAL(aboutToShow()),
00173
this, SLOT(
slotBackAboutToShow()));
00174 connect(
m_backAction->
popupMenu(), SIGNAL(activated(
int)),
00175
this, SLOT(
slotBackPopupActivated(
int)));
00176
00177
00178
m_forwardAction =
new KToolBarPopupAction(i18n(
"Forward"),
"forward", 0,
00179
this, SLOT(
slotForward()),
00180 ac,
"browser_forward");
00181
m_forwardAction->
setEnabled(
false );
00182
m_forwardAction->
setToolTip(i18n(
"Forward"));
00183
m_forwardAction->
setWhatsThis(i18n(
"<b>Forward</b><p>Moves forward one step in the <b>documentation</b> browsing history."));
00184
00185 connect(
m_forwardAction->
popupMenu(), SIGNAL(aboutToShow()),
00186
this, SLOT(
slotForwardAboutToShow()));
00187 connect(
m_forwardAction->
popupMenu(), SIGNAL(activated(
int)),
00188
this, SLOT(
slotForwardPopupActivated(
int)));
00189 }
00190
00191
00192 void PartController::setEncoding(
const QString &encoding)
00193 {
00194
m_presetEncoding = encoding;
00195 }
00196
00197 KParts::Part*
PartController::findOpenDocument(
const KURL& url)
00198 {
00199
KURL partURL =
API::getInstance()->
project() ?
findURLInProject(url) : url;
00200
00201 partURL.
cleanPath();
00202
00203
return partForURL(partURL);
00204 }
00205
00206 KURL PartController::findURLInProject(
const KURL& url)
00207 {
00208
QStringList fileList =
API::getInstance()->
project()->
allFiles();
00209
00210
bool filenameOnly = (url.
url().find(
'/') == -1);
00211
QString filename = filenameOnly ?
"/" :
"";
00212 filename += url.
url();
00213
00214
for (QStringList::Iterator it = fileList.begin(); it != fileList.end(); ++it) {
00215
if ((*it).endsWith(filename)) {
00216
00217
return API::getInstance()->
project()->
projectDirectory() +
"/" + *it;
00218 }
00219 }
00220
00221
return url;
00222 }
00223
00224 void PartController::editDocument(
const KURL &inputUrl,
int lineNum,
int col)
00225 {
00226
kdDebug(9000) <<
k_funcinfo << inputUrl.
prettyURL() <<
" linenum " << lineNum <<
endl;
00227
00228
KURL url = inputUrl;
00229
bool localUrl = url.
url().startsWith(
"file:/");
00230
00231
00232
00233
#ifdef OLD__KDE
00234
if (!url.
isValid() || (localUrl ? !
QFile(url.
path()).exists() : !KIO::NetAccess::exists(url))) {
00235
#else
00236
if (!url.
isValid() || (localUrl ? !
QFile(url.
path()).exists() : !KIO::NetAccess::exists(url,
false, 0))) {
00237
#endif
00238
00239
KDevProject* project =
API::getInstance()->
project();
00240
00241
if (project) {
00242 url =
findURLInProject(url);
00243
00244 localUrl = url.
url().startsWith(
"file:/");
00245
#ifdef OLD__KDE
00246
if (!url.
isValid() || (localUrl ? !
QFile(url.
path()).exists() : !KIO::NetAccess::exists(url))) {
00247
#else
00248
if (!url.
isValid() || (localUrl ? !
QFile(url.
path()).exists() : !KIO::NetAccess::exists(url,
false, 0))) {
00249
#endif
00250
00251 url = project->
projectDirectory() +
"/" + url.
url();
00252 }
00253 }
00254
00255 localUrl = url.
url().startsWith(
"file:/");
00256
#ifdef OLD__KDE
00257
if (!url.
isValid() || (localUrl ? !
QFile(url.
path()).exists() : !KIO::NetAccess::exists(url))) {
00258
#else
00259
if (!url.
isValid() || (localUrl ? !
QFile(url.
path()).exists() : !KIO::NetAccess::exists(url,
false, 0))) {
00260
#endif
00261
00262
return;
00263 }
00264 }
00265
00266
00267
00268 url.
cleanPath(
true);
00269
if (url.
isLocalFile())
00270 {
00271
QString path = url.
path();
00272 path =
URLUtil::canonicalPath(path);
00273
if ( !path.isEmpty() )
00274 url.
setPath(path);
00275 }
00276
00277
KParts::Part *existingPart =
partForURL(url);
00278
if (existingPart)
00279 {
00280
activatePart(existingPart);
00281
EditorProxy::getInstance()->
setLineNumber(existingPart, lineNum, col);
00282
return;
00283 }
00284
00285
QString preferred, className;
00286
00287
QString mimeType, encoding;
00288
if (
m_presetEncoding.isNull())
00289 mimeType = KMimeType::findByURL(url)->name();
00290
else {
00291 mimeType =
"text/plain";
00292 encoding =
m_presetEncoding;
00293 m_presetEncoding = QString::null;
00294 }
00295
00296
00297
00298
if ( mimeType ==
"application/x-designer" )
00299 {
00300
KService::Ptr preferredApp = KServiceTypeProfile::preferredService( mimeType,
"Application" );
00301
if ( preferredApp && preferredApp->desktopEntryName() ==
"designer" )
00302 {
00303 KRun::runURL(url, mimeType);
00304
return;
00305 }
00306 }
00307
00308
kdDebug(9000) <<
"mimeType = " << mimeType <<
endl;
00309
00310
if ( mimeType.startsWith(
"text/")
00311 || mimeType.startsWith(
"application/x-") && mimeType !=
"application/x-designer"
00312 || mimeType ==
"image/x-xpm")
00313 {
00314 mimeType =
"text/plain";
00315 kapp->config()->setGroup(
"Editor");
00316 preferred = kapp->config()->readPathEntry(
"EmbeddedKTextEditor");
00317 }
else if( mimeType.startsWith(
"inode/") ){
00318
return;
00319 }
00320
00321
KParts::Factory *factory = 0;
00322
00323
00324
00325
00326
QString services[] = {
"KTextEditor/Document",
"KParts/ReadWritePart",
"KParts/ReadOnlyPart"};
00327
QString classnames[] = {
"KTextEditor::Document",
"KParts::ReadWritePart",
"KParts::ReadOnlyPart"};
00328
for (uint i=0; i<3; ++i)
00329 {
00330 factory =
findPartFactory(mimeType, services[i], preferred);
00331
if (factory)
00332 {
00333 className = classnames[i];
00334
break;
00335 }
00336 }
00337
00338
kdDebug(9000) <<
"factory = " << factory <<
endl;
00339
00340
if (factory)
00341 {
00342
00343
00344
00345
00346
if (className ==
"KTextEditor::Document")
00347 className =
"KTextEditor::Editor";
00348
00349
00350
KParts::ReadOnlyPart *part = static_cast<KParts::ReadOnlyPart*>(factory->
createPart(TopLevel::getInstance()->
main(), 0, 0, 0, className.latin1()));
00351
KParts::BrowserExtension *extension = KParts::BrowserExtension::childObject(part);
00352
kdDebug(9000) <<
"Encoding: " << encoding <<
", extension: " << extension <<
endl;
00353
if (extension && !encoding.isNull())
00354 {
00355
KParts::URLArgs args;
00356 args.
serviceType = mimeType +
";" + encoding;
00357 extension->
setURLArgs(args);
00358 }
00359 part->
openURL(url);
00360
00361
bool isTextEditor = className ==
"KTextEditor::Editor";
00362
integratePart(part, url, isTextEditor );
00363
00364
if( isTextEditor )
00365
EditorProxy::getInstance()->
setLineNumber(part, lineNum, col);
00366 }
00367
else
00368 KRun::runURL(url, mimeType);
00369 }
00370
00371
00372 void PartController::showDocument(
const KURL &url,
const QString &context)
00373 {
00374
QString fixedPath = DocumentationPart::resolveEnvVarsInURL(url.
url());
00375
KURL docUrl(fixedPath);
00376
kdDebug(9000) <<
"SHOW: " << docUrl.
url() <<
" context=" << context <<
endl;
00377
00378
if ( docUrl.
isLocalFile() && KMimeType::findByURL(docUrl)->name() !=
"text/html" ) {
00379
00380
00381
editDocument( docUrl );
00382
return;
00383 }
00384
00385
DocumentationPart *part = 0;
00386
00387
if (!context.isEmpty())
00388 part =
findDocPart(context);
00389
00390
if (!part)
00391 {
00392 part =
new DocumentationPart;
00393 part->
setContext(context);
00394
integratePart(part,docUrl);
00395 }
00396
else
00397
activatePart(part);
00398
00399
if( !
m_restoring )
00400
addHistoryEntry(
new HistoryEntry(docUrl, context) );
00401
00402
bool bSuccess = part->
openURL(docUrl);
00403
if (!bSuccess) {
00404
00405 }
00406 }
00407
00408
00409 DocumentationPart *
PartController::findDocPart(
const QString &context)
00410 {
00411
QPtrListIterator<KParts::Part> it(*
parts());
00412
for ( ; it.current(); ++it)
00413 {
00414
DocumentationPart *part = dynamic_cast<DocumentationPart*>(it.current());
00415
if (part && (part->
context() == context))
00416
return part;
00417 }
00418
00419
return 0;
00420 }
00421
00422
00423 KParts::Factory *
PartController::findPartFactory(
const QString &mimeType,
const QString &partType,
const QString &preferredName)
00424 {
00425 KTrader::OfferList offers = KTrader::self()->query(mimeType,
QString(
"'%1' in ServiceTypes").arg(partType));
00426
00427
if (offers.count() > 0)
00428 {
00429
KService::Ptr ptr = 0;
00430
00431
if ( !preferredName.isEmpty() ) {
00432 KTrader::OfferList::Iterator it;
00433
for (it = offers.begin(); it != offers.end(); ++it) {
00434
if ((*it)->name() == preferredName) {
00435 ptr = (*it);
00436 }
00437 }
00438 }
00439
00440
if ( !ptr ) {
00441 ptr = offers.first();
00442 }
00443
return static_cast<KParts::Factory*>(
KLibLoader::self()->
factory(QFile::encodeName(ptr->library())));
00444 }
00445
00446
return 0;
00447 }
00448
00449
00450 void PartController::integratePart(
KParts::Part *part,
const KURL &url,
bool isTextEditor )
00451 {
00452
if (!part->
widget()) {
00454
kdDebug(9000) <<
"no widget for this part!!" <<
endl;
00455
return;
00456 }
00457
00458
TopLevel::getInstance()->
embedPartView(part->
widget(), url.
filename(), url.
url());
00459
savePartWidgetIcon(part);
00460
00461 addPart(part);
00462
00463
if( isTextEditor ){
00464
EditorProxy::getInstance()->
installPopup(part,
contextPopupMenu());
00465
00466
#if KDE_VERSION < 310
00467
00468
00469 connect(part, SIGNAL(fileNameChanged()),
this, SLOT(
slotUploadFinished()));
00470
#endif
00471
}
00472
00473
00474
KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(part);
00475
if (ro_part && ro_part->
url().
isLocalFile()) {
00476
00477
dirWatcher->
addFile( url.
path() );
00478
accessTimeMap[ ro_part ] =
dirWatcher->
ctime( url.
path() );
00479 emit loadedFile(ro_part->
url().
path());
00480 }
00481
00482
00483 connect(part, SIGNAL(completed()),
this, SLOT(
slotUploadFinished()));
00484 connect(part, SIGNAL(completed()),
this, SLOT(
slotRestoreStatus()));
00485
00486
00487
00488 connect(part, SIGNAL(fileNameChanged()),
this, SLOT(
slotFileNameChanged()));
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
if (isTextEditor)
00500 {
00501
KTextEditor::Document * doc = static_cast<KTextEditor::Document*>( part );
00502
QPtrList<KTextEditor::View> list = doc->
views();
00503
QPtrListIterator<KTextEditor::View> it( list );
00504
while ( it.current() )
00505 {
00506 connect( it, SIGNAL( newStatus() ),
this, SLOT(
slotNewStatus() ) );
00507 ++it;
00508 }
00509 }
00510 }
00511
00512 void PartController::reinstallPopups( ){
00513
00514
EditorProxy* editorProxy =
EditorProxy::getInstance();
00515
QPopupMenu* popup =
contextPopupMenu();
00516
00517
QPtrListIterator<KParts::Part> it(*
parts());
00518
for ( ; it.current(); ++it)
00519 editorProxy->
installPopup( it.current(), popup,
true );
00520 }
00521
00522 void PartController::slotUploadFinished()
00523 {
00524
const KParts::ReadOnlyPart *ro_part = dynamic_cast<const KParts::ReadOnlyPart*>(sender());
00525
00526
if (!ro_part || !ro_part->
url().
isLocalFile())
00527
return;
00528
00529
QString path = ro_part->
url().
path();
00530
00531
QFileInfo fi( path );
00532
00533
accessTimeMap[ ro_part ] = fi.lastModified();
00534 emit savedFile( path );
00535 }
00536
00537 void PartController::slotFileNameChanged()
00538 {
00539
const KParts::ReadOnlyPart *ro_part = dynamic_cast<const KParts::ReadOnlyPart*>(sender());
00540
00541
if ( !ro_part || !ro_part->
url().
isLocalFile() )
00542
return;
00543
00544 emit
partURLChanged( const_cast<KParts::ReadOnlyPart*>(ro_part) );
00545
00546
QString path = ro_part->url().path();
00547
accessTimeMap[ ro_part ] =
dirWatcher->
ctime( path );
00548 emit fileDirty( ro_part->url() );
00549 }
00550
00551 QPopupMenu *
PartController::contextPopupMenu()
00552 {
00553
QPopupMenu * popup = (
QPopupMenu*)(
TopLevel::getInstance()->
main())->factory()->container(
"rb_popup", TopLevel::getInstance()->
main());
00554
00555
kdDebug( 9000 ) <<
"PartController::contextPopupMenu() will return " << popup <<
endl;
00556
00557
return popup;
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 KParts::Part *
PartController::partForURL(
const KURL &url)
00578 {
00579
QPtrListIterator<KParts::Part> it(*
parts());
00580
for ( ; it.current(); ++it)
00581 {
00582
KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(it.current());
00583
if (ro_part && url == ro_part->
url())
00584
return ro_part;
00585 }
00586
00587
return 0;
00588 }
00589
00590
00591 void PartController::activatePart(
KParts::Part *part)
00592 {
00593 setActivePart(part);
00594
00595
if (part->
widget())
00596 {
00597
TopLevel::getInstance()->
raiseView(part->
widget());
00598 part->
widget()->setFocus();
00599 }
00600 }
00601
00602
00603 void PartController::closeActivePart()
00604 {
00605
if (!
activePart())
00606
return;
00607
00608
closePart(
activePart());
00609 }
00610
00611
00612 bool PartController::closePart(
KParts::Part *part)
00613 {
00614
if (part->inherits(
"KParts::ReadOnlyPart"))
00615 {
00616
KParts::ReadOnlyPart *ro_part = static_cast<KParts::ReadOnlyPart*>(part);
00617
00618
if (!ro_part->
closeURL())
00619 {
00620
return false;
00621 }
00622 }
00623
partWidgetIcons.remove(part);
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 removePart( part );
00639
00640
if (part->
widget())
00641
TopLevel::getInstance()->
removeView(part->
widget());
00642
00643
delete part;
00644
00645
return true;
00646 }
00647
00648
00649 void PartController::updateMenuItems()
00650 {
00651
bool hasWriteParts =
false;
00652
bool hasReadOnlyParts =
false;
00653
00654
QPtrListIterator<KParts::Part> it(*
parts());
00655
for ( ; it.current(); ++it)
00656 {
00657
if (it.current()->inherits(
"KParts::ReadWritePart"))
00658 hasWriteParts =
true;
00659
if (it.current()->inherits(
"KParts::ReadOnlyPart"))
00660 hasReadOnlyParts =
true;
00661 }
00662
00663
m_saveAllFilesAction->
setEnabled(hasWriteParts);
00664
m_revertAllFilesAction->
setEnabled(hasWriteParts);
00665
m_closeWindowAction->
setEnabled(hasReadOnlyParts);
00666
m_closeAllWindowsAction->
setEnabled(hasReadOnlyParts);
00667
m_closeOtherWindowsAction->
setEnabled(hasReadOnlyParts);
00668
00669
m_backAction->
setEnabled(
m_history.current() !=
m_history.getFirst());
00670
m_forwardAction->
setEnabled(
m_history.current() !=
m_history.getLast());
00671 }
00672
00673
00674 void PartController::slotSaveAllFiles()
00675 {
00676
saveAllFiles();
00677 }
00678
00679
00680 void PartController::saveFile(
KParts::Part *part)
00681 {
00682
KParts::ReadWritePart *rw_part = dynamic_cast<KParts::ReadWritePart*>(part);
00683
if ( !rw_part )
00684
return;
00685
if (
isDirty( rw_part ) ) {
00686
kdDebug(9000) <<
"DIRTY SAVE" <<
endl;
00687 }
00688
00689
if( rw_part->
isModified() ) {
00690 rw_part->
save();
00691
TopLevel::getInstance()->
statusBar()->message(i18n(
"Saved %1").arg(rw_part->
url().
prettyURL()), 2000);
00692 }
00693 }
00694
00695 void PartController::saveAllFiles()
00696 {
00697
QPtrListIterator<KParts::Part> it(*
parts());
00698
for ( ; it.current(); ++it)
00699
saveFile( it.current() );
00700 }
00701
00702
00703 void PartController::slotRevertAllFiles()
00704 {
00705
revertAllFiles();
00706 }
00707
00708 void PartController::revertFile(
KParts::Part *part)
00709 {
00710
if ( !part )
00711
return;
00712
00713
if (part->inherits(
"KParts::ReadWritePart")) {
00714
KParts::ReadWritePart *rw_part = static_cast<KParts::ReadWritePart*>(part);
00715
if ( rw_part->
url().
isLocalFile() )
00716
accessTimeMap[ static_cast<KParts::ReadOnlyPart*>(part) ] =
dirWatcher->
ctime( rw_part->
url().
path() );
00717 rw_part->
openURL(rw_part->
url());
00718 }
00719 }
00720
00721 void PartController::revertAllFiles()
00722 {
00723
QPtrListIterator<KParts::Part> it(*
parts());
00724
for ( ; it.current(); ++it)
00725
revertFile( it.current() );
00726 }
00727
00728
00729 void PartController::slotCloseWindow()
00730 {
00731
closeActivePart();
00732 }
00733
00734 KURL::List PartController::modifiedDocuments()
00735 {
00736
KURL::List modFiles;
00737
00738
QPtrListIterator<KParts::Part> it( *
parts() );
00739
while( it.current() )
00740 {
00741
KParts::ReadWritePart *rw_part = dynamic_cast<KParts::ReadWritePart*>(it.current());
00742
if ( rw_part && rw_part->
isModified() )
00743 {
00744 modFiles << rw_part->
url();
00745 }
00746 ++it;
00747 }
00748
return modFiles;
00749 }
00750
00751 void PartController::saveFiles(
KURL::List const & filelist )
00752 {
00753 KURL::List::ConstIterator it = filelist.begin();
00754
while ( it != filelist.end() )
00755 {
00756
KParts::ReadWritePart * rw_part = dynamic_cast<KParts::ReadWritePart*>(
partForURL( *it ) );
00757
if ( rw_part )
00758 {
00759 rw_part->
save();
00760 }
00761 ++it;
00762 }
00763 }
00764
00765 void PartController::clearModified(
KURL::List const & filelist )
00766 {
00767 KURL::List::ConstIterator it = filelist.begin();
00768
while ( it != filelist.end() )
00769 {
00770
KParts::ReadWritePart * rw_part = dynamic_cast<KParts::ReadWritePart*>(
partForURL( *it ) );
00771
if ( rw_part )
00772 {
00773 rw_part->
setModified(
false );
00774 }
00775 ++it;
00776 }
00777 }
00778
00779 bool PartController::closeWindows(
KURL::List const & ignoreList )
00780 {
00781
KURL::List modList =
modifiedDocuments();
00782
00783
if ( modList.count() > 0 && modList != ignoreList )
00784 {
00785
KSaveSelectDialog dlg( modList, ignoreList, TopLevel::getInstance()->
main() );
00786
if ( dlg.exec() == QDialog::Accepted )
00787 {
00788
saveFiles( dlg.
filesToSave() );
00789
clearModified( dlg.
filesNotToSave() );
00790 }
00791
else
00792 {
00793
return false;
00794 }
00795 }
00796
00797
QPtrList<KParts::Part> partList( *
parts() );
00798
QPtrListIterator<KParts::Part> it( partList );
00799
while (
KParts::Part* part = it.current() )
00800 {
00801
KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart*>( part );
00802
if ( ro_part && !ignoreList.contains( ro_part->
url() ) || !ro_part )
00803 {
00804
closePart( part );
00805 }
00806 ++it;
00807 }
00808
00809
return true;
00810 }
00811
00812 bool PartController::closeAllWindows()
00813 {
00814
return closeWindows(
KURL::List() );
00815 }
00816
00817 void PartController::slotCloseAllWindows()
00818 {
00819
closeAllWindows();
00820 }
00821
00822 void PartController::slotCloseOtherWindows()
00823 {
00824
KParts::ReadOnlyPart * active = dynamic_cast<KParts::ReadOnlyPart*>(
activePart());
00825
if ( !active )
return;
00826
00827
KURL::List ignoreList;
00828 ignoreList.append( active->
url() );
00829
00830
closeWindows( ignoreList );
00831 }
00832
00833 void PartController::slotCurrentChanged(
QWidget *w)
00834 {
00835
00836
kdDebug()<<
"slotCurrentChanged***********************************+"<<
endl;
00837
QPtrListIterator<KParts::Part> it(*
parts());
00838
for ( ; it.current(); ++it)
00839
if (it.current()->widget() == w)
00840 {
00841
kdDebug()<<
"found it**************************************"<<
endl;
00842 setActivePart(it.current(), w);
00843
break;
00844 }
00845 }
00846
00847 void PartController::slotOpenFile()
00848 {
00849
KURL::List fileNames = KFileDialog::getOpenURLs(QString::null, QString::null, TopLevel::getInstance()->
main(), QString::null);
00850
00851
for ( KURL::List::Iterator it = fileNames.begin(); it != fileNames.end(); ++it )
00852 {
00853
editDocument( *it );
00854
m_openRecentAction->
addURL( *it );
00855 }
00856
m_openRecentAction->
saveEntries( kapp->config(),
"RecentFiles" );
00857 }
00858
00859 void PartController::slotOpenRecent(
const KURL& url )
00860 {
00861
editDocument( url );
00862
00863
m_openRecentAction->
setCurrentItem( -1 );
00864 }
00865
00866 void PartController::slotClosePartForWidget(
const QWidget* w)
00867 {
00868
closePartForWidget(w);
00869 }
00870
00871 bool PartController::closePartForWidget(
const QWidget* w )
00872 {
00873
QPtrListIterator<KParts::Part> it(*
parts());
00874
for ( ; it.current(); ++it)
00875
if (it.current()->widget() == w)
00876 {
00877
return closePart( *it );
00878 }
00879
return true;
00880 }
00881
00882 bool PartController::readyToClose()
00883 {
00884
return closeAllWindows();
00885 }
00886
00887 void PartController::slotActivePartChanged(
KParts::Part* part )
00888 {
00889
updateMenuItems();
00890
if( !part ||
QString(part->name()) !=
"DocumentationPart" ){
00891
m_backAction->
setEnabled(
false );
00892
m_forwardAction->
setEnabled(
false );
00893 }
00894 }
00895
00896 void PartController::slotSwitchTo()
00897 {
00898
QMap<QString,KParts::ReadOnlyPart*> parts_map;
00899
QStringList part_list;
00900
QPtrList<KParts::Part> pl = *
parts();
00901
KParts::Part *part;
00902
for(part=pl.first();part;part=pl.next()) {
00903
kdDebug(9000) <<
"Part..." <<
endl;
00904
if (part->inherits(
"KParts::ReadOnlyPart")) {
00905
KParts::ReadOnlyPart *ro_part = static_cast<KParts::ReadOnlyPart*>(part);
00906
QString name = ro_part->
url().
fileName();
00907 part_list.append(name);
00908 parts_map[name] = ro_part;
00909
kdDebug(9000) <<
"Found part for URL " << ro_part->url().prettyURL() <<
endl;
00910 }
00911 }
00912
00913
KDialogBase dialog(KDialogBase::Plain, i18n(
"Switch To..."), KDialogBase::Ok|KDialogBase::Cancel,
00914 KDialogBase::Ok, 0,
"Switch to",
true);
00915
QGridLayout *grid =
new QGridLayout( dialog.
plainPage(), 2, 1, 10, 10);
00916
KLineEdit *editbox =
new KLineEdit(dialog.
plainPage());
00917 grid->addWidget(
new QLabel( i18n(
"Switch to buffer:"), dialog.
plainPage() ), 0, 0);
00918 grid->addWidget(editbox, 1, 0);
00919 editbox->
completionObject()->
setItems( part_list );
00920 editbox->setFocus();
00921
int result = dialog.exec();
00922
if (result==KDialogBase::KDialogBase::Accepted) {
00923
if (parts_map.contains(editbox->text())) {
00924
activatePart(parts_map[editbox->text()]);
00925 }
00926 }
00927 }
00928
00929 void PartController::slotBack()
00930 {
00931
saveState(
activePart());
00932
00933
if(
m_history.prev()==0L)
m_history.first();
00934
00935
restoreState();
00936 }
00937
00938 void PartController::slotForward()
00939 {
00940
saveState(
activePart());
00941
00942
if(
m_history.next()==0L)
m_history.last();
00943
00944
restoreState();
00945 }
00946
00947 void PartController::slotBackAboutToShow()
00948 {
00949
KPopupMenu *popup =
m_backAction->
popupMenu();
00950 popup->clear();
00951
00952
int savePos =
m_history.at();
00953
for (
int i=0; i<10 &&
m_history.prev(); ++i)
00954 popup->insertItem(
m_history.current()->url.url() );
00955
00956
m_history.at(savePos);
00957 }
00958
00959 void PartController::slotBackPopupActivated(
int id )
00960 {
00961
int by =
m_backAction->
popupMenu()->indexOf(
id)+1;
00962
00963
saveState(
activePart());
00964
for (
int i=0; i < by; ++i)
00965
m_history.prev();
00966
if(
m_history.prev()==0L)
m_history.first();
00967
00968
restoreState();
00969
00970
updateMenuItems();
00971 }
00972
00973 void PartController::slotForwardAboutToShow()
00974 {
00975
KPopupMenu *popup =
m_forwardAction->
popupMenu();
00976 popup->clear();
00977
00978
int savePos =
m_history.at();
00979
for (
int i=0; i<10 &&
m_history.next(); ++i)
00980 popup->insertItem(
m_history.current()->url.url());
00981
00982
m_history.at(savePos);
00983 }
00984
00985 void PartController::slotForwardPopupActivated(
int id )
00986 {
00987
int by =
m_forwardAction->
popupMenu()->indexOf(
id)+1;
00988
00989
saveState(
activePart());
00990
for (
int i=0; i < by; ++i)
00991
m_history.next();
00992
if(
m_history.current()==0L)
m_history.last();
00993
00994
restoreState();
00995
00996
updateMenuItems();
00997 }
00998
00999 void PartController::addHistoryEntry(
HistoryEntry* entry )
01000 {
01001
HistoryEntry *current =
m_history.current();
01002
while (
m_history.getLast() != current)
01003
m_history.removeLast();
01004
m_history.append( entry );
01005
m_history.last();
01006
01007
updateMenuItems();
01008 }
01009
01010 void PartController::saveState(
KParts::Part* part )
01011 {
01012
DocumentationPart* d = dynamic_cast<DocumentationPart*>( part );
01013
if( !d )
01014
return;
01015
01016
HistoryEntry *entry =
m_history.current();
01017
if (!entry)
01018
return;
01019
01020 entry->
url = d->
url();
01021 }
01022
01023
01024 void PartController::restoreState()
01025 {
01026
HistoryEntry *entry =
m_history.current();
01027
if (!entry)
01028
return;
01029
01030
m_restoring =
true;
01031
showDocument( entry->
url, entry->
context );
01032
m_restoring =
false;
01033
updateMenuItems();
01034 }
01035
01036 void PartController::showPart(
KParts::Part* part,
const QString& name,
const QString& shortDescription )
01037 {
01038
if (!part->
widget()) {
01040
return;
01041 }
01042
01043
QPtrListIterator<KParts::Part> it(*
parts());
01044
for ( ; it.current(); ++it)
01045 {
01046
if( it.current() == part ){
01047
01048
activatePart( it.current() );
01049
return;
01050 }
01051 }
01052
01053
01054
TopLevel::getInstance()->
embedPartView( part->
widget(), name, shortDescription );
01055
savePartWidgetIcon(part);
01056 addPart( part );
01057 }
01058
01059 void PartController::dirty(
const QString& fileName )
01060 {
01061
01062 emit fileDirty(
KURL( fileName ) );
01063 }
01064
01065 bool PartController::isDirty(
KParts::ReadOnlyPart* part )
01066 {
01067
if ( !part || !part->
url().
isLocalFile() )
01068
return false;
01069
01070
01071
01072
if (
accessTimeMap.contains( part ) )
01073
return (
accessTimeMap[ part ] <
dirWatcher->
ctime( part->
url().
path() ) );
01074
01075
accessTimeMap[ part ] =
dirWatcher->
ctime( part->
url().
path() );
01076
return false;
01077 }
01078
01079 void PartController::savePartWidgetIcon(
KParts::Part * part )
01080 {
01081
if ((!part->
widget()) || (!part->
widget()->icon()))
01082
return;
01083
QPixmap m(*(part->
widget()->icon()));
01084
partWidgetIcons[part] = m;
01085 }
01086
01087 void PartController::restorePartWidgetIcon(
KParts::Part * part )
01088 {
01089
if (!part->
widget())
01090
return;
01091
if (
partWidgetIcons.contains(part))
01092 part->
widget()->setIcon(
partWidgetIcons[part]);
01093 }
01094
01095 void PartController::slotNewStatus( )
01096 {
01097
kdDebug(9000) <<
"PartController::slotNewStatus()" <<
endl;
01098
01099
QObject * senderobj = const_cast<QObject*>( sender() );
01100
KTextEditor::View * view = dynamic_cast<KTextEditor::View*>( senderobj );
01101
01102
if ( view )
01103 {
01104
KParts::ReadWritePart * rw_part = view->
document();
01105
if (
isDirty( rw_part ) ) {
01106 }
else if ( rw_part->
isModified() ) {
01107 rw_part->
widget()->setIcon(SmallIcon(
"filesave"));
01108 }
else {
01109
restorePartWidgetIcon(rw_part);
01110 }
01111 }
01112 }
01113
01114 void PartController::slotRestoreStatus( )
01115 {
01116
KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(const_cast<QObject*>(sender()));
01117
01118
if ( !ro_part )
01119
return;
01120
01121
if (!
isDirty(ro_part))
01122
restorePartWidgetIcon(ro_part);
01123 }
01124
01125 void PartController::slotFileDirty(
const KURL & url )
01126 {
01127
kdDebug(9000) <<
k_funcinfo <<
endl;
01128
01129
KParts::ReadWritePart * rw_part = dynamic_cast<KParts::ReadWritePart*>(
partForURL( url ) );
01130
if ( !rw_part || !rw_part->
widget() )
return;
01131
01132
if (
isDirty( rw_part ) )
01133 {
01134 rw_part->
widget()->setIcon( SmallIcon(
"revert") );
01135 }
01136
else if ( !rw_part->
isModified() )
01137 {
01138 rw_part->
widget()->setIcon( SmallIcon(
"kdevelop") );
01139 }
01140
else
01141 {
01142 rw_part->
widget()->setIcon( SmallIcon(
"filesave") );
01143 }
01144 }
01145
01146
#include "partcontroller.moc"