diff options
Diffstat (limited to 'akregator/src/pageviewer.cpp')
-rw-r--r-- | akregator/src/pageviewer.cpp | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/akregator/src/pageviewer.cpp b/akregator/src/pageviewer.cpp new file mode 100644 index 000000000..1a10b4953 --- /dev/null +++ b/akregator/src/pageviewer.cpp @@ -0,0 +1,514 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Sashmit Bhaduri <smt@vfemail.net> + 2005 Frank Osterfeld <frank.osterfeld at kdemail.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "akregatorconfig.h" +#include "akregator_run.h" +#include "feediconmanager.h" +#include "pageviewer.h" +#include "viewer.h" + +#include <kaction.h> +#include <kapplication.h> +#include <kbookmark.h> +#include <kbookmarkmanager.h> +#include <kconfig.h> +#include <kglobalsettings.h> +#include <khtml_settings.h> +#include <khtmlview.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kstandarddirs.h> +#include <kstdaccel.h> +#include <kparts/browserinterface.h> + +#include <qclipboard.h> +#include <qcstring.h> +#include <qdatastream.h> +#include <qdatetime.h> +#include <qfile.h> +#include <qmetaobject.h> +#include <qscrollview.h> +#include <qstring.h> +#include <qvaluelist.h> +#include <private/qucomextra_p.h> + +#include <cstdlib> +using std::abs; + +namespace Akregator { + + +// taken from KDevelop +class PageViewer::HistoryEntry +{ + public: + + KURL url; + QString title; + QByteArray state; + int id; + + HistoryEntry() {} + HistoryEntry(const KURL& u, const QString& t=QString::null): url(u), title(t) + { + id = abs( QTime::currentTime().msecsTo( QTime() ) ); // nasty, but should provide a reasonably unique number + } + +}; + +class PageViewer::PageViewerPrivate +{ + public: + + QValueList<HistoryEntry> history; + QValueList<HistoryEntry>::Iterator current; + + KToolBarPopupAction* backAction; + KToolBarPopupAction* forwardAction; + KAction* reloadAction; + KAction* stopAction; + + QString caption; +}; + + +PageViewer::PageViewer(QWidget *parent, const char *name) + : Viewer(parent, name), d(new PageViewerPrivate) +{ + // this hack is necessary since the part looks for []HTML Settings] in + // KGlobal::config() by default, which is wrong when running in Kontact + KHTMLSettings* s = const_cast<KHTMLSettings*> (settings()); + s->init(Settings::self()->config()); + + setXMLFile(locate("data", "akregator/pageviewer.rc"), true); + + QPair< KGuiItem, KGuiItem > backForward = KStdGuiItem::backAndForward(); + + d->backAction = new KToolBarPopupAction(backForward.first, + KStdAccel::shortcut(KStdAccel::Back), this, + SLOT(slotBack()), actionCollection(), + "pageviewer_back"); + + connect(d->backAction->popupMenu(), SIGNAL(aboutToShow()), + this, SLOT(slotBackAboutToShow())); + connect(d->backAction->popupMenu(), SIGNAL(activated(int)), + this, SLOT(slotPopupActivated(int))); + + + d->forwardAction = new KToolBarPopupAction(backForward.second, + KStdAccel::shortcut(KStdAccel::Forward),this, + SLOT(slotForward()), actionCollection(), + "pageviewer_forward"); + + connect(d->forwardAction->popupMenu(), SIGNAL(aboutToShow()), + this, SLOT(slotForwardAboutToShow())); + connect(d->forwardAction->popupMenu(), SIGNAL(activated(int)), + this, SLOT(slotPopupActivated(int))); + + d->reloadAction = new KAction(i18n("Reload"), "reload", 0, + this, SLOT(slotReload()), + actionCollection(), "pageviewer_reload"); + d->stopAction = new KAction(KStdGuiItem::guiItem(KStdGuiItem::Stop), 0, + this, SLOT(slotStop()), + actionCollection(), "pageviewer_stop"); + + //connect( this, SIGNAL(popupMenu(const QString &, const QPoint &)), this, SLOT(slotPopupMenu(const QString &, const QPoint &))); + + d->backAction->setEnabled(false); + d->forwardAction->setEnabled(false); + d->stopAction->setEnabled(false); + + connect( this, SIGNAL(setWindowCaption (const QString &)), + this, SLOT(slotSetCaption (const QString &)) ); + + connect(this, SIGNAL(started(KIO::Job *)), this, SLOT(slotStarted(KIO::Job* ))); + connect(this, SIGNAL(completed()), this, SLOT(slotCompleted())); + connect(this, SIGNAL(canceled(const QString &)), this, SLOT(slotCancelled(const QString &))); + + d->current = d->history.end(); + + // uncomment this to load konq plugins (doesn't work properly and clutters the GUI) + //loadPlugins( partObject(), this, instance() ); + +} + +PageViewer::~PageViewer() +{ + delete d; + d = 0; +} + +// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp) +void PageViewer::slotBack() +{ + if ( d->current != d->history.begin() ) + { + QValueList<HistoryEntry>::Iterator tmp = d->current; + --tmp; + restoreHistoryEntry(tmp); + } +} + +// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp) +void PageViewer::slotForward() +{ + if ( d->current != d->history.fromLast() && d->current != d->history.end() ) + { + QValueList<HistoryEntry>::Iterator tmp = d->current; + ++tmp; + restoreHistoryEntry(tmp); + } +} + +void PageViewer::slotBackAboutToShow() +{ + KPopupMenu *popup = d->backAction->popupMenu(); + popup->clear(); + + if ( d->current == d->history.begin() ) + return; + + QValueList<HistoryEntry>::Iterator it = d->current; + --it; + + int i = 0; + while( i < 10 ) + { + if ( it == d->history.begin() ) + { + popup->insertItem( (*it).title, (*it).id ); + return; + } + + popup->insertItem( (*it).title, (*it).id ); + ++i; + --it; + } +} + +void PageViewer::slotForwardAboutToShow() +{ + KPopupMenu *popup = d->forwardAction->popupMenu(); + popup->clear(); + + if ( d->current == d->history.fromLast() ) + return; + + QValueList<HistoryEntry>::Iterator it = d->current; + ++it; + + int i = 0; + while( i < 10 ) + { + if ( it == d->history.fromLast() ) + { + popup->insertItem( (*it).title, (*it).id ); + return; + } + + popup->insertItem( (*it).title, (*it).id ); + ++i; + ++it; + } +} + + +void PageViewer::slotReload() +{ + openURL( url() ); +} + +void PageViewer::slotStop() +{ + closeURL(); +} + +bool PageViewer::openURL(const KURL& url) +{ + updateHistoryEntry(); // update old history entry before switching to the new one + emit started(0); + + bool val = KHTMLPart::openURL(url); + + addHistoryEntry(url); // add new URL to history + + d->backAction->setEnabled( d->current != d->history.begin() ); + d->forwardAction->setEnabled( d->current != d->history.fromLast() ); + + QString favicon = FeedIconManager::self()->iconLocation(url); + if (!favicon.isEmpty()) + emit setTabIcon(QPixmap(KGlobal::dirs()->findResource("cache", favicon+".png"))); + else + emit setTabIcon(SmallIcon("html")); + + return val; +} + + +void PageViewer::slotOpenURLRequest(const KURL& url, const KParts::URLArgs& args) +{ + updateHistoryEntry(); + if (args.doPost()) + { + browserExtension()->setURLArgs(args); + openURL(url); + } + +} + +void PageViewer::slotPopupActivated( int id ) +{ + QValueList<HistoryEntry>::Iterator it = d->history.begin(); + while( it != d->history.end() ) + { + if ( (*it).id == id ) + { + restoreHistoryEntry(it); + return; + } + ++it; + } +} + +void PageViewer::updateHistoryEntry() +{ + (*d->current).title = d->caption; + (*d->current).state = QByteArray(); // Start with empty buffer. + QDataStream stream( (*d->current).state, IO_WriteOnly); + browserExtension()->saveState(stream); +} + +void PageViewer::restoreHistoryEntry(const QValueList<HistoryEntry>::Iterator& entry) +{ + updateHistoryEntry(); + + QDataStream stream( (*entry).state, IO_ReadOnly ); + browserExtension()->restoreState( stream ); + d->current = entry; + d->backAction->setEnabled( d->current != d->history.begin() ); + d->forwardAction->setEnabled( d->current != d->history.fromLast() ); + //openURL( entry.url ); // TODO read state + + +} + +// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp) +void PageViewer::addHistoryEntry(const KURL& url) +{ + QValueList<HistoryEntry>::Iterator it = d->current; + + // if We're not already the last entry, we truncate the list here before adding an entry + if ( it != d->history.end() && it != d->history.fromLast() ) + { + d->history.erase( ++it, d->history.end() ); + } + HistoryEntry newEntry( url, url.url() ); + + // Only save the new entry if it is different from the last + if ( newEntry.url != (*d->current).url ) + { + d->history.append( newEntry ); + d->current = d->history.fromLast(); + } + updateHistoryEntry(); +} + +// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp) +void PageViewer::slotStarted( KIO::Job * ) +{ + d->stopAction->setEnabled(true); +} + +// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp) +void PageViewer::slotCompleted( ) +{ + d->stopAction->setEnabled(false); +} + +// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp) +void PageViewer::slotCancelled( const QString & /*errMsg*/ ) +{ + d->stopAction->setEnabled(false); +} + +void PageViewer::urlSelected(const QString &url, int button, int state, const QString &_target, KParts::URLArgs args) +{ + if (url.startsWith(QString::fromLatin1( "javascript:" ), /*case-sensitive=*/false) ) + { + KHTMLPart::urlSelected(url,button,state,_target,args); + } + else + { + if (button == LeftButton) + { + m_url = completeURL(url); + browserExtension()->setURLArgs(args); + slotOpenLinkInThisTab(); + } + else + { + Viewer::urlSelected(url,button,state,_target,args); + } + } +} + +void PageViewer::slotSetCaption(const QString& cap) +{ + d->caption = cap; + (*d->current).title = cap; +} + +void PageViewer::slotPaletteOrFontChanged() +{ + kdDebug() << "PageViewer::slotPaletteOrFontChanged()" << endl; + // taken from KonqView (kdebase/konqueror/konq_view.cc) + + QObject *obj = KParts::BrowserExtension::childObject(this); + if ( !obj ) // not all views have a browser extension ! + return; + + int id = obj->metaObject()->findSlot("reparseConfiguration()"); + if (id == -1) + return; + QUObject o[1]; + + obj->qt_invoke(id, o); + + // this hack is necessary since the part looks for []HTML Settings] in + // KGlobal::config() by default, which is wrong when running in Kontact + // NOTE: when running in Kontact, immediate updating doesn't work + KHTMLSettings* s = const_cast<KHTMLSettings*> (settings()); + s->init(Settings::self()->config()); +} + +void PageViewer::slotGlobalBookmarkArticle() +{ + KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager(); + KBookmarkGroup grp = mgr->root(); + grp.addBookmark(mgr, d->caption, toplevelURL()); + mgr->emitChanged(grp); + mgr->save(); +} + + +void PageViewer::slotPopupMenu(KXMLGUIClient*, const QPoint& p, const KURL& kurl, const KParts::URLArgs&, KParts::BrowserExtension::PopupFlags kpf, mode_t) +{ + m_url = kurl; + QString url = kurl.url(); // maximal url confusion + + const bool showReload = (kpf & KParts::BrowserExtension::ShowReload) != 0; + const bool showNavigationItems = (kpf & KParts::BrowserExtension::ShowNavigationItems) != 0; + const bool isLink = (kpf & (KParts::BrowserExtension::ShowNavigationItems | KParts::BrowserExtension::ShowTextSelectionItems)) == 0; + const bool isSelection = (kpf & KParts::BrowserExtension::ShowTextSelectionItems) != 0; + + KPopupMenu popup(this->widget()); + + int idNewWindow = -2; + if (isLink) + { + idNewWindow = popup.insertItem(SmallIcon("tab_new"),i18n("Open Link in New &Tab"), this, SLOT(slotOpenLinkInForegroundTab())); + popup.setWhatsThis(idNewWindow, i18n("<b>Open Link in New Tab</b><p>Opens current link in a new tab.")); + popup.insertItem(SmallIcon("window_new"), i18n("Open Link in External &Browser"), this, SLOT(slotOpenLinkInBrowser())); + + popup.insertSeparator(); + action("savelinkas")->plug(&popup); + KAction* copylinkaddress = action("copylinkaddress"); + if (copylinkaddress) + { + copylinkaddress->plug( &popup); + //popup.insertSeparator(); + } + } + else // we are not on a link + { + if (showNavigationItems) + { + d->backAction->plug( &popup ); + d->forwardAction->plug( &popup ); + } + + if (showReload) + d->reloadAction->plug(&popup); + + d->stopAction->plug(&popup); + + popup.insertSeparator(); + + if (isSelection) + { + action("viewer_copy")->plug(&popup); + popup.insertSeparator(); + } + + KAction* incFontAction = this->action("incFontSizes"); + KAction* decFontAction = this->action("decFontSizes"); + if ( incFontAction && decFontAction ) + { + incFontAction->plug( &popup ); + decFontAction->plug( &popup ); + popup.insertSeparator(); + } + + popup.insertItem(SmallIcon("window_new"), i18n("Open Page in External Browser"), this, SLOT(slotOpenLinkInBrowser())); + + action("viewer_print")->plug(&popup); + popup.insertSeparator(); + + KAction *ac = action("setEncoding"); + if (ac) + ac->plug(&popup); + popup.insertItem(SmallIcon("bookmark_add"),i18n("Add to Konqueror Bookmarks"), this, SLOT(slotGlobalBookmarkArticle())); + } + + int r = popup.exec(p); + + if (r == idNewWindow) + { + KURL kurl; + if (!KURL(url).path().startsWith("/")) + { + kdDebug() << "processing relative url: " << url << endl; + if (url.startsWith("#")) + { + kurl = KURL(PageViewer::url()); + kurl.setRef(url.mid(1)); + } + else + kurl = KURL(PageViewer::url().upURL().url(true)+url); + } + else + kurl = KURL(url); +// kurl.addPath(url); + if (kurl.isValid()) { + //slotOpenInNewWindow(kurl); + } +// ( kurl ); + } +} + +} // namespace Akregator + +#include "pageviewer.moc" |