KHtml

khtmlimage.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2000 Simon Hausmann <[email protected]>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "khtmlimage.h"
21 #include "khtmlview.h"
22 #include "khtml_ext.h"
23 #include "xml/dom_docimpl.h"
24 #include "html/html_documentimpl.h"
25 #include "html/html_elementimpl.h"
26 #include "rendering/render_image.h"
27 #include "misc/loader.h"
28 
29 #include <QTimer>
30 #include <QVBoxLayout>
31 
32 #include <kparts/guiactivateevent.h>
33 #include <kjobuidelegate.h>
34 #include <kio/job.h>
35 #include <qmimedatabase.h>
36 #include <klocalizedstring.h>
37 #include <kactioncollection.h>
38 #include <kaboutdata.h>
39 
40 #include "../khtml_version.h"
41 
42 
43 KHTMLImage::KHTMLImage(QWidget *parentWidget,
44  QObject *parent, const QVariantList &args)
45  : KParts::ReadOnlyPart(parent), m_image(nullptr)
46 {
47  KHTMLPart *parentPart = qobject_cast<KHTMLPart *>(parent);
48 
49  KAboutData about("khtmlimage", i18n("KHTML Image"), QStringLiteral(KHTML_VERSION_STRING));
50  KHTMLPart::GUIProfile prof = KHTMLPart::DefaultGUI;
51  if (args.contains("Browser/View")) {
52  prof = KHTMLPart::BrowserViewGUI;
53  }
54  setComponentData(about, prof == KHTMLPart::BrowserViewGUI && !parentPart);
55 
56  QWidget *box = new QWidget(parentWidget);
57  box->setLayout(new QVBoxLayout(box));
58  box->setAcceptDrops(true);
59 
60  m_khtml = new KHTMLPart(box, this, prof);
61  box->layout()->addWidget(m_khtml->widget());
62  m_khtml->setAutoloadImages(true);
63 
64  // We do not want our subpart to be destroyed when its widget is,
65  // since that may cause all KHTMLParts to die when we're dealing
66  // with
67  m_khtml->setAutoDeletePart(false);
68 
69  connect(m_khtml->view(), SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
70 
71  setWidget(box);
72 
73  // VBox can't take focus, so pass it on to sub-widget
74  box->setFocusProxy(m_khtml->widget());
75 
76  m_ext = new KHTMLImageBrowserExtension(this);
77  m_ext->setObjectName("be");
78 
79  m_sbExt = new KParts::StatusBarExtension(this);
80  m_sbExt->setObjectName("sbe");
81 
82  // Remove unnecessary actions.
83  delete actionCollection()->action("setEncoding");
84  delete actionCollection()->action("viewDocumentSource");
85  delete actionCollection()->action("selectAll");
86 
87  // forward important signals from the khtml part
88 
89  // forward opening requests to parent frame (if existing)
90  KHTMLPart *p = qobject_cast<KHTMLPart *>(parent);
91  KParts::BrowserExtension *be = p ? p->browserExtension() : m_ext;
92  connect(m_khtml->browserExtension(), SIGNAL(openUrlRequestDelayed(QUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)),
93  be, SIGNAL(openUrlRequestDelayed(QUrl,KParts::OpenUrlArguments,KParts::BrowserArguments)));
94 
97 
98  connect(m_khtml->browserExtension(), SIGNAL(enableAction(const char*,bool)),
99  m_ext, SIGNAL(enableAction(const char*,bool)));
100 
101  m_ext->setURLDropHandlingEnabled(true);
102 }
103 
104 KHTMLImage::~KHTMLImage()
105 {
106  disposeImage();
107 
108  // important: delete the html part before the part or qobject destructor runs.
109  // we now delete the htmlpart which deletes the part's widget which makes
110  // _OUR_ m_widget 0 which in turn avoids our part destructor to delete the
111  // widget ;-)
112  // ### additional note: it _can_ be that the part has been deleted before:
113  // when we're in a html frameset and the view dies first, then it will also
114  // kill the htmlpart
115  if (m_khtml) {
116  delete static_cast<KHTMLPart *>(m_khtml);
117  }
118 }
119 
120 bool KHTMLImage::openUrl(const QUrl &url)
121 {
122  static const QString &html = QString::fromLatin1("<html><body><img src=\"%1\"></body></html>");
123 
124  // Propagate statusbar to our kid part.
125  KParts::StatusBarExtension::childObject(m_khtml)->setStatusBar(m_sbExt->statusBar());
126 
127  disposeImage();
128 
129  setUrl(url);
130 
131  emit started(nullptr);
132 
133  KParts::OpenUrlArguments args = arguments();
134  m_mimeType = args.mimeType();
135 
136  QUrl kurl(url);
137  emit setWindowCaption(kurl.toDisplayString());
138 
139  // Need to keep a copy of the offsets since they are cleared when emitting completed
140  m_xOffset = args.xOffset();
141  m_yOffset = args.yOffset();
142 
143  m_khtml->begin(this->url());
144  m_khtml->setAutoloadImages(true);
145 
146  DOM::DocumentImpl *impl = dynamic_cast<DOM::DocumentImpl *>(m_khtml->document().handle()); // ### hack ;-)
147  if (!impl) {
148  return false;
149  }
150 
151  if (arguments().reload()) {
152  impl->docLoader()->setCachePolicy(KIO::CC_Reload);
153  }
154 
155  khtml::DocLoader *dl = impl->docLoader();
156  m_image = dl->requestImage(this->url().toString());
157  if (m_image) {
158  m_image->ref(this);
159  }
160 
161  m_khtml->write(html.arg(this->url().toString()));
162  m_khtml->end();
163 
164  /*
165  connect( khtml::Cache::loader(), SIGNAL(requestDone(khtml::DocLoader*,khtml::CachedObject*)),
166  this, SLOT(updateWindowCaption()) );
167  */
168  return true;
169 }
170 
171 bool KHTMLImage::closeUrl()
172 {
173  disposeImage();
174  return m_khtml->closeUrl();
175 }
176 
177 // This can happen after openUrl returns, or directly from m_image->ref()
178 void KHTMLImage::notifyFinished(khtml::CachedObject *o)
179 {
180  if (!m_image || o != m_image) {
181  return;
182  }
183 
184  //const QPixmap &pix = m_image->pixmap();
186 
187  QMimeDatabase db;
189  if (!m_mimeType.isEmpty()) {
190  mimeType = db.mimeTypeForName(m_mimeType);
191  }
192 
193  if (mimeType.isValid()) {
194  if (!m_image->suggestedTitle().isEmpty()) {
195  caption = i18n("%1 (%2 - %3x%4 Pixels)", m_image->suggestedTitle(), mimeType.comment(), m_image->pixmap_size().width(), m_image->pixmap_size().height());
196  } else {
197  caption = i18n("%1 - %2x%3 Pixels", mimeType.comment(),
198  m_image->pixmap_size().width(), m_image->pixmap_size().height());
199  }
200  } else {
201  if (!m_image->suggestedTitle().isEmpty()) {
202  caption = i18n("%1 (%2x%3 Pixels)", m_image->suggestedTitle(), m_image->pixmap_size().width(), m_image->pixmap_size().height());
203  } else {
204  caption = i18n("Image - %1x%2 Pixels", m_image->pixmap_size().width(), m_image->pixmap_size().height());
205  }
206  }
207 
208  emit setWindowCaption(caption);
209  emit completed();
210  emit setStatusBarText(i18n("Done."));
211 }
212 
213 void KHTMLImage::restoreScrollPosition()
214 {
215  if (m_khtml->view()->contentsY() == 0) {
216  m_khtml->view()->setContentsPos(m_xOffset, m_yOffset);
217  }
218 }
219 
220 void KHTMLImage::guiActivateEvent(KParts::GUIActivateEvent *e)
221 {
222  // prevent the base implementation from emitting setWindowCaption with
223  // our url. It destroys our pretty, previously caption. Konq saves/restores
224  // the caption for us anyway.
225  if (e->activated()) {
226  return;
227  }
229 }
230 
231 /*
232 void KHTMLImage::slotImageJobFinished( KIO::Job *job )
233 {
234  if ( job->error() )
235  {
236  job->uiDelegate()->showErrorMessage();
237  emit canceled( job->errorString() );
238  }
239  else
240  {
241  emit completed();
242  QTimer::singleShot( 0, this, SLOT(updateWindowCaption()) );
243  }
244 }
245 
246 void KHTMLImage::updateWindowCaption()
247 {
248  if ( !m_khtml )
249  return;
250 
251  DOM::HTMLDocumentImpl *impl = dynamic_cast<DOM::HTMLDocumentImpl *>( m_khtml->document().handle() );
252  if ( !impl )
253  return;
254 
255  DOM::HTMLElementImpl *body = impl->body();
256  if ( !body )
257  return;
258 
259  DOM::NodeImpl *image = body->firstChild();
260  if ( !image )
261  return;
262 
263  khtml::RenderImage *renderImage = dynamic_cast<khtml::RenderImage *>( image->renderer() );
264  if ( !renderImage )
265  return;
266 
267  QPixmap pix = renderImage->pixmap();
268 
269  QString caption;
270 
271  KMimeType::Ptr mimeType;
272  if ( !m_mimeType.isEmpty() )
273  mimeType = KMimeType::mimeType( m_mimeType, KMimeType::ResolveAliases );
274 
275  if ( mimeType )
276  caption = i18n( "%1 - %2x%3 Pixels" ).arg( mimeType.comment() )
277  .arg( pix.width() ).arg( pix.height() );
278  else
279  caption = i18n( "Image - %1x%2 Pixels" ).arg( pix.width() ).arg( pix.height() );
280 
281  emit setWindowCaption( caption );
282  emit completed();
283  emit setStatusBarText(i18n("Done."));
284 }
285 */
286 
287 void KHTMLImage::disposeImage()
288 {
289  if (!m_image) {
290  return;
291  }
292 
293  m_image->deref(this);
294  m_image = nullptr;
295 }
296 
297 KHTMLImageBrowserExtension::KHTMLImageBrowserExtension(KHTMLImage *parent)
298  : KParts::BrowserExtension(parent)
299 {
300  m_imgPart = parent;
301 }
302 
303 int KHTMLImageBrowserExtension::xOffset()
304 {
305  return m_imgPart->doc()->view()->contentsX();
306 }
307 
308 int KHTMLImageBrowserExtension::yOffset()
309 {
310  return m_imgPart->doc()->view()->contentsY();
311 }
312 
313 void KHTMLImageBrowserExtension::print()
314 {
315  static_cast<KHTMLPartBrowserExtension *>(m_imgPart->doc()->browserExtension())->print();
316 }
317 
318 void KHTMLImageBrowserExtension::reparseConfiguration()
319 {
320  static_cast<KHTMLPartBrowserExtension *>(m_imgPart->doc()->browserExtension())->reparseConfiguration();
321  m_imgPart->doc()->setAutoloadImages(true);
322 }
323 
324 void KHTMLImageBrowserExtension::disableScrolling()
325 {
326  static_cast<KHTMLPartBrowserExtension *>(m_imgPart->doc()->browserExtension())->disableScrolling();
327 }
328 
329 void KHTMLImage::slotPopupMenu(const QPoint &global, const QUrl &url, mode_t mode,
330  const KParts::OpenUrlArguments &origArgs,
331  const KParts::BrowserArguments &browserArgs,
333  const KParts::BrowserExtension::ActionGroupMap &actionGroups)
334 {
335  KParts::OpenUrlArguments args = origArgs;
336  args.setMimeType(m_mimeType);
337  m_ext->popupMenu(global, url, mode, args, browserArgs, flags, actionGroups);
338 }
339 
QLayout * layout() const const
QString caption()
void setStatusBar(QStatusBar *status)
void about(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
void setURLDropHandlingEnabled(bool enable)
This class is khtml&#39;s main class.
Definition: khtml_part.h:208
QString mimeType() const
void setLayout(QLayout *layout)
KParts::BrowserExtension * browserExtension() const
Returns a pointer to the KParts::BrowserExtension.
void setFocusProxy(QWidget *w)
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
void addWidget(QWidget *w)
const QList< QKeySequence > & print()
void setAcceptDrops(bool on)
bool isValid() const const
QString i18n(const char *text, const TYPE &arg...)
char * toString(const T &value)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
This is the BrowserExtension for a KHTMLPart document.
Definition: khtml_ext.h:45
static StatusBarExtension * childObject(QObject *obj)
QString fromLatin1(const char *str, int size)
void reparseConfiguration(const QString &componentName)
QString mimeType(Type)
void guiActivateEvent(GUIActivateEvent *event) override
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Fri Oct 15 2021 22:48:07 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.