akregator/src

pageviewer.cpp
1/*
2 This file is part of Akregator.
3
4 Copyright (C) 2004 Sashmit Bhaduri <smt@vfemail.net>
5 2005 Frank Osterfeld <frank.osterfeld at kdemail.net>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
21 As a special exception, permission is given to link this program
22 with any edition of TQt, and distribute the resulting executable,
23 without including the source code for TQt in the source distribution.
24*/
25
26#include "akregatorconfig.h"
27#include "akregator_run.h"
28#include "feediconmanager.h"
29#include "pageviewer.h"
30#include "viewer.h"
31
32#include <tdeaction.h>
33#include <tdeapplication.h>
34#include <kbookmark.h>
35#include <kbookmarkmanager.h>
36#include <tdeconfig.h>
37#include <tdeglobalsettings.h>
38#include <tdehtml_settings.h>
39#include <tdehtmlview.h>
40#include <kiconloader.h>
41#include <tdelocale.h>
42#include <tdepopupmenu.h>
43#include <tdestandarddirs.h>
44#include <tdestdaccel.h>
45#include <tdeparts/browserinterface.h>
46
47#include <tqclipboard.h>
48#include <tqcstring.h>
49#include <tqdatastream.h>
50#include <tqdatetime.h>
51#include <tqfile.h>
52#include <tqmetaobject.h>
53#include <tqscrollview.h>
54#include <tqstring.h>
55#include <tqvaluelist.h>
56#include <private/tqucomextra_p.h>
57
58#include <cstdlib>
59using std::abs;
60
61namespace Akregator {
62
63
64// taken from KDevelop
65class PageViewer::HistoryEntry
66{
67 public:
68
69 KURL url;
70 TQString title;
71 TQByteArray state;
72 int id;
73
74 HistoryEntry() {}
75 HistoryEntry(const KURL& u, const TQString& t=TQString()): url(u), title(t)
76 {
77 id = abs( TQTime::currentTime().msecsTo( TQTime() ) ); // nasty, but should provide a reasonably unique number
78 }
79
80};
81
82class PageViewer::PageViewerPrivate
83{
84 public:
85
86 TQValueList<HistoryEntry> history;
87 TQValueList<HistoryEntry>::Iterator current;
88
89 TDEToolBarPopupAction* backAction;
90 TDEToolBarPopupAction* forwardAction;
91 TDEAction* reloadAction;
92 TDEAction* stopAction;
93
94 TQString caption;
95};
96
97
98PageViewer::PageViewer(TQWidget *parent, const char *name)
99 : Viewer(parent, name), d(new PageViewerPrivate)
100{
101 // this hack is necessary since the part looks for []HTML Settings] in
102 // TDEGlobal::config() by default, which is wrong when running in Kontact
103 TDEHTMLSettings* s = const_cast<TDEHTMLSettings*> (settings());
104 s->init(Settings::self()->config());
105
106 setXMLFile(locate("data", "akregator/pageviewer.rc"), true);
107
108 TQPair< KGuiItem, KGuiItem > backForward = KStdGuiItem::backAndForward();
109
110 d->backAction = new TDEToolBarPopupAction(backForward.first,
111 TDEStdAccel::shortcut(TDEStdAccel::Back), this,
112 TQ_SLOT(slotBack()), actionCollection(),
113 "pageviewer_back");
114
115 connect(d->backAction->popupMenu(), TQ_SIGNAL(aboutToShow()),
116 this, TQ_SLOT(slotBackAboutToShow()));
117 connect(d->backAction->popupMenu(), TQ_SIGNAL(activated(int)),
118 this, TQ_SLOT(slotPopupActivated(int)));
119
120
121 d->forwardAction = new TDEToolBarPopupAction(backForward.second,
122 TDEStdAccel::shortcut(TDEStdAccel::Forward),this,
123 TQ_SLOT(slotForward()), actionCollection(),
124 "pageviewer_forward");
125
126 connect(d->forwardAction->popupMenu(), TQ_SIGNAL(aboutToShow()),
127 this, TQ_SLOT(slotForwardAboutToShow()));
128 connect(d->forwardAction->popupMenu(), TQ_SIGNAL(activated(int)),
129 this, TQ_SLOT(slotPopupActivated(int)));
130
131 d->reloadAction = new TDEAction(i18n("Reload"), "reload", 0,
132 this, TQ_SLOT(slotReload()),
133 actionCollection(), "pageviewer_reload");
134 d->stopAction = new TDEAction(KStdGuiItem::guiItem(KStdGuiItem::Stop), 0,
135 this, TQ_SLOT(slotStop()),
136 actionCollection(), "pageviewer_stop");
137
138 //connect( this, TQ_SIGNAL(popupMenu(const TQString &, const TQPoint &)), this, TQ_SLOT(slotPopupMenu(const TQString &, const TQPoint &)));
139
140 d->backAction->setEnabled(false);
141 d->forwardAction->setEnabled(false);
142 d->stopAction->setEnabled(false);
143
144 connect( this, TQ_SIGNAL(setWindowCaption (const TQString &)),
145 this, TQ_SLOT(slotSetCaption (const TQString &)) );
146
147 connect(this, TQ_SIGNAL(started(TDEIO::Job *)), this, TQ_SLOT(slotStarted(TDEIO::Job* )));
148 connect(this, TQ_SIGNAL(completed()), this, TQ_SLOT(slotCompleted()));
149 connect(this, TQ_SIGNAL(canceled(const TQString &)), this, TQ_SLOT(slotCancelled(const TQString &)));
150
151 d->current = d->history.end();
152
153 // uncomment this to load konq plugins (doesn't work properly and clutters the GUI)
154 //loadPlugins( partObject(), this, instance() );
155
156}
157
158PageViewer::~PageViewer()
159{
160 delete d;
161 d = 0;
162}
163
164// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp)
165void PageViewer::slotBack()
166{
167 if ( d->current != d->history.begin() )
168 {
169 TQValueList<HistoryEntry>::Iterator tmp = d->current;
170 --tmp;
171 restoreHistoryEntry(tmp);
172 }
173}
174
175// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp)
176void PageViewer::slotForward()
177{
178 if ( d->current != d->history.fromLast() && d->current != d->history.end() )
179 {
180 TQValueList<HistoryEntry>::Iterator tmp = d->current;
181 ++tmp;
182 restoreHistoryEntry(tmp);
183 }
184}
185
186void PageViewer::slotBackAboutToShow()
187{
188 TDEPopupMenu *popup = d->backAction->popupMenu();
189 popup->clear();
190
191 if ( d->current == d->history.begin() )
192 return;
193
194 TQValueList<HistoryEntry>::Iterator it = d->current;
195 --it;
196
197 int i = 0;
198 while( i < 10 )
199 {
200 if ( it == d->history.begin() )
201 {
202 popup->insertItem( (*it).title, (*it).id );
203 return;
204 }
205
206 popup->insertItem( (*it).title, (*it).id );
207 ++i;
208 --it;
209 }
210}
211
212void PageViewer::slotForwardAboutToShow()
213{
214 TDEPopupMenu *popup = d->forwardAction->popupMenu();
215 popup->clear();
216
217 if ( d->current == d->history.fromLast() )
218 return;
219
220 TQValueList<HistoryEntry>::Iterator it = d->current;
221 ++it;
222
223 int i = 0;
224 while( i < 10 )
225 {
226 if ( it == d->history.fromLast() )
227 {
228 popup->insertItem( (*it).title, (*it).id );
229 return;
230 }
231
232 popup->insertItem( (*it).title, (*it).id );
233 ++i;
234 ++it;
235 }
236}
237
238
239void PageViewer::slotReload()
240{
241 openURL( url() );
242}
243
244void PageViewer::slotStop()
245{
246 closeURL();
247}
248
249bool PageViewer::openURL(const KURL& url)
250{
251 updateHistoryEntry(); // update old history entry before switching to the new one
252 emit started(0);
253
254 bool val = TDEHTMLPart::openURL(url);
255
256 addHistoryEntry(url); // add new URL to history
257
258 d->backAction->setEnabled( d->current != d->history.begin() );
259 d->forwardAction->setEnabled( d->current != d->history.fromLast() );
260
261 TQString favicon = FeedIconManager::self()->iconLocation(url);
262 if (!favicon.isEmpty())
263 emit setTabIcon(TQPixmap(TDEGlobal::dirs()->findResource("cache", favicon+".png")));
264 else
265 emit setTabIcon(SmallIcon("text-html"));
266
267 return val;
268}
269
270
271void PageViewer::slotOpenURLRequest(const KURL& url, const KParts::URLArgs& args)
272{
273 updateHistoryEntry();
274 if (args.doPost())
275 {
276 browserExtension()->setURLArgs(args);
277 openURL(url);
278 }
279
280}
281
282void PageViewer::slotPopupActivated( int id )
283{
284 TQValueList<HistoryEntry>::Iterator it = d->history.begin();
285 while( it != d->history.end() )
286 {
287 if ( (*it).id == id )
288 {
289 restoreHistoryEntry(it);
290 return;
291 }
292 ++it;
293 }
294}
295
296void PageViewer::updateHistoryEntry()
297{
298 (*d->current).title = d->caption;
299 (*d->current).state = TQByteArray(); // Start with empty buffer.
300 TQDataStream stream( (*d->current).state, IO_WriteOnly);
301 browserExtension()->saveState(stream);
302}
303
304void PageViewer::restoreHistoryEntry(const TQValueList<HistoryEntry>::Iterator& entry)
305{
306 updateHistoryEntry();
307
308 TQDataStream stream( (*entry).state, IO_ReadOnly );
309 browserExtension()->restoreState( stream );
310 d->current = entry;
311 d->backAction->setEnabled( d->current != d->history.begin() );
312 d->forwardAction->setEnabled( d->current != d->history.fromLast() );
313 //openURL( entry.url ); // TODO read state
314
315
316}
317
318// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp)
319void PageViewer::addHistoryEntry(const KURL& url)
320{
321 TQValueList<HistoryEntry>::Iterator it = d->current;
322
323 // if We're not already the last entry, we truncate the list here before adding an entry
324 if ( it != d->history.end() && it != d->history.fromLast() )
325 {
326 d->history.erase( ++it, d->history.end() );
327 }
328 HistoryEntry newEntry( url, url.url() );
329
330 // Only save the new entry if it is different from the last
331 if ( newEntry.url != (*d->current).url )
332 {
333 d->history.append( newEntry );
334 d->current = d->history.fromLast();
335 }
336 updateHistoryEntry();
337}
338
339// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp)
340void PageViewer::slotStarted( TDEIO::Job * )
341{
342 d->stopAction->setEnabled(true);
343}
344
345// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp)
346void PageViewer::slotCompleted( )
347{
348 d->stopAction->setEnabled(false);
349}
350
351// Taken from KDevelop (lib/widgets/kdevhtmlpart.cpp)
352void PageViewer::slotCancelled( const TQString & /*errMsg*/ )
353{
354 d->stopAction->setEnabled(false);
355}
356
357void PageViewer::urlSelected(const TQString &url, int button, int state, const TQString &_target, KParts::URLArgs args)
358{
359 if (url.startsWith(TQString::fromLatin1( "javascript:" ), /*case-sensitive=*/false) )
360 {
361 TDEHTMLPart::urlSelected(url,button,state,_target,args);
362 }
363 else
364 {
365 if (button == TQt::LeftButton)
366 {
367 m_url = completeURL(url);
368 browserExtension()->setURLArgs(args);
369 slotOpenLinkInThisTab();
370 }
371 else
372 {
373 Viewer::urlSelected(url,button,state,_target,args);
374 }
375 }
376}
377
378void PageViewer::slotSetCaption(const TQString& cap)
379{
380 d->caption = cap;
381 (*d->current).title = cap;
382}
383
384void PageViewer::slotPaletteOrFontChanged()
385{
386 kdDebug() << "PageViewer::slotPaletteOrFontChanged()" << endl;
387 // taken from KonqView (tdebase/konqueror/konq_view.cpp)
388
389 TQObject *obj = KParts::BrowserExtension::childObject(this);
390 if ( !obj ) // not all views have a browser extension !
391 return;
392
393 int id = obj->metaObject()->findSlot("reparseConfiguration()");
394 if (id == -1)
395 return;
396 TQUObject o[1];
397
398 obj->tqt_invoke(id, o);
399
400 // this hack is necessary since the part looks for []HTML Settings] in
401 // TDEGlobal::config() by default, which is wrong when running in Kontact
402 // NOTE: when running in Kontact, immediate updating doesn't work
403 TDEHTMLSettings* s = const_cast<TDEHTMLSettings*> (settings());
404 s->init(Settings::self()->config());
405}
406
407void PageViewer::slotGlobalBookmarkArticle()
408{
409 KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager();
410 KBookmarkGroup grp = mgr->root();
411 grp.addBookmark(mgr, d->caption, toplevelURL());
412 mgr->emitChanged(grp);
413 mgr->save();
414}
415
416
417void PageViewer::slotPopupMenu(KXMLGUIClient*, const TQPoint& p, const KURL& kurl, const KParts::URLArgs&, KParts::BrowserExtension::PopupFlags kpf, mode_t)
418{
419 m_url = kurl;
420 TQString url = kurl.url(); // maximal url confusion
421
422 const bool showReload = (kpf & KParts::BrowserExtension::ShowReload) != 0;
423 const bool showNavigationItems = (kpf & KParts::BrowserExtension::ShowNavigationItems) != 0;
424 const bool isLink = (kpf & (KParts::BrowserExtension::ShowNavigationItems | KParts::BrowserExtension::ShowTextSelectionItems)) == 0;
425 const bool isSelection = (kpf & KParts::BrowserExtension::ShowTextSelectionItems) != 0;
426
427 TDEPopupMenu popup(this->widget());
428
429 int idNewWindow = -2;
430 if (isLink)
431 {
432 idNewWindow = popup.insertItem(SmallIcon("tab_new"),i18n("Open Link in New &Tab"), this, TQ_SLOT(slotOpenLinkInForegroundTab()));
433 popup.setWhatsThis(idNewWindow, i18n("<b>Open Link in New Tab</b><p>Opens current link in a new tab."));
434 popup.insertItem(SmallIcon("window-new"), i18n("Open Link in External &Browser"), this, TQ_SLOT(slotOpenLinkInBrowser()));
435
436 popup.insertSeparator();
437 action("savelinkas")->plug(&popup);
438 TDEAction* copylinkaddress = action("copylinkaddress");
439 if (copylinkaddress)
440 {
441 copylinkaddress->plug( &popup);
442 //popup.insertSeparator();
443 }
444 }
445 else // we are not on a link
446 {
447 if (showNavigationItems)
448 {
449 d->backAction->plug( &popup );
450 d->forwardAction->plug( &popup );
451 }
452
453 if (showReload)
454 d->reloadAction->plug(&popup);
455
456 d->stopAction->plug(&popup);
457
458 popup.insertSeparator();
459
460 if (isSelection)
461 {
462 action("viewer_copy")->plug(&popup);
463 popup.insertSeparator();
464 }
465
466 TDEAction* incFontAction = this->action("incFontSizes");
467 TDEAction* decFontAction = this->action("decFontSizes");
468 if ( incFontAction && decFontAction )
469 {
470 incFontAction->plug( &popup );
471 decFontAction->plug( &popup );
472 popup.insertSeparator();
473 }
474
475 popup.insertItem(SmallIcon("window-new"), i18n("Open Page in External Browser"), this, TQ_SLOT(slotOpenLinkInBrowser()));
476
477 action("viewer_print")->plug(&popup);
478 popup.insertSeparator();
479
480 TDEAction *ac = action("setEncoding");
481 if (ac)
482 ac->plug(&popup);
483 popup.insertItem(SmallIcon("bookmark_add"),i18n("Add to Konqueror Bookmarks"), this, TQ_SLOT(slotGlobalBookmarkArticle()));
484 }
485
486 int r = popup.exec(p);
487
488 if (r == idNewWindow)
489 {
490 KURL kurl;
491 if (!KURL(url).path().startsWith("/"))
492 {
493 kdDebug() << "processing relative url: " << url << endl;
494 if (url.startsWith("#"))
495 {
496 kurl = KURL(PageViewer::url());
497 kurl.setRef(url.mid(1));
498 }
499 else
500 kurl = KURL(PageViewer::url().upURL().url(true)+url);
501 }
502 else
503 kurl = KURL(url);
504// kurl.addPath(url);
505 if (kurl.isValid()) {
506 //slotOpenInNewWindow(kurl);
507 }
508// ( kurl );
509 }
510}
511
512} // namespace Akregator
513
514#include "pageviewer.moc"