00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "akregatorconfig.h"
00027 #include "akregator_run.h"
00028 #include "feediconmanager.h"
00029 #include "pageviewer.h"
00030 #include "viewer.h"
00031
00032 #include <kaction.h>
00033 #include <kapplication.h>
00034 #include <kbookmark.h>
00035 #include <kbookmarkmanager.h>
00036 #include <kconfig.h>
00037 #include <kglobalsettings.h>
00038 #include <khtml_settings.h>
00039 #include <khtmlview.h>
00040 #include <kiconloader.h>
00041 #include <klocale.h>
00042 #include <kpopupmenu.h>
00043 #include <kstandarddirs.h>
00044 #include <kstdaccel.h>
00045 #include <kparts/browserinterface.h>
00046
00047 #include <qclipboard.h>
00048 #include <qcstring.h>
00049 #include <qdatastream.h>
00050 #include <qdatetime.h>
00051 #include <qfile.h>
00052 #include <qmetaobject.h>
00053 #include <qscrollview.h>
00054 #include <qstring.h>
00055 #include <qvaluelist.h>
00056 #include <private/qucomextra_p.h>
00057
00058 #include <cstdlib>
00059 using std::abs;
00060
00061 namespace Akregator {
00062
00063
00064
00065 class PageViewer::HistoryEntry
00066 {
00067 public:
00068
00069 KURL url;
00070 QString title;
00071 QByteArray state;
00072 int id;
00073
00074 HistoryEntry() {}
00075 HistoryEntry(const KURL& u, const QString& t=QString::null): url(u), title(t)
00076 {
00077 id = abs( QTime::currentTime().msecsTo( QTime() ) );
00078 }
00079
00080 };
00081
00082 class PageViewer::PageViewerPrivate
00083 {
00084 public:
00085
00086 QValueList<HistoryEntry> history;
00087 QValueList<HistoryEntry>::Iterator current;
00088
00089 KToolBarPopupAction* backAction;
00090 KToolBarPopupAction* forwardAction;
00091 KAction* reloadAction;
00092 KAction* stopAction;
00093
00094 QString caption;
00095 };
00096
00097
00098 PageViewer::PageViewer(QWidget *parent, const char *name)
00099 : Viewer(parent, name), d(new PageViewerPrivate)
00100 {
00101
00102
00103 KHTMLSettings* s = const_cast<KHTMLSettings*> (settings());
00104 s->init(Settings::self()->config());
00105
00106 setXMLFile(locate("data", "akregator/pageviewer.rc"), true);
00107
00108 QPair< KGuiItem, KGuiItem > backForward = KStdGuiItem::backAndForward();
00109
00110 d->backAction = new KToolBarPopupAction(backForward.first,
00111 KStdAccel::shortcut(KStdAccel::Back), this,
00112 SLOT(slotBack()), actionCollection(),
00113 "pageviewer_back");
00114
00115 connect(d->backAction->popupMenu(), SIGNAL(aboutToShow()),
00116 this, SLOT(slotBackAboutToShow()));
00117 connect(d->backAction->popupMenu(), SIGNAL(activated(int)),
00118 this, SLOT(slotPopupActivated(int)));
00119
00120
00121 d->forwardAction = new KToolBarPopupAction(backForward.second,
00122 KStdAccel::shortcut(KStdAccel::Forward),this,
00123 SLOT(slotForward()), actionCollection(),
00124 "pageviewer_forward");
00125
00126 connect(d->forwardAction->popupMenu(), SIGNAL(aboutToShow()),
00127 this, SLOT(slotForwardAboutToShow()));
00128 connect(d->forwardAction->popupMenu(), SIGNAL(activated(int)),
00129 this, SLOT(slotPopupActivated(int)));
00130
00131 d->reloadAction = new KAction(i18n("Reload"), "reload", 0,
00132 this, SLOT(slotReload()),
00133 actionCollection(), "pageviewer_reload");
00134 d->stopAction = new KAction(KStdGuiItem::guiItem(KStdGuiItem::Stop), 0,
00135 this, SLOT(slotStop()),
00136 actionCollection(), "pageviewer_stop");
00137
00138
00139
00140 d->backAction->setEnabled(false);
00141 d->forwardAction->setEnabled(false);
00142 d->stopAction->setEnabled(false);
00143
00144 connect( this, SIGNAL(setWindowCaption (const QString &)),
00145 this, SLOT(slotSetCaption (const QString &)) );
00146
00147 connect(this, SIGNAL(started(KIO::Job *)), this, SLOT(slotStarted(KIO::Job* )));
00148 connect(this, SIGNAL(completed()), this, SLOT(slotCompleted()));
00149 connect(this, SIGNAL(canceled(const QString &)), this, SLOT(slotCancelled(const QString &)));
00150
00151 d->current = d->history.end();
00152
00153
00154
00155
00156 }
00157
00158 PageViewer::~PageViewer()
00159 {
00160 delete d;
00161 d = 0;
00162 }
00163
00164
00165 void PageViewer::slotBack()
00166 {
00167 if ( d->current != d->history.begin() )
00168 {
00169 QValueList<HistoryEntry>::Iterator tmp = d->current;
00170 --tmp;
00171 restoreHistoryEntry(tmp);
00172 }
00173 }
00174
00175
00176 void PageViewer::slotForward()
00177 {
00178 if ( d->current != d->history.fromLast() && d->current != d->history.end() )
00179 {
00180 QValueList<HistoryEntry>::Iterator tmp = d->current;
00181 ++tmp;
00182 restoreHistoryEntry(tmp);
00183 }
00184 }
00185
00186 void PageViewer::slotBackAboutToShow()
00187 {
00188 KPopupMenu *popup = d->backAction->popupMenu();
00189 popup->clear();
00190
00191 if ( d->current == d->history.begin() )
00192 return;
00193
00194 QValueList<HistoryEntry>::Iterator it = d->current;
00195 --it;
00196
00197 int i = 0;
00198 while( i < 10 )
00199 {
00200 if ( it == d->history.begin() )
00201 {
00202 popup->insertItem( (*it).title, (*it).id );
00203 return;
00204 }
00205
00206 popup->insertItem( (*it).title, (*it).id );
00207 ++i;
00208 --it;
00209 }
00210 }
00211
00212 void PageViewer::slotForwardAboutToShow()
00213 {
00214 KPopupMenu *popup = d->forwardAction->popupMenu();
00215 popup->clear();
00216
00217 if ( d->current == d->history.fromLast() )
00218 return;
00219
00220 QValueList<HistoryEntry>::Iterator it = d->current;
00221 ++it;
00222
00223 int i = 0;
00224 while( i < 10 )
00225 {
00226 if ( it == d->history.fromLast() )
00227 {
00228 popup->insertItem( (*it).title, (*it).id );
00229 return;
00230 }
00231
00232 popup->insertItem( (*it).title, (*it).id );
00233 ++i;
00234 ++it;
00235 }
00236 }
00237
00238
00239 void PageViewer::slotReload()
00240 {
00241 openURL( url() );
00242 }
00243
00244 void PageViewer::slotStop()
00245 {
00246 closeURL();
00247 }
00248
00249 bool PageViewer::openURL(const KURL& url)
00250 {
00251 updateHistoryEntry();
00252 emit started(0);
00253
00254 bool val = KHTMLPart::openURL(url);
00255
00256 addHistoryEntry(url);
00257
00258 d->backAction->setEnabled( d->current != d->history.begin() );
00259 d->forwardAction->setEnabled( d->current != d->history.fromLast() );
00260
00261 QString favicon = FeedIconManager::self()->iconLocation(url);
00262 if (!favicon.isEmpty())
00263 emit setTabIcon(QPixmap(KGlobal::dirs()->findResource("cache", favicon+".png")));
00264 else
00265 emit setTabIcon(SmallIcon("html"));
00266
00267 return val;
00268 }
00269
00270
00271 void PageViewer::slotOpenURLRequest(const KURL& url, const KParts::URLArgs& args)
00272 {
00273 updateHistoryEntry();
00274 if (args.doPost())
00275 {
00276 browserExtension()->setURLArgs(args);
00277 openURL(url);
00278 }
00279
00280 }
00281
00282 void PageViewer::slotPopupActivated( int id )
00283 {
00284 QValueList<HistoryEntry>::Iterator it = d->history.begin();
00285 while( it != d->history.end() )
00286 {
00287 if ( (*it).id == id )
00288 {
00289 restoreHistoryEntry(it);
00290 return;
00291 }
00292 ++it;
00293 }
00294 }
00295
00296 void PageViewer::updateHistoryEntry()
00297 {
00298 (*d->current).title = d->caption;
00299 (*d->current).state = QByteArray();
00300 QDataStream stream( (*d->current).state, IO_WriteOnly);
00301 browserExtension()->saveState(stream);
00302 }
00303
00304 void PageViewer::restoreHistoryEntry(const QValueList<HistoryEntry>::Iterator& entry)
00305 {
00306 updateHistoryEntry();
00307
00308 QDataStream stream( (*entry).state, IO_ReadOnly );
00309 browserExtension()->restoreState( stream );
00310 d->current = entry;
00311 d->backAction->setEnabled( d->current != d->history.begin() );
00312 d->forwardAction->setEnabled( d->current != d->history.fromLast() );
00313
00314
00315
00316 }
00317
00318
00319 void PageViewer::addHistoryEntry(const KURL& url)
00320 {
00321 QValueList<HistoryEntry>::Iterator it = d->current;
00322
00323
00324 if ( it != d->history.end() && it != d->history.fromLast() )
00325 {
00326 d->history.erase( ++it, d->history.end() );
00327 }
00328 HistoryEntry newEntry( url, url.url() );
00329
00330
00331 if ( newEntry.url != (*d->current).url )
00332 {
00333 d->history.append( newEntry );
00334 d->current = d->history.fromLast();
00335 }
00336 updateHistoryEntry();
00337 }
00338
00339
00340 void PageViewer::slotStarted( KIO::Job * )
00341 {
00342 d->stopAction->setEnabled(true);
00343 }
00344
00345
00346 void PageViewer::slotCompleted( )
00347 {
00348 d->stopAction->setEnabled(false);
00349 }
00350
00351
00352 void PageViewer::slotCancelled( const QString & )
00353 {
00354 d->stopAction->setEnabled(false);
00355 }
00356
00357 void PageViewer::urlSelected(const QString &url, int button, int state, const QString &_target, KParts::URLArgs args)
00358 {
00359 if (button == LeftButton)
00360 {
00361 m_url = completeURL(url);
00362 browserExtension()->setURLArgs(args);
00363 slotOpenLinkInThisTab();
00364 }
00365 else
00366 {
00367 Viewer::urlSelected(url,button,state,_target,args);
00368 }
00369 }
00370
00371 void PageViewer::slotSetCaption(const QString& cap)
00372 {
00373 d->caption = cap;
00374 (*d->current).title = cap;
00375 }
00376
00377 void PageViewer::slotPaletteOrFontChanged()
00378 {
00379 kdDebug() << "PageViewer::slotPaletteOrFontChanged()" << endl;
00380
00381
00382 QObject *obj = KParts::BrowserExtension::childObject(this);
00383 if ( !obj )
00384 return;
00385
00386 int id = obj->metaObject()->findSlot("reparseConfiguration()");
00387 if (id == -1)
00388 return;
00389 QUObject o[1];
00390
00391 obj->qt_invoke(id, o);
00392
00393
00394
00395
00396 KHTMLSettings* s = const_cast<KHTMLSettings*> (settings());
00397 s->init(Settings::self()->config());
00398 }
00399
00400 void PageViewer::slotGlobalBookmarkArticle()
00401 {
00402 KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager();
00403 KBookmarkGroup grp = mgr->root();
00404 grp.addBookmark(mgr, d->caption, toplevelURL());
00405 mgr->emitChanged(grp);
00406 mgr->save();
00407 }
00408
00409
00410 void PageViewer::slotPopupMenu(KXMLGUIClient*, const QPoint& p, const KURL& kurl, const KParts::URLArgs&, KParts::BrowserExtension::PopupFlags kpf, mode_t)
00411 {
00412 m_url = kurl;
00413 QString url = kurl.url();
00414
00415 const bool showReload = (kpf & KParts::BrowserExtension::ShowReload) != 0;
00416 const bool showNavigationItems = (kpf & KParts::BrowserExtension::ShowNavigationItems) != 0;
00417 const bool isLink = (kpf & (KParts::BrowserExtension::ShowNavigationItems | KParts::BrowserExtension::ShowTextSelectionItems)) == 0;
00418 const bool isSelection = (kpf & KParts::BrowserExtension::ShowTextSelectionItems) != 0;
00419
00420 KPopupMenu popup(this->widget());
00421
00422 int idNewWindow = -2;
00423 if (isLink)
00424 {
00425 idNewWindow = popup.insertItem(SmallIcon("tab_new"),i18n("Open Link in New &Tab"), this, SLOT(slotOpenLinkInForegroundTab()));
00426 popup.setWhatsThis(idNewWindow, i18n("<b>Open Link in New Tab</b><p>Opens current link in a new tab."));
00427 popup.insertItem(SmallIcon("window_new"), i18n("Open Link in External &Browser"), this, SLOT(slotOpenLinkInBrowser()));
00428
00429 popup.insertSeparator();
00430 action("savelinkas")->plug(&popup);
00431 KAction* copylinkaddress = action("copylinkaddress");
00432 if (copylinkaddress)
00433 {
00434 copylinkaddress->plug( &popup);
00435
00436 }
00437 }
00438 else
00439 {
00440 if (showNavigationItems)
00441 {
00442 d->backAction->plug( &popup );
00443 d->forwardAction->plug( &popup );
00444 }
00445
00446 if (showReload)
00447 d->reloadAction->plug(&popup);
00448
00449 d->stopAction->plug(&popup);
00450
00451 popup.insertSeparator();
00452
00453 if (isSelection)
00454 {
00455 action("viewer_copy")->plug(&popup);
00456 popup.insertSeparator();
00457 }
00458
00459 KAction* incFontAction = this->action("incFontSizes");
00460 KAction* decFontAction = this->action("decFontSizes");
00461 if ( incFontAction && decFontAction )
00462 {
00463 incFontAction->plug( &popup );
00464 decFontAction->plug( &popup );
00465 popup.insertSeparator();
00466 }
00467
00468 popup.insertItem(SmallIcon("window_new"), i18n("Open Page in External Browser"), this, SLOT(slotOpenLinkInBrowser()));
00469
00470 action("viewer_print")->plug(&popup);
00471 popup.insertSeparator();
00472
00473 KAction *ac = action("setEncoding");
00474 if (ac)
00475 ac->plug(&popup);
00476 popup.insertItem(SmallIcon("bookmark_add"),i18n("Add to Konqueror Bookmarks"), this, SLOT(slotGlobalBookmarkArticle()));
00477 }
00478
00479 int r = popup.exec(p);
00480
00481 if (r == idNewWindow)
00482 {
00483 KURL kurl;
00484 if (!KURL(url).path().startsWith("/"))
00485 {
00486 kdDebug() << "processing relative url: " << url << endl;
00487 if (url.startsWith("#"))
00488 {
00489 kurl = KURL(PageViewer::url());
00490 kurl.setRef(url.mid(1));
00491 }
00492 else
00493 kurl = KURL(PageViewer::url().upURL().url(true)+url);
00494 }
00495 else
00496 kurl = KURL(url);
00497
00498 if (kurl.isValid()) {
00499
00500 }
00501
00502 }
00503 }
00504
00505 }
00506
00507 #include "pageviewer.moc"