kparts Library API Documentation

browserextension.cpp

00001 /* This file is part of the KDE project 00002 Copyright (C) 1999 Simon Hausmann <hausmann@kde.org> 00003 (C) 1999 David Faure <faure@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 #include "browserextension.h" 00021 00022 #include <qapplication.h> 00023 #include <qclipboard.h> 00024 #include <qtimer.h> 00025 #include <qobjectlist.h> 00026 #include <qmetaobject.h> 00027 #include <qregexp.h> 00028 #include <qstrlist.h> 00029 #include <qstylesheet.h> 00030 00031 #include <kdebug.h> 00032 #include <klocale.h> 00033 #include <kmessagebox.h> 00034 #include <kstaticdeleter.h> 00035 #include <kurifilter.h> 00036 #include <assert.h> 00037 00038 using namespace KParts; 00039 00040 const char *OpenURLEvent::s_strOpenURLEvent = "KParts/BrowserExtension/OpenURLevent"; 00041 00042 class OpenURLEvent::OpenURLEventPrivate 00043 { 00044 public: 00045 OpenURLEventPrivate() 00046 { 00047 } 00048 ~OpenURLEventPrivate() 00049 { 00050 } 00051 }; 00052 00053 OpenURLEvent::OpenURLEvent( ReadOnlyPart *part, const KURL &url, const URLArgs &args ) 00054 : Event( s_strOpenURLEvent ), m_part( part ), m_url( url ), m_args( args ) 00055 { 00056 // d = new OpenURLEventPrivate(); 00057 } 00058 00059 OpenURLEvent::~OpenURLEvent() 00060 { 00061 // delete d; 00062 } 00063 00064 namespace KParts 00065 { 00066 00067 struct URLArgsPrivate 00068 { 00069 URLArgsPrivate() { 00070 doPost = false; 00071 redirectedRequest = false; 00072 lockHistory = false; 00073 newTab = false; 00074 forcesNewWindow = false; 00075 } 00076 QString contentType; // for POST 00077 QMap<QString, QString> metaData; 00078 bool doPost; 00079 bool redirectedRequest; 00080 bool lockHistory; 00081 bool newTab; 00082 bool forcesNewWindow; 00083 }; 00084 00085 } 00086 00087 URLArgs::URLArgs() 00088 { 00089 reload = false; 00090 xOffset = 0; 00091 yOffset = 0; 00092 trustedSource = false; 00093 d = 0L; // Let's build it on demand for now 00094 } 00095 00096 00097 URLArgs::URLArgs( bool _reload, int _xOffset, int _yOffset, const QString &_serviceType ) 00098 { 00099 reload = _reload; 00100 xOffset = _xOffset; 00101 yOffset = _yOffset; 00102 serviceType = _serviceType; 00103 d = 0L; // Let's build it on demand for now 00104 } 00105 00106 URLArgs::URLArgs( const URLArgs &args ) 00107 { 00108 d = 0L; 00109 (*this) = args; 00110 } 00111 00112 URLArgs &URLArgs::operator=(const URLArgs &args) 00113 { 00114 if (this == &args) return *this; 00115 00116 delete d; d= 0; 00117 00118 reload = args.reload; 00119 xOffset = args.xOffset; 00120 yOffset = args.yOffset; 00121 serviceType = args.serviceType; 00122 postData = args.postData; 00123 frameName = args.frameName; 00124 docState = args.docState; 00125 trustedSource = args.trustedSource; 00126 00127 if ( args.d ) 00128 d = new URLArgsPrivate( * args.d ); 00129 00130 return *this; 00131 } 00132 00133 URLArgs::~URLArgs() 00134 { 00135 delete d; 00136 d = 0; 00137 } 00138 00139 void URLArgs::setContentType( const QString & contentType ) 00140 { 00141 if (!d) 00142 d = new URLArgsPrivate; 00143 d->contentType = contentType; 00144 } 00145 00146 void URLArgs::setRedirectedRequest( bool redirected ) 00147 { 00148 if (!d) 00149 d = new URLArgsPrivate; 00150 d->redirectedRequest = redirected; 00151 } 00152 00153 bool URLArgs::redirectedRequest () const 00154 { 00155 return d ? d->redirectedRequest : false; 00156 } 00157 00158 QString URLArgs::contentType() const 00159 { 00160 return d ? d->contentType : QString::null; 00161 } 00162 00163 QMap<QString, QString> &URLArgs::metaData() 00164 { 00165 if (!d) 00166 d = new URLArgsPrivate; 00167 return d->metaData; 00168 } 00169 00170 void URLArgs::setDoPost( bool enable ) 00171 { 00172 if ( !d ) 00173 d = new URLArgsPrivate; 00174 d->doPost = enable; 00175 } 00176 00177 bool URLArgs::doPost() const 00178 { 00179 return d ? d->doPost : false; 00180 } 00181 00182 void URLArgs::setLockHistory( bool lock ) 00183 { 00184 if (!d) 00185 d = new URLArgsPrivate; 00186 d->lockHistory = lock; 00187 } 00188 00189 bool URLArgs::lockHistory() const 00190 { 00191 return d ? d->lockHistory : false; 00192 } 00193 00194 void URLArgs::setNewTab( bool newTab ) 00195 { 00196 if (!d) 00197 d = new URLArgsPrivate; 00198 d->newTab = newTab; 00199 } 00200 00201 bool URLArgs::newTab() const 00202 { 00203 return d ? d->newTab : false; 00204 } 00205 00206 void URLArgs::setForcesNewWindow( bool forcesNewWindow ) 00207 { 00208 if (!d) 00209 d = new URLArgsPrivate; 00210 d->forcesNewWindow = forcesNewWindow; 00211 } 00212 00213 bool URLArgs::forcesNewWindow() const 00214 { 00215 return d ? d->forcesNewWindow : false; 00216 } 00217 00218 namespace KParts 00219 { 00220 00221 struct WindowArgsPrivate 00222 { 00223 }; 00224 00225 } 00226 00227 WindowArgs::WindowArgs() 00228 { 00229 x = y = width = height = -1; 00230 fullscreen = false; 00231 menuBarVisible = true; 00232 toolBarsVisible = true; 00233 statusBarVisible = true; 00234 resizable = true; 00235 lowerWindow = false; 00236 d = 0; 00237 } 00238 00239 WindowArgs::WindowArgs( const WindowArgs &args ) 00240 { 00241 d = 0; 00242 (*this) = args; 00243 } 00244 00245 WindowArgs &WindowArgs::operator=( const WindowArgs &args ) 00246 { 00247 if ( this == &args ) return *this; 00248 00249 delete d; d = 0; 00250 00251 x = args.x; 00252 y = args.y; 00253 width = args.width; 00254 height = args.height; 00255 fullscreen = args.fullscreen; 00256 menuBarVisible = args.menuBarVisible; 00257 toolBarsVisible = args.toolBarsVisible; 00258 statusBarVisible = args.statusBarVisible; 00259 resizable = args.resizable; 00260 lowerWindow = args.lowerWindow; 00261 00262 /* 00263 if ( args.d ) 00264 { 00265 [ ... ] 00266 } 00267 */ 00268 00269 return *this; 00270 } 00271 00272 WindowArgs::WindowArgs( const QRect &_geometry, bool _fullscreen, bool _menuBarVisible, 00273 bool _toolBarsVisible, bool _statusBarVisible, bool _resizable ) 00274 { 00275 d = 0; 00276 x = _geometry.x(); 00277 y = _geometry.y(); 00278 width = _geometry.width(); 00279 height = _geometry.height(); 00280 fullscreen = _fullscreen; 00281 menuBarVisible = _menuBarVisible; 00282 toolBarsVisible = _toolBarsVisible; 00283 statusBarVisible = _statusBarVisible; 00284 resizable = _resizable; 00285 lowerWindow = false; 00286 } 00287 00288 WindowArgs::WindowArgs( int _x, int _y, int _width, int _height, bool _fullscreen, 00289 bool _menuBarVisible, bool _toolBarsVisible, 00290 bool _statusBarVisible, bool _resizable ) 00291 { 00292 d = 0; 00293 x = _x; 00294 y = _y; 00295 width = _width; 00296 height = _height; 00297 fullscreen = _fullscreen; 00298 menuBarVisible = _menuBarVisible; 00299 toolBarsVisible = _toolBarsVisible; 00300 statusBarVisible = _statusBarVisible; 00301 resizable = _resizable; 00302 lowerWindow = false; 00303 } 00304 00305 namespace KParts 00306 { 00307 00308 // Internal class, use to store the status of the actions 00309 class KBitArray 00310 { 00311 public: 00312 int val; 00313 KBitArray() { val = 0; } 00314 bool operator [](int index) { return (val & (1 << index)) ? true : false; } 00315 void setBit(int index, bool value) { 00316 if (value) val = val | (1 << index); 00317 else val = val & ~(1 << index); 00318 } 00319 }; 00320 00321 class BrowserExtensionPrivate 00322 { 00323 public: 00324 BrowserExtensionPrivate() 00325 { 00326 m_browserInterface = 0; 00327 } 00328 ~BrowserExtensionPrivate() 00329 { 00330 } 00331 00332 struct DelayedRequest { 00333 KURL m_delayedURL; 00334 KParts::URLArgs m_delayedArgs; 00335 }; 00336 QValueList<DelayedRequest> m_requests; 00337 bool m_urlDropHandlingEnabled; 00338 KBitArray m_actionStatus; 00339 BrowserInterface *m_browserInterface; 00340 }; 00341 00342 } 00343 00344 BrowserExtension::ActionSlotMap * BrowserExtension::s_actionSlotMap = 0L; 00345 static KStaticDeleter<BrowserExtension::ActionSlotMap> actionSlotMapsd; 00346 BrowserExtension::ActionNumberMap * BrowserExtension::s_actionNumberMap = 0L; 00347 static KStaticDeleter<BrowserExtension::ActionNumberMap> actionNumberMapsd; 00348 00349 BrowserExtension::BrowserExtension( KParts::ReadOnlyPart *parent, 00350 const char *name ) 00351 : QObject( parent, name), m_part( parent ) 00352 { 00353 //kdDebug() << "BrowserExtension::BrowserExtension() " << this << endl; 00354 d = new BrowserExtensionPrivate; 00355 d->m_urlDropHandlingEnabled = false; 00356 00357 if ( !s_actionSlotMap ) 00358 // Create the action-slot map 00359 createActionSlotMap(); 00360 00361 // Set the initial status of the actions depending on whether 00362 // they're supported or not 00363 ActionSlotMap::ConstIterator it = s_actionSlotMap->begin(); 00364 ActionSlotMap::ConstIterator itEnd = s_actionSlotMap->end(); 00365 QStrList slotNames = metaObject()->slotNames(); 00366 for ( int i=0 ; it != itEnd ; ++it, ++i ) 00367 { 00368 // Does the extension have a slot with the name of this action ? 00369 d->m_actionStatus.setBit( i, slotNames.contains( it.key()+"()" ) ); 00370 } 00371 00372 connect( m_part, SIGNAL( completed() ), 00373 this, SLOT( slotCompleted() ) ); 00374 connect( this, SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ), 00375 this, SLOT( slotOpenURLRequest( const KURL &, const KParts::URLArgs & ) ) ); 00376 connect( this, SIGNAL( enableAction( const char *, bool ) ), 00377 this, SLOT( slotEnableAction( const char *, bool ) ) ); 00378 } 00379 00380 BrowserExtension::~BrowserExtension() 00381 { 00382 //kdDebug() << "BrowserExtension::~BrowserExtension() " << this << endl; 00383 delete d; 00384 } 00385 00386 void BrowserExtension::setURLArgs( const URLArgs &args ) 00387 { 00388 m_args = args; 00389 } 00390 00391 URLArgs BrowserExtension::urlArgs() const 00392 { 00393 return m_args; 00394 } 00395 00396 int BrowserExtension::xOffset() 00397 { 00398 return 0; 00399 } 00400 00401 int BrowserExtension::yOffset() 00402 { 00403 return 0; 00404 } 00405 00406 void BrowserExtension::saveState( QDataStream &stream ) 00407 { 00408 stream << m_part->url() << (Q_INT32)xOffset() << (Q_INT32)yOffset(); 00409 } 00410 00411 void BrowserExtension::restoreState( QDataStream &stream ) 00412 { 00413 KURL u; 00414 Q_INT32 xOfs, yOfs; 00415 stream >> u >> xOfs >> yOfs; 00416 00417 URLArgs args( urlArgs() ); 00418 args.xOffset = xOfs; 00419 args.yOffset = yOfs; 00420 00421 setURLArgs( args ); 00422 00423 m_part->openURL( u ); 00424 } 00425 00426 bool BrowserExtension::isURLDropHandlingEnabled() const 00427 { 00428 return d->m_urlDropHandlingEnabled; 00429 } 00430 00431 void BrowserExtension::setURLDropHandlingEnabled( bool enable ) 00432 { 00433 d->m_urlDropHandlingEnabled = enable; 00434 } 00435 00436 void BrowserExtension::slotCompleted() 00437 { 00438 //empty the argument stuff, to avoid bogus/invalid values when opening a new url 00439 setURLArgs( URLArgs() ); 00440 } 00441 00442 void BrowserExtension::pasteRequest() 00443 { 00444 QCString plain("plain"); 00445 QString url = QApplication::clipboard()->text(plain, QClipboard::Selection).stripWhiteSpace(); 00446 // Remove linefeeds and any whitespace surrounding it. 00447 url.replace(QRegExp("[\\ ]*\\n+[\\ ]*"),""); 00448 00449 // Check if it's a URL 00450 QStringList filters = KURIFilter::self()->pluginNames(); 00451 filters.remove( "kuriikwsfilter" ); 00452 filters.remove( "localdomainurifilter" ); 00453 KURIFilterData filterData; 00454 filterData.setData( url ); 00455 filterData.setCheckForExecutables( false ); 00456 if ( KURIFilter::self()->filterURI( filterData, filters ) ) 00457 { 00458 switch ( filterData.uriType() ) 00459 { 00460 case KURIFilterData::LOCAL_FILE: 00461 case KURIFilterData::LOCAL_DIR: 00462 case KURIFilterData::NET_PROTOCOL: 00463 slotOpenURLRequest( filterData.uri(), KParts::URLArgs() ); 00464 break; 00465 case KURIFilterData::ERROR: 00466 KMessageBox::sorry( m_part->widget(), filterData.errorMsg() ); 00467 break; 00468 default: 00469 break; 00470 } 00471 } 00472 else if ( KURIFilter::self()->filterURI( filterData, "kuriikwsfilter" ) && url.length() < 250 ) 00473 { 00474 if ( KMessageBox::questionYesNo( m_part->widget(), 00475 i18n( "<qt>Do you want to search the Internet for <b>%1</b>?" ).arg( QStyleSheet::escape(url) ), 00476 i18n( "Internet Search" ), KGuiItem( i18n( "&Search" ), "find"), 00477 KStdGuiItem::cancel(), "MiddleClickSearch" ) == KMessageBox::Yes) 00478 slotOpenURLRequest( filterData.uri(), KParts::URLArgs() ); 00479 } 00480 } 00481 00482 void BrowserExtension::slotOpenURLRequest( const KURL &url, const KParts::URLArgs &args ) 00483 { 00484 //kdDebug() << this << " BrowserExtension::slotOpenURLRequest(): url=" << url.url() << endl; 00485 BrowserExtensionPrivate::DelayedRequest req; 00486 req.m_delayedURL = url; 00487 req.m_delayedArgs = args; 00488 d->m_requests.append( req ); 00489 QTimer::singleShot( 0, this, SLOT( slotEmitOpenURLRequestDelayed() ) ); 00490 } 00491 00492 void BrowserExtension::slotEmitOpenURLRequestDelayed() 00493 { 00494 if (d->m_requests.isEmpty()) return; 00495 BrowserExtensionPrivate::DelayedRequest req = d->m_requests.front(); 00496 d->m_requests.pop_front(); 00497 emit openURLRequestDelayed( req.m_delayedURL, req.m_delayedArgs ); 00498 // tricky: do not do anything here! (no access to member variables, etc.) 00499 } 00500 00501 void BrowserExtension::setBrowserInterface( BrowserInterface *impl ) 00502 { 00503 d->m_browserInterface = impl; 00504 } 00505 00506 BrowserInterface *BrowserExtension::browserInterface() const 00507 { 00508 return d->m_browserInterface; 00509 } 00510 00511 void BrowserExtension::slotEnableAction( const char * name, bool enabled ) 00512 { 00513 //kdDebug() << "BrowserExtension::slotEnableAction " << name << " " << enabled << endl; 00514 ActionNumberMap::ConstIterator it = s_actionNumberMap->find( name ); 00515 if ( it != s_actionNumberMap->end() ) 00516 { 00517 d->m_actionStatus.setBit( it.data(), enabled ); 00518 //kdDebug() << "BrowserExtension::slotEnableAction setting bit " << it.data() << " to " << enabled << endl; 00519 } 00520 else 00521 kdWarning() << "BrowserExtension::slotEnableAction unknown action " << name << endl; 00522 } 00523 00524 bool BrowserExtension::isActionEnabled( const char * name ) const 00525 { 00526 int actionNumber = (*s_actionNumberMap)[ name ]; 00527 return d->m_actionStatus[ actionNumber ]; 00528 } 00529 00530 // for compatibility 00531 BrowserExtension::ActionSlotMap BrowserExtension::actionSlotMap() 00532 { 00533 return *actionSlotMapPtr(); 00534 } 00535 00536 BrowserExtension::ActionSlotMap * BrowserExtension::actionSlotMapPtr() 00537 { 00538 if (!s_actionSlotMap) 00539 createActionSlotMap(); 00540 return s_actionSlotMap; 00541 } 00542 00543 void BrowserExtension::createActionSlotMap() 00544 { 00545 assert(!s_actionSlotMap); 00546 s_actionSlotMap = actionSlotMapsd.setObject( s_actionSlotMap, new ActionSlotMap ); 00547 00548 s_actionSlotMap->insert( "cut", SLOT( cut() ) ); 00549 s_actionSlotMap->insert( "copy", SLOT( copy() ) ); 00550 s_actionSlotMap->insert( "paste", SLOT( paste() ) ); 00551 s_actionSlotMap->insert( "rename", SLOT( rename() ) ); 00552 s_actionSlotMap->insert( "trash", SLOT( trash() ) ); 00553 s_actionSlotMap->insert( "del", SLOT( del() ) ); 00554 s_actionSlotMap->insert( "properties", SLOT( properties() ) ); 00555 s_actionSlotMap->insert( "editMimeType", SLOT( editMimeType() ) ); 00556 s_actionSlotMap->insert( "print", SLOT( print() ) ); 00557 // Tricky. Those aren't actions in fact, but simply methods that a browserextension 00558 // can have or not. No need to return them here. 00559 //s_actionSlotMap->insert( "reparseConfiguration", SLOT( reparseConfiguration() ) ); 00560 //s_actionSlotMap->insert( "refreshMimeTypes", SLOT( refreshMimeTypes() ) ); 00561 // nothing for setSaveViewPropertiesLocally either 00562 00563 // Create the action-number map 00564 assert(!s_actionNumberMap); 00565 s_actionNumberMap = actionNumberMapsd.setObject( s_actionNumberMap, new ActionNumberMap ); 00566 ActionSlotMap::ConstIterator it = s_actionSlotMap->begin(); 00567 ActionSlotMap::ConstIterator itEnd = s_actionSlotMap->end(); 00568 for ( int i=0 ; it != itEnd ; ++it, ++i ) 00569 { 00570 //kdDebug(1202) << " action " << it.key() << " number " << i << endl; 00571 s_actionNumberMap->insert( it.key(), i ); 00572 } 00573 } 00574 00575 BrowserExtension *BrowserExtension::childObject( QObject *obj ) 00576 { 00577 if ( !obj || !obj->children() ) 00578 return 0L; 00579 00580 // we try to do it on our own, in hope that we are faster than 00581 // queryList, which looks kind of big :-) 00582 const QObjectList *children = obj->children(); 00583 QObjectListIt it( *children ); 00584 for (; it.current(); ++it ) 00585 if ( it.current()->inherits( "KParts::BrowserExtension" ) ) 00586 return static_cast<KParts::BrowserExtension *>( it.current() ); 00587 00588 return 0L; 00589 } 00590 00591 namespace KParts 00592 { 00593 00594 class BrowserHostExtension::BrowserHostExtensionPrivate 00595 { 00596 public: 00597 BrowserHostExtensionPrivate() 00598 { 00599 } 00600 ~BrowserHostExtensionPrivate() 00601 { 00602 } 00603 00604 KParts::ReadOnlyPart *m_part; 00605 }; 00606 00607 } 00608 00609 BrowserHostExtension::BrowserHostExtension( KParts::ReadOnlyPart *parent, const char *name ) 00610 : QObject( parent, name ) 00611 { 00612 d = new BrowserHostExtensionPrivate; 00613 d->m_part = parent; 00614 } 00615 00616 BrowserHostExtension::~BrowserHostExtension() 00617 { 00618 delete d; 00619 } 00620 00621 QStringList BrowserHostExtension::frameNames() const 00622 { 00623 return QStringList(); 00624 } 00625 00626 const QPtrList<KParts::ReadOnlyPart> BrowserHostExtension::frames() const 00627 { 00628 return QPtrList<KParts::ReadOnlyPart>(); 00629 } 00630 00631 bool BrowserHostExtension::openURLInFrame( const KURL &, const KParts::URLArgs & ) 00632 { 00633 return false; 00634 } 00635 00636 BrowserHostExtension *BrowserHostExtension::childObject( QObject *obj ) 00637 { 00638 if ( !obj || !obj->children() ) 00639 return 0L; 00640 00641 // we try to do it on our own, in hope that we are faster than 00642 // queryList, which looks kind of big :-) 00643 const QObjectList *children = obj->children(); 00644 QObjectListIt it( *children ); 00645 for (; it.current(); ++it ) 00646 if ( it.current()->inherits( "KParts::BrowserHostExtension" ) ) 00647 return static_cast<KParts::BrowserHostExtension *>( it.current() ); 00648 00649 return 0L; 00650 } 00651 00652 void BrowserExtension::virtual_hook( int, void* ) 00653 { /*BASE::virtual_hook( id, data );*/ } 00654 00655 BrowserHostExtension * 00656 BrowserHostExtension::findFrameParent(KParts::ReadOnlyPart *callingPart, const QString &frame) 00657 { 00658 FindFrameParentParams param; 00659 param.parent = 0; 00660 param.callingPart = callingPart; 00661 param.frame = frame; 00662 virtual_hook(VIRTUAL_FIND_FRAME_PARENT, &param); 00663 return param.parent; 00664 } 00665 00666 void BrowserHostExtension::virtual_hook( int, void* ) 00667 { /*BASE::virtual_hook( id, data );*/ } 00668 00669 LiveConnectExtension::LiveConnectExtension( KParts::ReadOnlyPart *parent, const char *name ) : QObject( parent, name) {} 00670 00671 bool LiveConnectExtension::get( const unsigned long, const QString &, Type &, unsigned long &, QString & ) { 00672 return false; 00673 } 00674 00675 bool LiveConnectExtension::put( const unsigned long, const QString &, const QString & ) { 00676 return false; 00677 } 00678 00679 bool LiveConnectExtension::call( const unsigned long, const QString &, const QStringList &, Type &, unsigned long &, QString & ) { 00680 return false; 00681 } 00682 00683 void LiveConnectExtension::unregister( const unsigned long ) {} 00684 00685 LiveConnectExtension *LiveConnectExtension::childObject( QObject *obj ) 00686 { 00687 if ( !obj || !obj->children() ) 00688 return 0L; 00689 00690 // we try to do it on our own, in hope that we are faster than 00691 // queryList, which looks kind of big :-) 00692 const QObjectList *children = obj->children(); 00693 QObjectListIt it( *children ); 00694 for (; it.current(); ++it ) 00695 if ( it.current()->inherits( "KParts::LiveConnectExtension" ) ) 00696 return static_cast<KParts::LiveConnectExtension *>( it.current() ); 00697 00698 return 0L; 00699 } 00700 00701 #include "browserextension.moc"
KDE Logo
This file is part of the documentation for kparts Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:23:06 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003