1 /* This file is part of the KDE project
2 Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
3 (C) 1999 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#include "browserextension.h"
21
22#include <QtGui/QApplication>
23#include <QtGui/QClipboard>
24#include <QtCore/QTimer>
25#include <QtCore/QObject>
26#include <QtCore/QMap>
27#include <QtCore/QMetaEnum>
28#include <QtCore/QRegExp>
29#include <QtGui/QTextDocument>
30
31#include <kdebug.h>
32#include <klocale.h>
33#include <kmessagebox.h>
34#include <kurifilter.h>
35#include <kglobal.h>
36
37using namespace KParts;
38
39
40class OpenUrlEvent::OpenUrlEventPrivate
41{
42public:
43 OpenUrlEventPrivate( ReadOnlyPart *part,
44 const KUrl &url,
45 const OpenUrlArguments &args,
46 const BrowserArguments &browserArgs )
47 : m_part( part )
48 , m_url( url )
49 , m_args(args)
50 , m_browserArgs(browserArgs)
51 {
52 }
53 ~OpenUrlEventPrivate()
54 {
55 }
56 static const char *s_strOpenUrlEvent;
57 ReadOnlyPart *m_part;
58 KUrl m_url;
59 OpenUrlArguments m_args;
60 BrowserArguments m_browserArgs;
61};
62
63const char *OpenUrlEvent::OpenUrlEventPrivate::s_strOpenUrlEvent =
64 "KParts/BrowserExtension/OpenURLevent";
65
66OpenUrlEvent::OpenUrlEvent( ReadOnlyPart *part, const KUrl &url,
67 const OpenUrlArguments &args,
68 const BrowserArguments &browserArgs )
69 : Event( OpenUrlEventPrivate::s_strOpenUrlEvent )
70 , d( new OpenUrlEventPrivate(part, url, args, browserArgs) )
71{
72}
73
74OpenUrlEvent::~OpenUrlEvent()
75{
76 delete d;
77}
78
79ReadOnlyPart *OpenUrlEvent::part() const
80{
81 return d->m_part;
82}
83
84KUrl OpenUrlEvent::url() const
85{
86 return d->m_url;
87}
88
89OpenUrlArguments OpenUrlEvent::arguments() const
90{
91 return d->m_args;
92}
93
94BrowserArguments OpenUrlEvent::browserArguments() const
95{
96 return d->m_browserArgs;
97}
98
99bool OpenUrlEvent::test( const QEvent *event )
100{
101 return Event::test( event, OpenUrlEventPrivate::s_strOpenUrlEvent );
102}
103
104namespace KParts
105{
106
107struct BrowserArgumentsPrivate
108{
109 BrowserArgumentsPrivate() {
110 doPost = false;
111 redirectedRequest = false;
112 lockHistory = false;
113 newTab = false;
114 forcesNewWindow = false;
115 }
116 QString contentType; // for POST
117 bool doPost;
118 bool redirectedRequest;
119 bool lockHistory;
120 bool newTab;
121 bool forcesNewWindow;
122};
123
124}
125
126BrowserArguments::BrowserArguments()
127{
128 softReload = false;
129 trustedSource = false;
130 d = 0; // Let's build it on demand for now
131}
132
133BrowserArguments::BrowserArguments( const BrowserArguments &args )
134{
135 d = 0;
136 (*this) = args;
137}
138
139BrowserArguments &BrowserArguments::operator=(const BrowserArguments &args)
140{
141 if (this == &args) return *this;
142
143 delete d; d= 0;
144
145 softReload = args.softReload;
146 postData = args.postData;
147 frameName = args.frameName;
148 docState = args.docState;
149 trustedSource = args.trustedSource;
150
151 if ( args.d )
152 d = new BrowserArgumentsPrivate( * args.d );
153
154 return *this;
155}
156
157BrowserArguments::~BrowserArguments()
158{
159 delete d;
160 d = 0;
161}
162
163void BrowserArguments::setContentType( const QString & contentType )
164{
165 if (!d)
166 d = new BrowserArgumentsPrivate;
167 d->contentType = contentType;
168}
169
170void BrowserArguments::setRedirectedRequest( bool redirected )
171{
172 if (!d)
173 d = new BrowserArgumentsPrivate;
174 d->redirectedRequest = redirected;
175}
176
177bool BrowserArguments::redirectedRequest () const
178{
179 return d ? d->redirectedRequest : false;
180}
181
182QString BrowserArguments::contentType() const
183{
184 return d ? d->contentType : QString();
185}
186
187void BrowserArguments::setDoPost( bool enable )
188{
189 if ( !d )
190 d = new BrowserArgumentsPrivate;
191 d->doPost = enable;
192}
193
194bool BrowserArguments::doPost() const
195{
196 return d ? d->doPost : false;
197}
198
199void BrowserArguments::setLockHistory( bool lock )
200{
201 if (!d)
202 d = new BrowserArgumentsPrivate;
203 d->lockHistory = lock;
204}
205
206bool BrowserArguments::lockHistory() const
207{
208 return d ? d->lockHistory : false;
209}
210
211void BrowserArguments::setNewTab( bool newTab )
212{
213 if (!d)
214 d = new BrowserArgumentsPrivate;
215 d->newTab = newTab;
216}
217
218bool BrowserArguments::newTab() const
219{
220 return d ? d->newTab : false;
221}
222
223void BrowserArguments::setForcesNewWindow( bool forcesNewWindow )
224{
225 if (!d)
226 d = new BrowserArgumentsPrivate;
227 d->forcesNewWindow = forcesNewWindow;
228}
229
230bool BrowserArguments::forcesNewWindow() const
231{
232 return d ? d->forcesNewWindow : false;
233}
234
235namespace KParts
236{
237
238class WindowArgsPrivate : public QSharedData
239{
240public:
241 WindowArgsPrivate()
242 : x(-1), y(-1), width(-1), height(-1),
243 fullscreen(false),
244 menuBarVisible(true),
245 toolBarsVisible(true),
246 statusBarVisible(true),
247 resizable(true),
248 lowerWindow(false),
249 scrollBarsVisible(true)
250 {
251 }
252
253 // Position
254 int x;
255 int y;
256 // Size
257 int width;
258 int height;
259 bool fullscreen; //defaults to false
260 bool menuBarVisible; //defaults to true
261 bool toolBarsVisible; //defaults to true
262 bool statusBarVisible; //defaults to true
263 bool resizable; //defaults to true
264
265 bool lowerWindow; //defaults to false
266 bool scrollBarsVisible; //defaults to true
267};
268
269}
270
271WindowArgs::WindowArgs()
272 : d(new WindowArgsPrivate)
273{
274}
275
276WindowArgs::WindowArgs( const WindowArgs &args )
277 : d(args.d)
278{
279}
280
281WindowArgs::~WindowArgs()
282{
283}
284
285WindowArgs &WindowArgs::operator=( const WindowArgs &args )
286{
287 if ( this == &args ) return *this;
288
289 d = args.d;
290 return *this;
291}
292
293WindowArgs::WindowArgs( const QRect &_geometry, bool _fullscreen, bool _menuBarVisible,
294 bool _toolBarsVisible, bool _statusBarVisible, bool _resizable )
295 : d(new WindowArgsPrivate)
296{
297 d->x = _geometry.x();
298 d->y = _geometry.y();
299 d->width = _geometry.width();
300 d->height = _geometry.height();
301 d->fullscreen = _fullscreen;
302 d->menuBarVisible = _menuBarVisible;
303 d->toolBarsVisible = _toolBarsVisible;
304 d->statusBarVisible = _statusBarVisible;
305 d->resizable = _resizable;
306 d->lowerWindow = false;
307}
308
309WindowArgs::WindowArgs( int _x, int _y, int _width, int _height, bool _fullscreen,
310 bool _menuBarVisible, bool _toolBarsVisible,
311 bool _statusBarVisible, bool _resizable )
312 : d(new WindowArgsPrivate)
313{
314 d->x = _x;
315 d->y = _y;
316 d->width = _width;
317 d->height = _height;
318 d->fullscreen = _fullscreen;
319 d->menuBarVisible = _menuBarVisible;
320 d->toolBarsVisible = _toolBarsVisible;
321 d->statusBarVisible = _statusBarVisible;
322 d->resizable = _resizable;
323 d->lowerWindow = false;
324}
325
326void WindowArgs::setX(int x)
327{
328 d->x = x;
329}
330
331int WindowArgs::x() const
332{
333 return d->x;
334}
335
336void WindowArgs::setY(int y)
337{
338 d->y = y;
339}
340
341int WindowArgs::y() const
342{
343 return d->y;
344}
345
346void WindowArgs::setWidth(int w)
347{
348 d->width = w;
349}
350
351int WindowArgs::width() const
352{
353 return d->width;
354}
355
356void WindowArgs::setHeight(int h)
357{
358 d->height = h;
359}
360
361int WindowArgs::height() const
362{
363 return d->height;
364}
365
366void WindowArgs::setFullScreen(bool fs)
367{
368 d->fullscreen = fs;
369}
370
371bool WindowArgs::isFullScreen() const
372{
373 return d->fullscreen;
374}
375
376void WindowArgs::setMenuBarVisible(bool visible)
377{
378 d->menuBarVisible = visible;
379}
380
381bool WindowArgs::isMenuBarVisible() const
382{
383 return d->menuBarVisible;
384}
385
386void WindowArgs::setToolBarsVisible(bool visible)
387{
388 d->toolBarsVisible = visible;
389}
390
391bool WindowArgs::toolBarsVisible() const
392{
393 return d->toolBarsVisible;
394}
395
396void WindowArgs::setStatusBarVisible(bool visible)
397{
398 d->statusBarVisible = visible;
399}
400
401bool WindowArgs::isStatusBarVisible() const
402{
403 return d->statusBarVisible;
404}
405
406void WindowArgs::setResizable(bool resizable)
407{
408 d->resizable = resizable;
409}
410
411bool WindowArgs::isResizable() const
412{
413 return d->resizable;
414}
415
416void WindowArgs::setLowerWindow(bool lower)
417{
418 d->lowerWindow = lower;
419}
420
421bool WindowArgs::lowerWindow() const
422{
423 return d->lowerWindow;
424}
425
426void WindowArgs::setScrollBarsVisible(bool visible)
427{
428 d->scrollBarsVisible = visible;
429}
430
431bool WindowArgs::scrollBarsVisible() const
432{
433 return d->scrollBarsVisible;
434}
435
436namespace KParts
437{
438
439// Internal class, use to store the status of the actions
440class KBitArray
441{
442public:
443 int val;
444 KBitArray() { val = 0; }
445 bool operator [](int index) { return (val & (1 << index)) ? true : false; }
446 void setBit(int index, bool value) {
447 if (value) val = val | (1 << index);
448 else val = val & ~(1 << index);
449 }
450};
451
452class BrowserExtension::BrowserExtensionPrivate
453{
454public:
455 BrowserExtensionPrivate( KParts::ReadOnlyPart *parent )
456 : m_urlDropHandlingEnabled(false),
457 m_browserInterface(0),
458 m_part( parent )
459 {}
460
461 struct DelayedRequest {
462 KUrl m_delayedURL;
463 KParts::OpenUrlArguments m_delayedArgs;
464 KParts::BrowserArguments m_delayedBrowserArgs;
465 };
466
467 QList<DelayedRequest> m_requests;
468 bool m_urlDropHandlingEnabled;
469 KBitArray m_actionStatus;
470 QMap<int, QString> m_actionText;
471 BrowserInterface *m_browserInterface;
472
473 static void createActionSlotMap();
474
475 KParts::ReadOnlyPart *m_part;
476 OpenUrlArguments m_args;
477 BrowserArguments m_browserArgs;
478};
479
480K_GLOBAL_STATIC(BrowserExtension::ActionSlotMap, s_actionSlotMap)
481K_GLOBAL_STATIC(BrowserExtension::ActionNumberMap, s_actionNumberMap)
482
483void BrowserExtension::BrowserExtensionPrivate::createActionSlotMap()
484{
485 s_actionSlotMap->insert( "cut", SLOT(cut()) );
486 s_actionSlotMap->insert( "copy", SLOT(copy()) );
487 s_actionSlotMap->insert( "paste", SLOT(paste()) );
488 s_actionSlotMap->insert( "print", SLOT(print()) );
489 // Tricky. Those aren't actions in fact, but simply methods that a browserextension
490 // can have or not. No need to return them here.
491 //s_actionSlotMap->insert( "reparseConfiguration", SLOT(reparseConfiguration()) );
492 //s_actionSlotMap->insert( "refreshMimeTypes", SLOT(refreshMimeTypes()) );
493
494 // Create the action-number map
495 ActionSlotMap::ConstIterator it = s_actionSlotMap->constBegin();
496 ActionSlotMap::ConstIterator itEnd = s_actionSlotMap->constEnd();
497 for ( int i=0 ; it != itEnd ; ++it, ++i )
498 {
499 //kDebug(1202) << " action " << it.key() << " number " << i;
500 s_actionNumberMap->insert( it.key(), i );
501 }
502}
503
504}
505
506BrowserExtension::BrowserExtension( KParts::ReadOnlyPart *parent )
507: QObject( parent ), d( new BrowserExtensionPrivate(parent) )
508{
509 //kDebug() << "BrowserExtension::BrowserExtension() " << this;
510
511 if (s_actionSlotMap->isEmpty())
512 // Create the action-slot map
513 BrowserExtensionPrivate::createActionSlotMap();
514
515 // Build list with this extension's slot names.
516 QList<QByteArray> slotNames;
517 int methodCount = metaObject()->methodCount();
518 int methodOffset = metaObject()->methodOffset();
519 for ( int i=0 ; i < methodCount; ++i )
520 {
521 QMetaMethod method = metaObject()->method( methodOffset + i );
522 if ( method.methodType() == QMetaMethod::Slot )
523 slotNames.append( method.signature() );
524 }
525
526 // Set the initial status of the actions depending on whether
527 // they're supported or not
528 ActionSlotMap::ConstIterator it = s_actionSlotMap->constBegin();
529 ActionSlotMap::ConstIterator itEnd = s_actionSlotMap->constEnd();
530 for ( int i=0 ; it != itEnd ; ++it, ++i )
531 {
532 // Does the extension have a slot with the name of this action ?
533 // ######### KDE4 TODO: use QMetaObject::indexOfMethod() #######
534 d->m_actionStatus.setBit( i, slotNames.contains( it.key()+"()" ) );
535 }
536
537 connect( d->m_part, SIGNAL(completed()),
538 this, SLOT(slotCompleted()) );
539 connect( this, SIGNAL(openUrlRequest(KUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)),
540 this, SLOT(slotOpenUrlRequest(KUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)) );
541 connect( this, SIGNAL(enableAction(const char*,bool)),
542 this, SLOT(slotEnableAction(const char*,bool)) );
543 connect( this, SIGNAL(setActionText(const char*,QString)),
544 this, SLOT(slotSetActionText(const char*,QString)) );
545}
546
547BrowserExtension::~BrowserExtension()
548{
549 //kDebug() << "BrowserExtension::~BrowserExtension() " << this;
550 delete d;
551}
552
553void BrowserExtension::setBrowserArguments( const BrowserArguments &args )
554{
555 d->m_browserArgs = args;
556}
557
558BrowserArguments BrowserExtension::browserArguments() const
559{
560 return d->m_browserArgs;
561}
562
563int BrowserExtension::xOffset()
564{
565 return 0;
566}
567
568int BrowserExtension::yOffset()
569{
570 return 0;
571}
572
573void BrowserExtension::saveState( QDataStream &stream )
574{
575 // TODO add d->m_part->mimeType()
576 stream << d->m_part->url() << (qint32)xOffset() << (qint32)yOffset();
577}
578
579void BrowserExtension::restoreState( QDataStream &stream )
580{
581 KUrl u;
582 qint32 xOfs, yOfs;
583 stream >> u >> xOfs >> yOfs;
584
585 OpenUrlArguments args;
586 args.setXOffset(xOfs);
587 args.setYOffset(yOfs);
588 // TODO add args.setMimeType
589 d->m_part->setArguments(args);
590 d->m_part->openUrl(u);
591}
592
593bool BrowserExtension::isURLDropHandlingEnabled() const
594{
595 return d->m_urlDropHandlingEnabled;
596}
597
598void BrowserExtension::setURLDropHandlingEnabled( bool enable )
599{
600 d->m_urlDropHandlingEnabled = enable;
601}
602
603void BrowserExtension::slotCompleted()
604{
605 //empty the argument stuff, to avoid bogus/invalid values when opening a new url
606 setBrowserArguments( BrowserArguments() );
607}
608
609void BrowserExtension::pasteRequest()
610{
611 QString plain( "plain" );
612 QString url = QApplication::clipboard()->text(plain, QClipboard::Selection).trimmed();
613 // Remove linefeeds and any whitespace surrounding it.
614 url.remove(QRegExp("[\\ ]*\\n+[\\ ]*"));
615
616 // Check if it's a URL
617 QStringList filters = KUriFilter::self()->pluginNames();
618 filters.removeAll( "kuriikwsfilter" );
619 filters.removeAll( "localdomainurifilter" );
620 KUriFilterData filterData;
621 filterData.setData( url );
622 filterData.setCheckForExecutables( false );
623 if ( KUriFilter::self()->filterUri( filterData, filters ) )
624 {
625 switch ( filterData.uriType() )
626 {
627 case KUriFilterData::LocalFile:
628 case KUriFilterData::LocalDir:
629 case KUriFilterData::NetProtocol:
630 slotOpenUrlRequest( filterData.uri() );
631 break;
632 case KUriFilterData::Error:
633 KMessageBox::sorry( d->m_part->widget(), filterData.errorMsg() );
634 break;
635 default:
636 break;
637 }
638 }
639 else if ( KUriFilter::self()->filterUri( filterData,
640 QStringList( QLatin1String( "kuriikwsfilter" ) ) ) &&
641 url.length() < 250 )
642 {
643 if ( KMessageBox::questionYesNo( d->m_part->widget(),
644 i18n( "<qt>Do you want to search the Internet for <b>%1</b>?</qt>" , Qt::escape(url) ),
645 i18n( "Internet Search" ), KGuiItem( i18n( "&Search" ), "edit-find"),
646 KStandardGuiItem::cancel(), "MiddleClickSearch" ) == KMessageBox::Yes)
647 slotOpenUrlRequest( filterData.uri() );
648 }
649}
650
651void BrowserExtension::slotOpenUrlRequest( const KUrl &url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments &browserArgs )
652{
653 //kDebug() << this << " BrowserExtension::slotOpenURLRequest(): url=" << url.url();
654 BrowserExtensionPrivate::DelayedRequest req;
655 req.m_delayedURL = url;
656 req.m_delayedArgs = args;
657 req.m_delayedBrowserArgs = browserArgs;
658 d->m_requests.append( req );
659 QTimer::singleShot( 0, this, SLOT(slotEmitOpenUrlRequestDelayed()) );
660}
661
662void BrowserExtension::slotEmitOpenUrlRequestDelayed()
663{
664 if (d->m_requests.isEmpty()) return;
665 BrowserExtensionPrivate::DelayedRequest req = d->m_requests.front();
666 d->m_requests.pop_front();
667 emit openUrlRequestDelayed( req.m_delayedURL, req.m_delayedArgs, req.m_delayedBrowserArgs );
668 // tricky: do not do anything here! (no access to member variables, etc.)
669}
670
671void BrowserExtension::setBrowserInterface( BrowserInterface *impl )
672{
673 d->m_browserInterface = impl;
674}
675
676BrowserInterface *BrowserExtension::browserInterface() const
677{
678 return d->m_browserInterface;
679}
680
681void BrowserExtension::slotEnableAction( const char * name, bool enabled )
682{
683 //kDebug() << "BrowserExtension::slotEnableAction " << name << " " << enabled;
684 ActionNumberMap::ConstIterator it = s_actionNumberMap->constFind( name );
685 if ( it != s_actionNumberMap->constEnd() )
686 {
687 d->m_actionStatus.setBit( it.value(), enabled );
688 //kDebug() << "BrowserExtension::slotEnableAction setting bit " << it.data() << " to " << enabled;
689 }
690 else
691 kWarning() << "BrowserExtension::slotEnableAction unknown action " << name;
692}
693
694bool BrowserExtension::isActionEnabled( const char * name ) const
695{
696 int actionNumber = (*s_actionNumberMap)[ name ];
697 return d->m_actionStatus[ actionNumber ];
698}
699
700void BrowserExtension::slotSetActionText( const char * name, const QString& text )
701{
702 //kDebug() << "BrowserExtension::slotSetActionText " << name << " " << text;
703 ActionNumberMap::ConstIterator it = s_actionNumberMap->constFind( name );
704 if ( it != s_actionNumberMap->constEnd() )
705 {
706 d->m_actionText[ it.value() ] = text;
707 }
708 else
709 kWarning() << "BrowserExtension::slotSetActionText unknown action " << name;
710}
711
712QString BrowserExtension::actionText( const char * name ) const
713{
714 int actionNumber = (*s_actionNumberMap)[ name ];
715 QMap<int, QString>::ConstIterator it = d->m_actionText.constFind( actionNumber );
716 if ( it != d->m_actionText.constEnd() )
717 return *it;
718 return QString();
719}
720
721// for compatibility
722BrowserExtension::ActionSlotMap BrowserExtension::actionSlotMap()
723{
724 return *actionSlotMapPtr();
725}
726
727BrowserExtension::ActionSlotMap * BrowserExtension::actionSlotMapPtr()
728{
729 if (s_actionSlotMap->isEmpty())
730 BrowserExtensionPrivate::createActionSlotMap();
731 return s_actionSlotMap;
732}
733
734BrowserExtension *BrowserExtension::childObject( QObject *obj )
735{
736 return KGlobal::findDirectChild<KParts::BrowserExtension *>(obj);
737}
738
739namespace KParts
740{
741
742class BrowserHostExtension::BrowserHostExtensionPrivate
743{
744public:
745 BrowserHostExtensionPrivate()
746 {
747 }
748 ~BrowserHostExtensionPrivate()
749 {
750 }
751
752 KParts::ReadOnlyPart *m_part;
753};
754
755}
756
757BrowserHostExtension::BrowserHostExtension( KParts::ReadOnlyPart *parent )
758 : QObject( parent ), d( new BrowserHostExtensionPrivate )
759{
760 d->m_part = parent;
761}
762
763BrowserHostExtension::~BrowserHostExtension()
764{
765 delete d;
766}
767
768QStringList BrowserHostExtension::frameNames() const
769{
770 return QStringList();
771}
772
773const QList<KParts::ReadOnlyPart*> BrowserHostExtension::frames() const
774{
775 return QList<KParts::ReadOnlyPart*>();
776}
777
778bool BrowserHostExtension::openUrlInFrame( const KUrl &,
779 const KParts::OpenUrlArguments&,
780 const KParts::BrowserArguments & )
781{
782 return false;
783}
784
785BrowserHostExtension *BrowserHostExtension::childObject( QObject *obj )
786{
787 return KGlobal::findDirectChild<KParts::BrowserHostExtension *>(obj);
788}
789
790BrowserHostExtension *
791BrowserHostExtension::findFrameParent(KParts::ReadOnlyPart *callingPart, const QString &frame)
792{
793 Q_UNUSED(callingPart);
794 Q_UNUSED(frame);
795 return 0;
796}
797
798LiveConnectExtension::LiveConnectExtension( KParts::ReadOnlyPart *parent )
799 : QObject( parent ), d( 0 ) {}
800
801LiveConnectExtension::~LiveConnectExtension() {}
802
803bool LiveConnectExtension::get( const unsigned long, const QString &, Type &, unsigned long &, QString & ) {
804 return false;
805}
806
807bool LiveConnectExtension::put( const unsigned long, const QString &, const QString & ) {
808 return false;
809}
810
811bool LiveConnectExtension::call( const unsigned long, const QString &, const QStringList &, Type &, unsigned long &, QString & ) {
812 return false;
813}
814
815void LiveConnectExtension::unregister( const unsigned long ) {}
816
817LiveConnectExtension *LiveConnectExtension::childObject( QObject *obj )
818{
819 return KGlobal::findDirectChild<KParts::LiveConnectExtension *>(obj);
820}
821
822#include "browserextension.moc"
823