KHtml

render_form.cpp
1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll ([email protected])
5  * (C) 1999 Antti Koivisto ([email protected])
6  * (C) 2000 Dirk Mueller ([email protected])
7  * (C) 2006 Maksim Orlovich ([email protected])
8  * (C) 2007-2009 Germain Garand ([email protected])
9  * (C) 2007 Mitz Pettel ([email protected])
10  * (C) 2007 Charles Samuels ([email protected])
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB. If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  *
27  */
28 
29 #include "render_form.h"
30 
31 #include <kcompletionbox.h>
32 #include <kcursor.h>
33 #include "khtml_debug.h"
34 #include <kfind.h>
35 #include <kfinddialog.h>
36 #include <klocalizedstring.h>
37 #include <kmessagebox.h>
38 #include <kreplace.h>
39 #include <kreplacedialog.h>
40 #include <sonnet/dialog.h>
41 #include <kurlcompletion.h>
42 #include <kwindowsystem.h>
43 #include <kstandardaction.h>
44 #include <kactioncollection.h>
45 #include <kdesktopfile.h>
46 #include <kconfiggroup.h>
47 #include <kbuildsycocaprogressdialog.h>
48 #include <kservicetypetrader.h>
49 #include <kservice.h>
50 #include <sonnet/backgroundchecker.h>
51 #include <sonnet/dialog.h>
52 
53 #include <QAbstractItemView>
54 #include <QAbstractTextDocumentLayout>
55 #include <QDialog>
56 #include <QDialogButtonBox>
57 #include <QDir>
58 #include <QStyle>
59 #include <QStyleOptionButton>
60 #include <QLabel>
61 #include <QStyleOptionFrame>
62 #include <QStandardItemModel>
63 
64 #include <misc/helper.h>
65 #include <xml/dom2_eventsimpl.h>
66 #include <html/html_formimpl.h>
67 #include <html/html_miscimpl.h>
68 
69 #include <assert.h>
70 
71 #include <khtmlview.h>
72 #include <khtml_ext.h>
73 #include <xml/dom_docimpl.h>
74 
75 #include <QMenu>
76 #include <QBitmap>
77 #include <QHBoxLayout>
78 #include <QVBoxLayout>
79 
80 using namespace khtml;
81 using namespace DOM;
82 
83 // ----------------- proxy style used to apply some CSS properties to native Qt widgets -----------------
84 
85 struct KHTMLProxyStyle : public QProxyStyle {
86  KHTMLProxyStyle(QStyle *parent)
87  : QProxyStyle(parent)
88  {
89  noBorder = false;
90  left = right = top = bottom = 0;
91  clearButtonOverlay = 0;
92  }
93 
94  QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const override
95  {
96  QRect r = QProxyStyle::subElementRect(element, option, widget);
97  switch (element) {
101  r.adjust(left, top, -qMax(0, right - clearButtonOverlay), -bottom);
102  default:
103  break;
104  }
105  return r;
106  }
107 
108  void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override
109  {
110  if (element == QStyle::CE_ComboBoxLabel) {
111  const QStyleOptionComboBox *o = qstyleoption_cast<const QStyleOptionComboBox *>(option);
112  if (o) {
113  QStyleOptionComboBox comboOpt = *o;
114  comboOpt.currentText = comboOpt.currentText.trimmed();
115  // by default combobox label is drawn left justified, vertical centered
116  // translate it to reflect padding values
117  comboOpt.rect.translate(left, (top - bottom) / 2);
118  if (noBorder) {
119  // Need to expand a bit for some styles
120  comboOpt.rect.adjust(-1, -2, 1, 2);
121  comboOpt.state &= ~State_On;
122  }
123  return QProxyStyle::drawControl(element, &comboOpt, painter, widget);
124  }
125  }
126 
127  QProxyStyle::drawControl(element, option, painter, widget);
128  }
129 
130  void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *painter, const QWidget *widget) const override
131  {
132  if ((cc == QStyle::CC_ComboBox) && noBorder) {
133  if (const QStyleOptionComboBox *cbOpt = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
134  bool enabled = (cbOpt->state & State_Enabled);
135  QColor color = cbOpt->palette.color(QPalette::ButtonText);
136  painter->save();
138  painter->setPen(color);
140  // Drop down indicator
141  QRect arrowRect = QProxyStyle::subControlRect(cc, opt, SC_ComboBoxArrow, widget);
142  arrowRect.setTop(cbOpt->rect.top());
143  arrowRect.setBottom(cbOpt->rect.bottom());
144  arrowRect.setRight(cbOpt->rect.right() - 1);
145  if (enabled && (cbOpt->state & State_On)) {
146  arrowRect.translate(1, 1); // push effect
147  }
148  //if (!enabled) color = color.lighter();
149  painter->setBrush(enabled ? QBrush(color, Qt::SolidPattern) : Qt::NoBrush);
150  QPolygon cbArrowDown;
151  cbArrowDown.setPoints(6, 3, -2, 4, -2, 0, 2, -4, -2, -3, -2, 0, 1);
152  cbArrowDown.translate((arrowRect.x() + (arrowRect.width() >> 1)), (arrowRect.y() + (arrowRect.height() >> 1)));
153  painter->drawPolygon(cbArrowDown);
154  // Focus rect (from qcleanlooksstyle)
155  if (enabled && (cbOpt->state & State_HasFocus)) {
156  QRect focusRect = QProxyStyle::subElementRect(SE_ComboBoxFocusRect, cbOpt, widget);
157  focusRect.adjust(0, -2, 0, 2);
158  painter->setBrush(QBrush(color, Qt::Dense4Pattern));
159  painter->setBrushOrigin(focusRect.topLeft());
160  painter->setPen(Qt::NoPen);
161  const QRect rects[4] = {
162  QRect(focusRect.left(), focusRect.top(), focusRect.width(), 1), // Top
163  QRect(focusRect.left(), focusRect.bottom(), focusRect.width(), 1), // Bottom
164  QRect(focusRect.left(), focusRect.top(), 1, focusRect.height()), // Left
165  QRect(focusRect.right(), focusRect.top(), 1, focusRect.height()) // Right
166  };
167  painter->drawRects(rects, 4);
168  }
169  painter->restore();
170 
171  return;
172  }
173  }
174 
175  QProxyStyle::drawComplexControl(cc, opt, painter, widget);
176  }
177 
178  QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const override
179  {
180  // Make sure we give combo popup's enough room to display contents;
181  // Qt doesn't do this by default
182 
183  if (cc == QStyle::CC_ComboBox && sc == SC_ComboBoxListBoxPopup) {
184  const QComboBox *cb = qobject_cast<const QComboBox *>(widget);
185  const QStyleOptionComboBox *cbOpt = qstyleoption_cast<const QStyleOptionComboBox *>(opt);
186 
187  if (cb && cbOpt) {
188  QFontMetrics fm = cb->fontMetrics();
189  // Compute content width; Qt uses the usual +4 magic number for icon/text margin
190  int maxW = 0;
191  for (int c = 0; c < cb->count(); ++c) {
192  int iw = fm.width(cb->itemText(c));
193  if (!cb->itemIcon(c).isNull()) {
194  iw += 4 + cb->iconSize().width();
195  }
196  maxW = qMax(maxW, iw);
197  }
198 
199  // Now let sizeFromContent add in extra stuff.
200  maxW = QProxyStyle::sizeFromContents(QStyle::CT_ComboBox, opt, QSize(maxW, 1), widget).width();
201 
202  // How much more room do we need for the text?
203  int extraW = maxW > cbOpt->rect.width() ? maxW - cbOpt->rect.width() : 0;
204 
205  QRect r = QProxyStyle::subControlRect(cc, opt, sc, widget);
206  r.setWidth(r.width() + extraW);
207  return r;
208  }
209  }
210 
211  return QProxyStyle::subControlRect(cc, opt, sc, widget);
212  }
213 
214  int left, right, top, bottom;
215  int clearButtonOverlay;
216  bool noBorder;
217 };
218 
219 // ---------------------------------------------------------------------
220 
221 RenderFormElement::RenderFormElement(HTMLGenericFormElementImpl *element)
222  : RenderWidget(element)
223 // , m_state(0)
224  , m_proxyStyle(nullptr)
225  , m_exposeInternalPadding(false)
226  , m_isOxygenStyle(false)
227 {
228  // init RenderObject attributes
229  setInline(true); // our object is Inline
230 }
231 
232 RenderFormElement::~RenderFormElement()
233 {}
234 
235 void RenderFormElement::setStyle(RenderStyle *_style)
236 {
237  RenderWidget::setStyle(_style);
238  setPadding();
239  if (!shouldDisableNativeBorders()) {
240  // When the widget shows native border, clipping background to border
241  // results in a nasty rendering effects
242  if (style()->backgroundLayers()->backgroundClip() == BGBORDER) {
243  style()->accessBackgroundLayers()->setBackgroundClip(BGPADDING);
244  }
245  m_isOxygenStyle = QApplication::style()->objectName().contains("oxygen");
246  }
247 }
248 
249 int RenderFormElement::paddingTop() const
250 {
251  return (!includesPadding() || m_exposeInternalPadding) ? RenderWidget::paddingTop() : 0;
252 }
253 int RenderFormElement::paddingBottom() const
254 {
255  return (!includesPadding() || m_exposeInternalPadding) ? RenderWidget::paddingBottom() : 0;
256 }
257 int RenderFormElement::paddingLeft() const
258 {
259  return (!includesPadding() || m_exposeInternalPadding) ? RenderWidget::paddingLeft() : 0;
260 }
261 int RenderFormElement::paddingRight() const
262 {
263  return (!includesPadding() || m_exposeInternalPadding) ? RenderWidget::paddingRight() : 0;
264 }
265 
266 bool RenderFormElement::includesPadding() const
267 {
268  return true;
269 }
270 
271 void RenderFormElement::setPadding()
272 {
273  if (!includesPadding()) {
274  return;
275  }
276 
277  KHTMLProxyStyle *style = static_cast<KHTMLProxyStyle *>(getProxyStyle());
278  style->left = RenderWidget::paddingLeft();
279  style->right = RenderWidget::paddingRight();
280  style->top = RenderWidget::paddingTop();
281  style->bottom = RenderWidget::paddingBottom();
282 }
283 
284 QProxyStyle *RenderFormElement::getProxyStyle()
285 {
286  assert(widget());
287  if (m_proxyStyle) {
288  return m_proxyStyle;
289  }
290  m_proxyStyle = new KHTMLProxyStyle(widget()->style());
291  widget()->setStyle(m_proxyStyle);
292  return m_proxyStyle;
293 }
294 
295 short RenderFormElement::baselinePosition(bool f) const
296 {
297  return RenderWidget::baselinePosition(f) - 2 - style()->fontMetrics().descent();
298 }
299 
300 void RenderFormElement::setQWidget(QWidget *w)
301 {
302  // Avoid dangling proxy pointer when we switch widgets.
303  // the widget will cleanup the proxy, as it is its kid.
304  m_proxyStyle = nullptr;
305 
306  // sets the Qt Object Name for the purposes
307  // of setPadding() -- this is because QStyleSheet
308  // will propagate children of 'w' even if they are toplevel, like
309  // the "find" dialog or the popup menu
310  w->setObjectName("RenderFormElementWidget");
311  RenderWidget::setQWidget(w);
312 }
313 
314 void RenderFormElement::updateFromElement()
315 {
316  m_widget->setEnabled(!element()->disabled());
317 
318  // If we've disabled a focused element, clear its focus,
319  // so Qt doesn't do funny stuff like let one type into a disabled
320  // line edit.
321  if (element()->disabled() && element()->focused()) {
322  document()->quietResetFocus();
323  }
324 
325  RenderWidget::updateFromElement();
326 }
327 
328 // Some form widgets apply the padding internally (i.e. as if they were
329 // some kind of inline-block). Thus we only want to expose that padding
330 // while layouting (so that width/height calculations are correct), and
331 // then pretend it does not exist, as it is beyond the replaced edge and
332 // thus should not affect other calculations.
333 
334 void RenderFormElement::calcMinMaxWidth()
335 {
336  m_exposeInternalPadding = true;
337  RenderWidget::calcMinMaxWidth();
338  m_exposeInternalPadding = false;
339 }
340 
341 void RenderFormElement::calcWidth()
342 {
343  m_exposeInternalPadding = true;
344  RenderWidget::calcWidth();
345  m_exposeInternalPadding = false;
346 }
347 
348 void RenderFormElement::calcHeight()
349 {
350  m_exposeInternalPadding = true;
351  RenderWidget::calcHeight();
352  m_exposeInternalPadding = false;
353 }
354 
355 void RenderFormElement::layout()
356 {
357  KHTMLAssert(needsLayout());
358  KHTMLAssert(minMaxKnown());
359 
360  // minimum height
361  m_height = 0;
362  calcWidth();
363  calcHeight();
364 
365  if (m_widget)
366  resizeWidget(m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight(),
367  m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom());
368 
369  setNeedsLayout(false);
370 }
371 
372 int RenderFormElement::calcContentWidth(int w) const
373 {
374  if (!shouldDisableNativeBorders()) {
375  if (style()->boxSizing() == CONTENT_BOX) {
376  int nativeBorderWidth = m_widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, m_widget);
377  return RenderBox::calcContentWidth(w) + 2 * nativeBorderWidth;
378  }
379  }
380 
381  return RenderBox::calcContentWidth(w);
382 }
383 
384 int RenderFormElement::calcContentHeight(int h) const
385 {
386  if (!shouldDisableNativeBorders()) {
387  if (style()->boxSizing() == CONTENT_BOX) {
388  int nativeBorderWidth = m_widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, m_widget);
389  return RenderBox::calcContentHeight(h) + 2 * nativeBorderWidth;
390  }
391  }
392 
393  return RenderBox::calcContentHeight(h);
394 }
395 
396 void RenderFormElement::paintOneBackground(QPainter *p, const QColor &c, const BackgroundLayer *bgLayer, QRect clipr, int _tx, int _ty, int w, int height)
397 {
398  int fudge = 0;
399  if (!shouldDisableNativeBorders()) {
400  fudge = m_isOxygenStyle ? 3 : 1;
401  }
402 
403  paintBackgroundExtended(p, c, bgLayer, clipr, _tx, _ty, w, height,
404  fudge ? fudge : borderLeft(), fudge ? fudge : borderRight(), RenderWidget::paddingLeft(), RenderWidget::paddingRight(),
405  fudge ? fudge : borderTop(), fudge ? fudge : borderBottom(), RenderWidget::paddingTop(), RenderWidget::paddingBottom());
406 }
407 
408 Qt::Alignment RenderFormElement::textAlignment() const
409 {
410  switch (style()->textAlign()) {
411  case LEFT:
412  case KHTML_LEFT:
413  return Qt::AlignLeft;
414  case RIGHT:
415  case KHTML_RIGHT:
416  return Qt::AlignRight;
417  case CENTER:
418  case KHTML_CENTER:
419  return Qt::AlignHCenter;
420  case JUSTIFY:
421  // Just fall into the auto code for justify.
422  case TAAUTO:
423  return style()->direction() == RTL ? Qt::AlignRight : Qt::AlignLeft;
424  }
425  assert(false); // Should never be reached.
426  return Qt::AlignLeft;
427 }
428 
429 // -------------------------------------------------------------------------
430 
431 RenderButton::RenderButton(HTMLGenericFormElementImpl *element)
432  : RenderFormElement(element)
433 {
434  m_hasTextIndentHack = false;
435 }
436 
437 short RenderButton::baselinePosition(bool f) const
438 {
439  int ret = (height() - RenderWidget::paddingTop() - RenderWidget::paddingBottom() + 1) / 2;
440  ret += marginTop() + RenderWidget::paddingTop();
441  ret += ((fontMetrics(f).ascent()) / 2) - 1;
442  return ret;
443 }
444 
445 void RenderButton::layout()
446 {
447  RenderFormElement::layout();
448  bool needsTextIndentHack = false;
449  if (!style()->width().isAuto()) {
450  // check if we need to simulate the effect of a popular
451  // button text hiding 'trick' that makes use of negative text-indent,
452  // which we do not support on form widgets.
453  int ti = style()->textIndent().minWidth(containingBlockWidth());
454  if (m_widget->width() <= qAbs(ti)) {
455  needsTextIndentHack = true;
456  }
457  }
458  if (m_hasTextIndentHack != needsTextIndentHack) {
459  m_hasTextIndentHack = needsTextIndentHack;
460  updateFromElement();
461  }
462 }
463 
464 void RenderButton::setStyle(RenderStyle *style)
465 {
466  RenderFormElement::setStyle(style);
467  if (shouldDisableNativeBorders()) {
468  // we paint the borders ourselves on this button,
469  // remove the widget's native ones.
470  KHTMLProxyStyle *style = static_cast<KHTMLProxyStyle *>(getProxyStyle());
471  style->noBorder = true;
472  }
473 }
474 
475 // -------------------------------------------------------------------------------
476 
477 RenderCheckBox::RenderCheckBox(HTMLInputElementImpl *element)
478  : RenderButton(element)
479 {
480  CheckBoxWidget *b = new CheckBoxWidget(view()->widget());
481  //b->setAutoMask(true);
482  b->setMouseTracking(true);
483  setQWidget(b);
484 
485  // prevent firing toggled() signals on initialization
486  b->setChecked(element->checked());
487 
488  connect(b, SIGNAL(stateChanged(int)), this, SLOT(slotStateChanged(int)));
489  m_ignoreStateChanged = false;
490 }
491 
492 void RenderCheckBox::calcMinMaxWidth()
493 {
494  KHTMLAssert(!minMaxKnown());
495 
496  QCheckBox *cb = static_cast<QCheckBox *>(m_widget);
497  QSize s(qMin(22, qMax(14, cb->style()->pixelMetric(QStyle::PM_IndicatorWidth))),
498  qMin(22, qMax(12, cb->style()->pixelMetric(QStyle::PM_IndicatorHeight))));
499  setIntrinsicWidth(s.width());
500  setIntrinsicHeight(s.height());
501 
502  RenderButton::calcMinMaxWidth();
503 }
504 
505 void RenderCheckBox::updateFromElement()
506 {
507  if (widget()->isChecked() != element()->checked()) {
508  m_ignoreStateChanged = true;
509  widget()->setChecked(element()->checked());
510  m_ignoreStateChanged = false;
511  }
512 
513  RenderButton::updateFromElement();
514 }
515 
516 void RenderCheckBox::slotStateChanged(int state)
517 {
518  if (m_ignoreStateChanged) {
519  return;
520  }
521  element()->setChecked(state == Qt::Checked);
522 }
523 
524 bool RenderCheckBox::handleEvent(const DOM::EventImpl &ev)
525 {
526  switch (ev.id()) {
527  case EventImpl::DOMFOCUSIN_EVENT:
528  case EventImpl::DOMFOCUSOUT_EVENT:
529  case EventImpl::MOUSEMOVE_EVENT:
530  case EventImpl::MOUSEOUT_EVENT:
531  case EventImpl::MOUSEOVER_EVENT:
532  return RenderButton::handleEvent(ev);
533  default:
534  break;
535  }
536  return false;
537 }
538 
539 // -------------------------------------------------------------------------------
540 
541 RenderRadioButton::RenderRadioButton(HTMLInputElementImpl *element)
542  : RenderButton(element)
543 {
544  RadioButtonWidget *b = new RadioButtonWidget(view()->widget());
545  b->setMouseTracking(true);
546  b->setAutoExclusive(false);
547  setQWidget(b);
548 
549  // prevent firing toggled() signals on initialization
550  b->setChecked(element->checked());
551 
552  connect(b, SIGNAL(toggled(bool)), this, SLOT(slotToggled(bool)));
553  m_ignoreToggled = false;
554 }
555 
556 void RenderRadioButton::updateFromElement()
557 {
558  m_ignoreToggled = true;
559  widget()->setChecked(element()->checked());
560  m_ignoreToggled = false;
561 
562  RenderButton::updateFromElement();
563 }
564 
565 void RenderRadioButton::calcMinMaxWidth()
566 {
567  KHTMLAssert(!minMaxKnown());
568 
569  QRadioButton *rb = static_cast<QRadioButton *>(m_widget);
570  QSize s(qMin(22, qMax(14, rb->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth))),
571  qMin(20, qMax(12, rb->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorHeight))));
572  setIntrinsicWidth(s.width());
573  setIntrinsicHeight(s.height());
574 
575  RenderButton::calcMinMaxWidth();
576 }
577 
578 void RenderRadioButton::slotToggled(bool /*activated*/)
579 {
580  if (m_ignoreToggled) {
581  return;
582  }
583 }
584 
585 bool RenderRadioButton::handleEvent(const DOM::EventImpl &ev)
586 {
587  switch (ev.id()) {
588  case EventImpl::DOMFOCUSIN_EVENT:
589  case EventImpl::DOMFOCUSOUT_EVENT:
590  case EventImpl::MOUSEMOVE_EVENT:
591  case EventImpl::MOUSEOUT_EVENT:
592  case EventImpl::MOUSEOVER_EVENT:
593  return RenderButton::handleEvent(ev);
594  default:
595  break;
596  }
597  return false;
598 }
599 
600 // -------------------------------------------------------------------------------
601 
602 const QLatin1String sBorderNoneSheet("QPushButton{border:none}");
603 
604 RenderSubmitButton::RenderSubmitButton(HTMLInputElementImpl *element)
605  : RenderButton(element)
606 {
607  PushButtonWidget *p = new PushButtonWidget(view()->widget());
608  setQWidget(p);
609  //p->setAutoMask(true);
610  p->setMouseTracking(true);
611  p->setDefault(false);
612  p->setAutoDefault(false);
613 }
614 
615 static inline void setStyleSheet_helper(const QString &s, QWidget *w)
616 {
617  // ### buggy Qt stylesheets mess with the widget palette.
618  // force it again after any stylesheet update.
619  QPalette pal = w->palette();
620  w->setStyleSheet(s);
621  w->setPalette(pal);
622 }
623 
624 void RenderSubmitButton::setPadding()
625 {
626  // Proxy styling doesn't work well enough for buttons.
627  // Use stylesheets instead. tests/css/button-padding-top.html
628  assert(!m_proxyStyle);
629 
630  if (!includesPadding()) {
631  return;
632  }
633 
634  if (!RenderWidget::paddingLeft() && !RenderWidget::paddingRight() &&
635  !RenderWidget::paddingTop() && !RenderWidget::paddingBottom()) {
636  setStyleSheet_helper((shouldDisableNativeBorders() ? sBorderNoneSheet : QString()), widget());
637  return;
638  }
639 
640  setStyleSheet_helper(
641  QString("QPushButton{padding-left:%1px; padding-right:%2px; padding-top:%3px; padding-bottom:%4px}")
642  .arg(RenderWidget::paddingLeft())
643  .arg(RenderWidget::paddingRight())
644  .arg(RenderWidget::paddingTop())
645  .arg(RenderWidget::paddingBottom()) + (shouldDisableNativeBorders() ? sBorderNoneSheet : QString())
646  , widget());
647 }
648 
649 void RenderSubmitButton::setStyle(RenderStyle *style)
650 {
651  // Proxy styling doesn't work well enough for buttons.
652  // Use stylesheets instead. tests/css/button-padding-top.html
653  assert(!m_proxyStyle);
654  RenderFormElement::setStyle(style);
655 
656  QString s = widget()->styleSheet();
657  if (shouldDisableNativeBorders()) {
658  // we paint the borders ourselves on this button,
659  // remove the widget's native ones.
660  if (!s.contains(sBorderNoneSheet)) {
661  s.append(sBorderNoneSheet);
662  setStyleSheet_helper(s, widget());
663  }
664  } else {
665  setStyleSheet_helper(s.remove(sBorderNoneSheet), widget());
666  }
667 }
668 
669 QString RenderSubmitButton::rawText()
670 {
671  QString value = element()->valueWithDefault().string();
672  value = value.trimmed();
673  QString raw;
674  for (int i = 0; i < value.length(); i++) {
675  raw += value[i];
676  if (value[i] == '&') {
677  raw += '&';
678  }
679  }
680  return raw;
681 }
682 
683 bool RenderSubmitButton::canHaveBorder() const
684 {
685  // ### TODO would be nice to be able to
686  // return style()->hasBackgroundImage() here,
687  // depending on a config option (e.g. 'favour usability/integration over aspect')
688  // so that only buttons with both a custom border
689  // and a background image are drawn without native styling.
690  //
691  // This would go in the same place, gui wise, as a choice of b/w default color scheme,
692  // versus native color scheme.
693 
694  return true;
695 }
696 
697 void RenderSubmitButton::calcMinMaxWidth()
698 {
699  KHTMLAssert(!minMaxKnown());
700 
701  QString raw = rawText();
702  QPushButton *pb = static_cast<QPushButton *>(m_widget);
703  pb->setText(raw);
704  pb->setFont(style()->font());
705 
706  bool empty = raw.isEmpty();
707  if (empty) {
708  raw = QLatin1Char('X');
709  }
710  QFontMetrics fm = pb->fontMetrics();
711  QSize ts = fm.size(Qt::TextShowMnemonic, raw);
712  //Oh boy.
713  QStyleOptionButton butOpt;
714  butOpt.init(pb);
715  butOpt.text = raw;
716  QSize s = pb->style()->sizeFromContents(QStyle::CT_PushButton, &butOpt, ts, pb);
717 
719  int margin = pb->style()->pixelMetric(QStyle::PM_ButtonMargin) +
721 
722  int w = ts.width() + margin;
723  int h = s.height();
724 
725  assert(includesPadding());
726  int hpadding = RenderWidget::paddingLeft() + RenderWidget::paddingRight();
727  int vpadding = RenderWidget::paddingTop() + RenderWidget::paddingBottom();
728 
729  // add 30% margins to the width (heuristics to make it look similar to IE)
730  // ### FIXME BASELINE: we could drop this emulation and adopt Mozilla style buttons
731  // (+/- padding: 0px 8px 0px 8px) - IE is most often in a separate css
732  // code path nowadays, so we have wider buttons than other engines.
733  int toAdd = (w * 13 / 10) - w - hpadding;
734  toAdd = qMax(0, toAdd);
735  w += toAdd;
736 
737  if (shouldDisableNativeBorders()) {
738  // we paint the borders ourselves, so let's override our height to something saner
739  h = ts.height();
740  } else {
741  h -= vpadding;
742  }
744 
745  setIntrinsicWidth(s.width());
746  setIntrinsicHeight(s.height());
747 
748  RenderButton::calcMinMaxWidth();
749 }
750 
751 void RenderSubmitButton::updateFromElement()
752 {
753  QString oldText = static_cast<QPushButton *>(m_widget)->text();
754  QString newText = rawText();
755  static_cast<QPushButton *>(m_widget)->setText(newText);
756  if (oldText != newText) {
757  setNeedsLayoutAndMinMaxRecalc();
758  }
759  RenderFormElement::updateFromElement();
760 }
761 
762 short RenderSubmitButton::baselinePosition(bool f) const
763 {
764  int ret = (height() - RenderWidget::paddingTop() - RenderWidget::paddingBottom() + 1) / 2;
765  ret += marginTop() + RenderWidget::paddingTop();
766  ret += ((fontMetrics(f).ascent()) / 2) - 2;
767  return ret;
768 }
769 
770 // -------------------------------------------------------------------------------
771 
772 RenderResetButton::RenderResetButton(HTMLInputElementImpl *element)
773  : RenderSubmitButton(element)
774 {
775 }
776 
777 // -------------------------------------------------------------------------------
778 
779 namespace khtml
780 {
781 
782 class CompletionWidget: public KCompletionBox
783 {
784 public:
785  CompletionWidget(QWidget *parent = nullptr) : KCompletionBox(parent) {}
786  QPoint globalPositionHint() const override
787  {
788  QWidget *pw = parentWidget();
789  KHTMLWidget *kwp = dynamic_cast<KHTMLWidget *>(pw);
790  if (!kwp) {
791  qCDebug(KHTML_LOG) << "CompletionWidget has no KHTMLWidget parent";
793  }
794  QPoint dest;
795  KHTMLView *v = kwp->m_kwp->rootViewPos(dest);
796  QPoint ret;
797  if (v) {
798  ret = v->mapToGlobal(dest + QPoint(0, pw->height()));
799  int zoomLevel = v->zoomLevel();
800  if (zoomLevel != 100) {
801  ret.setX(ret.x()*zoomLevel / 100);
802  ret.setY(ret.y()*zoomLevel / 100);
803  }
804  }
805  return ret;
806  }
807 };
808 
809 }
810 
811 LineEditWidget::LineEditWidget(DOM::HTMLInputElementImpl *input, KHTMLView *view, QWidget *parent)
812  : KLineEdit(parent), m_input(input), m_view(view)
813 {
814  m_kwp->setIsRedirected(true);
815  setMouseTracking(true);
816  KActionCollection *ac = new KActionCollection(this);
817  m_spellAction = KStandardAction::spelling(this, SLOT(slotCheckSpelling()), ac);
818 
819  setCompletionBox(new CompletionWidget(this));
820  completionBox()->setObjectName("completion box");
821  completionBox()->setFont(font());
822 }
823 
824 LineEditWidget::~LineEditWidget()
825 {
826 }
827 
828 void LineEditWidget::slotCheckSpelling()
829 {
830  if (text().isEmpty()) {
831  return;
832  }
833  Sonnet::Dialog *spellDialog = new Sonnet::Dialog(new Sonnet::BackgroundChecker(this), nullptr);
834  connect(spellDialog, SIGNAL(replace(QString,int,QString)), this, SLOT(spellCheckerCorrected(QString,int,QString)));
835  connect(spellDialog, SIGNAL(misspelling(QString,int)), this, SLOT(spellCheckerMisspelling(QString,int)));
836  connect(spellDialog, SIGNAL(done(QString)), this, SLOT(slotSpellCheckDone(QString)));
837  connect(spellDialog, SIGNAL(cancel()), this, SLOT(spellCheckerFinished()));
838  connect(spellDialog, SIGNAL(stop()), this, SLOT(spellCheckerFinished()));
839  spellDialog->setBuffer(text());
840  spellDialog->show();
841 }
842 
843 void LineEditWidget::spellCheckerMisspelling(const QString &_text, int pos)
844 {
845  highLightWord(_text.length(), pos);
846 }
847 
848 void LineEditWidget::setFocus()
849 {
851  end(false);
852 }
853 
854 void LineEditWidget::highLightWord(unsigned int length, unsigned int pos)
855 {
856  setSelection(pos, length);
857 }
858 
859 void LineEditWidget::spellCheckerCorrected(const QString &old, int pos, const QString &corr)
860 {
861  if (old != corr) {
862  setSelection(pos, old.length());
863  insert(corr);
864  setSelection(pos, corr.length());
865  }
866 }
867 
868 void LineEditWidget::spellCheckerFinished()
869 {
870 }
871 
872 void LineEditWidget::slotSpellCheckDone(const QString &s)
873 {
874  if (s != text()) {
875  setText(s);
876  }
877 }
878 
879 namespace khtml
880 {
881 
882 /**
883  * @internal
884  */
885 class WebShortcutCreator
886 {
887 public:
888  /**
889  * @short Creates a Web Shourtcut without using kdebase SearchProvider class.
890  * It is used by LineEditWidget.
891  */
892  static bool createWebShortcut(QString query);
893 
894 private:
895  static bool askData(QString &name, QString &keys);
896  static void createFile(QString query, QString name, QString keys);
897 };
898 
899 bool WebShortcutCreator::createWebShortcut(QString query)
900 {
901  QString name = i18n("New Web Shortcut");
902  QString keys;
903  if (askData(name, keys)) {
904  bool isOk;
905  do { //It's going to be checked if the keys have already been assigned
906  isOk = true;
907  QStringList keyList(keys.split(','));
909  foreach (const KService::Ptr &provider, providers) {
910  if (!isOk) {
911  break;
912  }
913  foreach (const QString &s, provider->property("Keys").toStringList()) {
914  if (!isOk) {
915  break;
916  }
917  foreach (const QString &t, keys) {
918  if (!isOk) {
919  break;
920  }
921  if (s == t) {
922  KMessageBox::sorry(nullptr, i18n("%1 is already assigned to %2", s, provider->name()), i18n("Error"));
923  isOk = false;
924  }
925  }
926  }
927  }
928  if (!isOk && !askData(name, keys)) {
929  return false;
930  }
931  } while (!isOk);
932  createFile(query, name, keys);
933  return true;
934  } else {
935  return false;
936  }
937 }
938 
939 void WebShortcutCreator::createFile(QString query, QString name, QString keys)
940 {
941  // SearchProvider class is part of kdebase, so the file is written as
942  // an standard desktop file.
943  QString fileName(keys);
945  QDir().mkpath(dir);
946  while (QFile::exists(dir + fileName + ".desktop")) {
947  fileName += '_';
948  }
949  KDesktopFile f(dir + fileName + ".desktop");
950  f.desktopGroup().writeEntry("Keys", keys);
951  f.desktopGroup().writeEntry("Type", "Service");
952  f.desktopGroup().writeEntry("ServiceTypes", "SearchProvider");
953  f.desktopGroup().writeEntry("Name", name);
954  f.desktopGroup().writeEntry("Query", query);
955  f.sync();
957 }
958 
959 bool WebShortcutCreator::askData(QString &name, QString &keys)
960 {
961  QDialog *dialog = new QDialog();
962  dialog->setWindowTitle(name);
963  QVBoxLayout *mainLayout = new QVBoxLayout();
964  dialog->setLayout(mainLayout);
965 
966  QHBoxLayout *layout = new QHBoxLayout();
967  mainLayout->addLayout(layout);
968  QLabel *label = new QLabel(i18n("Search &provider name:"), dialog);
969  layout->addWidget(label);
970  QLineEdit *nameEdit = new QLineEdit(i18n("New search provider"), dialog);
971  label->setBuddy(nameEdit);
972  layout->addWidget(nameEdit);
973  layout = new QHBoxLayout();
974  mainLayout->addLayout(layout);
975  label = new QLabel(i18n("UR&I shortcuts:"), dialog);
976  layout->addWidget(label);
977  QLineEdit *keysEdit = new QLineEdit(dialog);
978  label->setBuddy(keysEdit);
979  layout->addWidget(keysEdit);
980 
981  QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
983  QObject::connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
984  QObject::connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
985  mainLayout->addWidget(buttonBox);
986 
987  bool res = dialog->exec();
988  if (res) {
989  name = nameEdit->text();
990  keys = keysEdit->text();
991  }
992  delete dialog;
993  return res;
994 }
995 
996 }
997 
998 void LineEditWidget::slotCreateWebShortcut()
999 {
1000  QString queryName(m_input->name().string());
1001  HTMLFormElementImpl *form = m_input->form();
1002  QUrl url(form->action().string());
1003  QUrl baseUrl(m_view->part()->baseURL().url() + '?');
1004  if (url.path().isEmpty()) {
1005  url.setPath(baseUrl.path());
1006  }
1007  if (url.host().isEmpty()) {
1008  url.setScheme(baseUrl.scheme());
1009  url.setHost(baseUrl.host());
1010  }
1011  NodeImpl *node;
1012  HTMLInputElementImpl *inputNode;
1013  for (unsigned long i = 0; (node = form->elements()->item(i)); i++) {
1014  inputNode = dynamic_cast<HTMLInputElementImpl *>(node);
1015  if (inputNode) {
1016  if ((!inputNode->name().string().size()) ||
1017  (inputNode->name().string() == queryName)) {
1018  continue;
1019  } else {
1020  switch (inputNode->inputType()) {
1021  case HTMLInputElementImpl::CHECKBOX:
1022  case HTMLInputElementImpl::RADIO:
1023  if (!inputNode->checked()) {
1024  break;
1025  }
1026  case HTMLInputElementImpl::TEXT:
1027  case HTMLInputElementImpl::PASSWORD:
1028  case HTMLInputElementImpl::HIDDEN:
1029  url.addQueryItem(inputNode->name().string(), inputNode->value().string());
1030  default:
1031  break;
1032  }
1033  }
1034  }
1035  }
1036  QString query(url.url());
1037  if (!query.contains("?")) {
1038  query += '?'; //This input is the only one of the form
1039  }
1040  query += '&' + queryName + "=\\{@}";
1041  WebShortcutCreator::createWebShortcut(query);
1042 }
1043 
1044 void LineEditWidget::contextMenuEvent(QContextMenuEvent *e)
1045 {
1046  QMenu *popup = createStandardContextMenu();
1047 
1048  if (!popup) {
1049  return;
1050  }
1051 
1052  if (m_input->autoComplete()) {
1053  popup->addSeparator();
1054  QAction *act = popup->addAction(QIcon::fromTheme("edit-clear-history"), i18n("Clear &History"));
1055  act->setEnabled(compObj() && !compObj()->isEmpty());
1056  connect(act, SIGNAL(triggered()),
1057  this, SLOT(clearHistoryActivated()));
1058  }
1059 
1060  if (echoMode() == QLineEdit::Normal &&
1061  !isReadOnly()) {
1062  popup->addSeparator();
1063 
1064  popup->addAction(m_spellAction);
1065  m_spellAction->setEnabled(!text().isEmpty());
1066  }
1067  if (!m_view->part()->onlyLocalReferences()) {
1068  popup->addSeparator();
1069  QAction *act = popup->addAction(i18n("Create Web Shortcut"));
1070  connect(act, SIGNAL(triggered()),
1071  this, SLOT(slotCreateWebShortcut()));
1072  }
1073 
1074  emit aboutToShowContextMenu(popup);
1075 
1076  popup->exec(e->globalPos());
1077  delete popup;
1078 }
1079 
1080 void LineEditWidget::clearHistoryActivated()
1081 {
1082  m_view->clearCompletionHistory(m_input->name().string());
1083  if (compObj()) {
1084  compObj()->clear();
1085  }
1086 }
1087 
1088 bool LineEditWidget::event(QEvent *e)
1089 {
1090  if (KLineEdit::event(e)) {
1091  return true;
1092  }
1093 #if 0
1094  if (e->type() == QEvent::AccelAvailable && isReadOnly()) {
1095  QKeyEvent *ke = (QKeyEvent *) e;
1096  if (ke->modifiers() & Qt::ControlModifier) {
1097  switch (ke->key()) {
1098  case Qt::Key_Left:
1099  case Qt::Key_Right:
1100  case Qt::Key_Up:
1101  case Qt::Key_Down:
1102  case Qt::Key_Home:
1103  case Qt::Key_End:
1104  ke->accept();
1105  default:
1106  break;
1107  }
1108  }
1109  }
1110 #endif
1111  return false;
1112 }
1113 
1114 void LineEditWidget::mouseMoveEvent(QMouseEvent *e)
1115 {
1116  // hack to prevent Qt from calling setCursor on the widget
1117  setDragEnabled(false);
1119  setDragEnabled(true);
1120 }
1121 
1122 // -----------------------------------------------------------------------------
1123 
1124 RenderLineEdit::RenderLineEdit(HTMLInputElementImpl *element)
1125  : RenderFormElement(element), m_blockElementUpdates(false)
1126 {
1127  LineEditWidget *edit = new LineEditWidget(element, view(), view()->widget());
1128  connect(edit, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
1129  connect(edit, SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString)));
1130 
1131  if (element->inputType() == HTMLInputElementImpl::PASSWORD) {
1132  edit->setEchoMode(QLineEdit::Password);
1133  }
1134 
1135  if (element->autoComplete()) {
1136  QStringList completions = view()->formCompletionItems(element->name().string());
1137  if (completions.count()) {
1138  edit->completionObject()->setItems(completions);
1139  edit->setContextMenuPolicy(Qt::NoContextMenu);
1140  edit->completionBox()->setTabHandling(false);
1141  }
1142  }
1143 
1144  setQWidget(edit);
1145 }
1146 
1147 short RenderLineEdit::baselinePosition(bool f) const
1148 {
1149  bool hasFrame = static_cast<LineEditWidget *>(widget())->hasFrame();
1150  int bTop = hasFrame ? 0 : borderTop();
1151  int bBottom = hasFrame ? 0 : borderBottom();
1152  int ret = (height() - RenderWidget::paddingTop() - RenderWidget::paddingBottom() - bTop - bBottom + 1) / 2;
1153  ret += marginTop() + RenderWidget::paddingTop() + bTop;
1154  ret += ((fontMetrics(f).ascent()) / 2) - 2;
1155  return ret;
1156 }
1157 
1158 void RenderLineEdit::setStyle(RenderStyle *_style)
1159 {
1160  RenderFormElement::setStyle(_style);
1161 
1162  if (widget()->alignment() != textAlignment()) {
1163  widget()->setAlignment(textAlignment());
1164  }
1165 
1166  bool showClearButton = (!shouldDisableNativeBorders() && !_style->hasBackgroundImage());
1167 
1168  if (!showClearButton && widget()->isClearButtonEnabled()) {
1169  widget()->setClearButtonEnabled(false);
1170  } else if (showClearButton && !widget()->isClearButtonEnabled()) {
1171  widget()->setClearButtonEnabled(true);
1172  QObjectList children = widget()->children();
1173  foreach (QObject *object, children) {
1174  QWidget *w = qobject_cast<QWidget *>(object);
1175  if (w && !w->isWindow() && (w->objectName() == "KLineEditButton")) {
1176  // this duplicates KHTMLView's handleWidget but this widget
1177  // is created on demand, so it might not be here at ChildPolished time
1178  w->installEventFilter(view());
1179  }
1180  }
1181  }
1182 
1183  if (m_proxyStyle) {
1184  static_cast<KHTMLProxyStyle *>(m_proxyStyle)->clearButtonOverlay = qMax(0, widget()->clearButtonUsedSize().width());
1185  }
1186 }
1187 
1188 void RenderLineEdit::highLightWord(unsigned int length, unsigned int pos)
1189 {
1190  LineEditWidget *w = static_cast<LineEditWidget *>(m_widget);
1191  if (w) {
1192  w->highLightWord(length, pos);
1193  }
1194 }
1195 
1196 void RenderLineEdit::slotReturnPressed()
1197 {
1198  // don't submit the form when return was pressed in a completion-popup
1199  KCompletionBox *box = widget()->completionBox(false);
1200 
1201  if (box && box->isVisible() && box->currentRow() != -1) {
1202  box->hide();
1203  return;
1204  }
1205 
1206  // Emit onChange if necessary
1207  // Works but might not be enough, dirk said he had another solution at
1208  // hand (can't remember which) - David
1209  handleFocusOut();
1210 
1211  HTMLFormElementImpl *fe = element()->form();
1212  if (fe) {
1213  fe->submitFromKeyboard();
1214  }
1215 }
1216 
1217 void RenderLineEdit::handleFocusOut()
1218 {
1219  if (widget() && widget()->isModified()) {
1220  element()->onChange();
1221  widget()->setModified(false);
1222  }
1223 }
1224 
1225 void RenderLineEdit::calcMinMaxWidth()
1226 {
1227  KHTMLAssert(!minMaxKnown());
1228 
1229  const QFontMetrics &fm = style()->fontMetrics();
1230  QSize s;
1231 
1232  int size = (element()->size() > 0) ? (element()->size() + 1) : 17; // "some"
1233 
1234  int h = fm.lineSpacing();
1235  int w = (fm.height() * size) / 2; // on average a character cell is twice as tall as it is wide
1236 
1237  QStyleOptionFrame opt;
1238  opt.initFrom(widget());
1239  if (widget()->hasFrame()) {
1240  opt.lineWidth = widget()->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, widget());
1241  }
1242 
1243  s = QSize(w, qMax(h, 14));
1244  s = widget()->style()->sizeFromContents(QStyle::CT_LineEdit, &opt, s, widget());
1246 
1247  setIntrinsicWidth(s.width());
1248  setIntrinsicHeight(s.height());
1249 
1250  RenderFormElement::calcMinMaxWidth();
1251 }
1252 
1253 void RenderLineEdit::updateFromElement()
1254 {
1255  int ml = element()->maxLength();
1256  if (ml < 0) {
1257  ml = 32767;
1258  }
1259 
1260  if (widget()->maxLength() != ml) {
1261  widget()->setMaxLength(ml);
1262  }
1263 
1264  if (element()->value().string() != widget()->text()) {
1265  m_blockElementUpdates = true; // Do not block signals here (#188374)
1266  int pos = widget()->cursorPosition();
1267  widget()->setText(element()->value().string());
1268  widget()->setCursorPosition(pos);
1269  m_blockElementUpdates = false;
1270  }
1271  widget()->setReadOnly(element()->readOnly());
1272 
1273  widget()->setPlaceholderText(element()->placeholder().string().remove(QLatin1Char('\n')).remove(QLatin1Char('\r')));
1274 
1275  RenderFormElement::updateFromElement();
1276 }
1277 
1278 void RenderLineEdit::slotTextChanged(const QString &string)
1279 {
1280  if (m_blockElementUpdates) {
1281  return;
1282  }
1283 
1284  // don't use setValue here!
1285  element()->m_value = string.isNull() ? DOMString("") : string;
1286  element()->m_unsubmittedFormChange = true;
1287 }
1288 
1289 void RenderLineEdit::select()
1290 {
1291  static_cast<LineEditWidget *>(m_widget)->selectAll();
1292 }
1293 
1294 long RenderLineEdit::selectionStart()
1295 {
1296  LineEditWidget *w = static_cast<LineEditWidget *>(m_widget);
1297  if (w->hasSelectedText()) {
1298  return w->selectionStart();
1299  } else {
1300  return w->cursorPosition();
1301  }
1302 }
1303 
1304 long RenderLineEdit::selectionEnd()
1305 {
1306  LineEditWidget *w = static_cast<LineEditWidget *>(m_widget);
1307  if (w->hasSelectedText()) {
1308  return w->selectionStart() + w->selectedText().length();
1309  } else {
1310  return w->cursorPosition();
1311  }
1312 }
1313 
1314 void RenderLineEdit::setSelectionStart(long pos)
1315 {
1316  LineEditWidget *w = static_cast<LineEditWidget *>(m_widget);
1317  //See whether we have a non-empty selection now.
1318  long end = selectionEnd();
1319  if (end > pos) {
1320  w->setSelection(pos, end - pos);
1321  }
1322  w->setCursorPosition(pos);
1323 }
1324 
1325 void RenderLineEdit::setSelectionEnd(long pos)
1326 {
1327  LineEditWidget *w = static_cast<LineEditWidget *>(m_widget);
1328  //See whether we have a non-empty selection now.
1329  long start = selectionStart();
1330  if (start < pos) {
1331  w->setSelection(start, pos - start);
1332  }
1333 
1334  w->setCursorPosition(pos);
1335 }
1336 
1337 void RenderLineEdit::setSelectionRange(long start, long end)
1338 {
1339  LineEditWidget *w = static_cast<LineEditWidget *>(m_widget);
1340  w->setCursorPosition(end);
1341  w->setSelection(start, end - start);
1342 }
1343 
1344 // ---------------------------------------------------------------------------
1345 
1346 RenderFieldset::RenderFieldset(HTMLGenericFormElementImpl *element)
1347  : RenderBlock(element)
1348 {
1349  m_intrinsicWidth = 0;
1350 }
1351 
1352 void RenderFieldset::calcMinMaxWidth()
1353 {
1354  RenderBlock::calcMinMaxWidth();
1355  if (style()->htmlHacks()) {
1356  if (RenderObject *legend = findLegend()) {
1357  int legendMinWidth = legend->minWidth();
1358 
1359  Length legendMarginLeft = legend->style()->marginLeft();
1360  Length legendMarginRight = legend->style()->marginLeft();
1361 
1362  if (legendMarginLeft.isFixed()) {
1363  legendMinWidth += legendMarginLeft.value();
1364  }
1365 
1366  if (legendMarginRight.isFixed()) {
1367  legendMinWidth += legendMarginRight.value();
1368  }
1369 
1370  m_intrinsicWidth = qMax((int)m_minWidth, legendMinWidth + paddingLeft() + paddingRight() + borderLeft() + borderRight());
1371  }
1372  }
1373 }
1374 
1375 RenderObject *RenderFieldset::layoutLegend(bool relayoutChildren)
1376 {
1377  RenderObject *legend = findLegend();
1378  if (legend) {
1379  if (relayoutChildren) {
1380  legend->setNeedsLayout(true);
1381  }
1382  legend->layoutIfNeeded();
1383 
1384  int xPos = borderLeft() + paddingLeft() + legend->marginLeft();
1385  if (style()->direction() == RTL) {
1386  xPos = m_width - paddingRight() - borderRight() - legend->width() - legend->marginRight();
1387  }
1388  int b = borderTop();
1389  int h = legend->height();
1390  legend->setPos(xPos, qMax((b - h) / 2, 0));
1391  m_height = qMax(b, h) + paddingTop();
1392  }
1393  return legend;
1394 }
1395 
1396 RenderObject *RenderFieldset::findLegend() const
1397 {
1398  for (RenderObject *legend = firstChild(); legend; legend = legend->nextSibling()) {
1399  if (!legend->isFloatingOrPositioned() && legend->element() &&
1400  legend->element()->id() == ID_LEGEND) {
1401  return legend;
1402  }
1403  }
1404  return nullptr;
1405 }
1406 
1407 void RenderFieldset::paintBoxDecorations(PaintInfo &pI, int _tx, int _ty)
1408 {
1409  //qCDebug(KHTML_LOG) << renderName() << "::paintDecorations()";
1410 
1411  RenderObject *legend = findLegend();
1412  if (!legend) {
1413  return RenderBlock::paintBoxDecorations(pI, _tx, _ty);
1414  }
1415 
1416  int w = width();
1417  int h = height() + borderTopExtra() + borderBottomExtra();
1418  int yOff = (legend->yPos() > 0) ? 0 : (legend->height() - borderTop()) / 2;
1419  int legendBottom = _ty + legend->yPos() + legend->height();
1420  h -= yOff;
1421  _ty += yOff - borderTopExtra();
1422 
1423  QRect cr = QRect(_tx, _ty, w, h).intersected(pI.r);
1424  paintOneBackground(pI.p, style()->backgroundColor(), style()->backgroundLayers(), cr, _tx, _ty, w, h);
1425 
1426  if (style()->hasBorder()) {
1427  paintBorderMinusLegend(pI.p, _tx, _ty, w, h, style(), legend->xPos(), legend->width(), legendBottom);
1428  }
1429 }
1430 
1431 void RenderFieldset::paintBorderMinusLegend(QPainter *p, int _tx, int _ty, int w, int h,
1432  const RenderStyle *style, int lx, int lw, int lb)
1433 {
1434 
1435  const QColor &tc = style->borderTopColor();
1436  const QColor &bc = style->borderBottomColor();
1437 
1438  EBorderStyle ts = style->borderTopStyle();
1439  EBorderStyle bs = style->borderBottomStyle();
1440  EBorderStyle ls = style->borderLeftStyle();
1441  EBorderStyle rs = style->borderRightStyle();
1442 
1443  bool render_t = ts > BHIDDEN;
1444  bool render_l = ls > BHIDDEN;
1445  bool render_r = rs > BHIDDEN;
1446  bool render_b = bs > BHIDDEN;
1447 
1448  int borderLeftWidth = style->borderLeftWidth();
1449  int borderRightWidth = style->borderRightWidth();
1450 
1451  if (render_t) {
1452  if (lx >= borderLeftWidth)
1453  drawBorder(p, _tx, _ty, _tx + lx, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
1454  (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? style->borderLeftWidth() : 0), 0);
1455  if (lx + lw <= w - borderRightWidth)
1456  drawBorder(p, _tx + lx + lw, _ty, _tx + w, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
1457  0, (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? style->borderRightWidth() : 0));
1458  }
1459 
1460  if (render_b)
1461  drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
1462  (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? style->borderLeftWidth() : 0),
1463  (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? style->borderRightWidth() : 0));
1464 
1465  if (render_l) {
1466  const QColor &lc = style->borderLeftColor();
1467 
1468  bool ignore_top =
1469  (tc == lc) &&
1470  (ls >= OUTSET) &&
1471  (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
1472 
1473  bool ignore_bottom =
1474  (bc == lc) &&
1475  (ls >= OUTSET) &&
1476  (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
1477 
1478  int startY = _ty;
1479  if (lx < borderLeftWidth && lx + lw > 0) {
1480  // The legend intersects the border.
1481  ignore_top = true;
1482  startY = lb;
1483  }
1484 
1485  drawBorder(p, _tx, startY, _tx + borderLeftWidth, _ty + h, BSLeft, lc, style->color(), ls,
1486  ignore_top ? 0 : style->borderTopWidth(),
1487  ignore_bottom ? 0 : style->borderBottomWidth());
1488  }
1489 
1490  if (render_r) {
1491  const QColor &rc = style->borderRightColor();
1492 
1493  bool ignore_top =
1494  (tc == rc) &&
1495  (rs >= DOTTED || rs == INSET) &&
1496  (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
1497 
1498  bool ignore_bottom =
1499  (bc == rc) &&
1500  (rs >= DOTTED || rs == INSET) &&
1501  (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
1502 
1503  int startY = _ty;
1504  if (lx < w && lx + lw > w - borderRightWidth) {
1505  // The legend intersects the border.
1506  ignore_top = true;
1507  startY = lb;
1508  }
1509 
1510  drawBorder(p, _tx + w - borderRightWidth, startY, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
1511  ignore_top ? 0 : style->borderTopWidth(),
1512  ignore_bottom ? 0 : style->borderBottomWidth());
1513  }
1514 }
1515 
1516 void RenderFieldset::setStyle(RenderStyle *_style)
1517 {
1518  RenderBlock::setStyle(_style);
1519 
1520  // WinIE renders fieldsets with display:inline like they're inline-blocks. For us,
1521  // an inline-block is just a block element with replaced set to true and inline set
1522  // to true. Ensure that if we ended up being inline that we set our replaced flag
1523  // so that we're treated like an inline-block.
1524  if (isInline()) {
1525  setReplaced(true);
1526  }
1527 }
1528 
1529 // -------------------------------------------------------------------------
1530 
1531 RenderFileButton::RenderFileButton(HTMLInputElementImpl *element)
1532  : RenderFormElement(element)
1533 {
1534  FileButtonWidget *w = new FileButtonWidget(view()->widget());
1535 
1536  w->setMode(KFile::File | KFile::ExistingOnly);
1537  w->lineEdit()->setCompletionBox(new CompletionWidget(w));
1539 
1540  connect(w->lineEdit(), SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
1541  connect(w->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(slotTextChanged(QString)));
1542  connect(w, SIGNAL(urlSelected(QUrl)), this, SLOT(slotUrlSelected()));
1543 
1544  setQWidget(w);
1545  m_haveFocus = false;
1546 }
1547 
1548 short RenderFileButton::baselinePosition(bool f) const
1549 {
1550  int bTop = borderTop();
1551  int bBottom = borderBottom();
1552  int ret = (height() - paddingTop() - paddingBottom() - bTop - bBottom + 1) / 2;
1553  ret += marginTop() + paddingTop() + bTop;
1554  ret += ((fontMetrics(f).ascent()) / 2) - 2;
1555  return ret;
1556 }
1557 
1558 void RenderFileButton::calcMinMaxWidth()
1559 {
1560  KHTMLAssert(!minMaxKnown());
1561 
1562  const QFontMetrics &fm = style()->fontMetrics();
1563  int size = (element()->size() > 0) ? (element()->size() + 1) : 17; // "some"
1564 
1565  int h = fm.lineSpacing();
1566  int w = (fm.height() * size) / 2; // on average a character cell is twice as tall as it is wide
1567  KLineEdit *edit = widget()->lineEdit();
1568 
1569  QStyleOptionFrame opt;
1570  opt.initFrom(edit);
1571  if (edit->hasFrame()) {
1572  opt.lineWidth = edit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, edit);
1573  }
1574 
1575  QSize s(w, qMax(h, 14));
1576  s = edit->style()->sizeFromContents(QStyle::CT_LineEdit, &opt, s, edit);
1578 
1579  QSize bs = widget()->minimumSizeHint() - edit->minimumSizeHint();
1580 
1581  setIntrinsicWidth(s.width() + bs.width());
1582  setIntrinsicHeight(qMax(s.height(), bs.height()));
1583 
1584  RenderFormElement::calcMinMaxWidth();
1585 }
1586 
1587 void RenderFileButton::handleFocusOut()
1588 {
1589  if (widget()->lineEdit() && widget()->lineEdit()->isModified()) {
1590  element()->onChange();
1591  widget()->lineEdit()->setModified(false);
1592  }
1593 }
1594 
1595 void RenderFileButton::updateFromElement()
1596 {
1597  KLineEdit *edit = widget()->lineEdit();
1598  bool blocked = edit->blockSignals(true);
1599  edit->setText(element()->value().string());
1600  edit->blockSignals(blocked);
1601  edit->setModified(false);
1602 
1603  RenderFormElement::updateFromElement();
1604 }
1605 
1606 void RenderFileButton::slotReturnPressed()
1607 {
1608  // don't submit the form when return was pressed in a completion-popup
1609  KCompletionBox *box = widget()->lineEdit()->completionBox(false);
1610  if (box && box->isVisible() && box->currentRow() != -1) {
1611  box->hide();
1612  return;
1613  }
1614 
1615  handleFocusOut();
1616 
1617  if (element()->form()) {
1618  element()->form()->submitFromKeyboard();
1619  }
1620 }
1621 
1622 void RenderFileButton::slotTextChanged(const QString &/*string*/)
1623 {
1624  element()->m_value = QUrl(widget()->url()).toDisplayString(QUrl::PreferLocalFile);
1625 }
1626 
1627 void RenderFileButton::slotUrlSelected()
1628 {
1629  element()->onChange();
1630 }
1631 
1632 void RenderFileButton::select()
1633 {
1634  widget()->lineEdit()->selectAll();
1635 }
1636 
1637 // -------------------------------------------------------------------------
1638 
1639 RenderLabel::RenderLabel(HTMLGenericFormElementImpl *element)
1640  : RenderFormElement(element)
1641 {
1642 
1643 }
1644 
1645 // -------------------------------------------------------------------------
1646 
1647 RenderLegend::RenderLegend(HTMLGenericFormElementImpl *element)
1648  : RenderBlock(element)
1649 {
1650 }
1651 
1652 // -------------------------------------------------------------------------------
1653 
1654 bool ListBoxWidget::event(QEvent *event)
1655 {
1656  // accept all wheel events so that they are not propagated to the view
1657  // once either end of the list is reached.
1658  bool ret = QListWidget::event(event);
1659  if (event->type() == QEvent::Wheel) {
1660  event->accept();
1661  ret = true;
1662  }
1663  return ret;
1664 }
1665 
1666 ComboBoxWidget::ComboBoxWidget(QWidget *parent)
1667  : KComboBox(false, parent)
1668 {
1669  m_kwp->setIsRedirected(true);
1670  //setAutoMask(true);
1671  if (view()) {
1672  view()->installEventFilter(this);
1673  }
1674  setMouseTracking(true);
1675 }
1676 
1677 void ComboBoxWidget::showPopup()
1678 {
1679  QPoint p = pos();
1680  QPoint dest(p);
1681  QWidget *parent = parentWidget();
1682  KHTMLView *v = m_kwp->rootViewPos(dest);
1683  int zoomLevel = v ? v->zoomLevel() : 100;
1684  if (zoomLevel != 100) {
1685  if (v) {
1686  // we need to place the popup even lower on the screen, take in count the widget is bigger
1687  // now, so we add also the difference between the original height, and the zoomed height
1688  dest.setY(dest.y() + (sizeHint().height() * zoomLevel / 100 - sizeHint().height()));
1689  }
1690  }
1691  bool blocked = blockSignals(true);
1692  if (v != parent) {
1693  setParent(v);
1694  }
1695  move(dest);
1696  blockSignals(blocked);
1697 
1699 
1700  blocked = blockSignals(true);
1701  if (v != parent) {
1702  setParent(parent);
1703  // undo side effect of setParent()
1704  show();
1705  }
1706  move(p);
1707  blockSignals(blocked);
1708 }
1709 
1710 void ComboBoxWidget::hidePopup()
1711 {
1713 }
1714 
1715 bool ComboBoxWidget::event(QEvent *e)
1716 {
1717  if (KComboBox::event(e)) {
1718  return true;
1719  }
1720  if (e->type() == QEvent::KeyPress) {
1721  QKeyEvent *ke = static_cast<QKeyEvent *>(e);
1722  switch (ke->key()) {
1723  case Qt::Key_Return:
1724  case Qt::Key_Enter:
1725  showPopup();
1726  ke->accept();
1727  return true;
1728  default:
1729  return false;
1730  }
1731  }
1732  return false;
1733 }
1734 
1735 bool ComboBoxWidget::eventFilter(QObject *dest, QEvent *e)
1736 {
1737  if (dest == view() && e->type() == QEvent::KeyPress) {
1738  QKeyEvent *ke = static_cast<QKeyEvent *>(e);
1739  bool forward = false;
1740  switch (ke->key()) {
1741  case Qt::Key_Tab:
1742  forward = true;
1743  // fall through
1744  case Qt::Key_Backtab:
1745  // ugly hack. emulate popdownlistbox() (private in QComboBox)
1746  // we re-use ke here to store the reference to the generated event.
1748  QApplication::sendEvent(dest, ke);
1749  focusNextPrevChild(forward);
1750  delete ke;
1751  return true;
1752  default:
1753  return KComboBox::eventFilter(dest, e);
1754  }
1755  }
1756  return KComboBox::eventFilter(dest, e);
1757 }
1758 
1759 void ComboBoxWidget::keyPressEvent(QKeyEvent *e)
1760 {
1761  // Normally, widgets are not sent Tab keys this way in the first
1762  // place as they are handled by QWidget::event() for focus handling
1763  // already. But we get our events via EventPropagator::sendEvent()
1764  // directly. Ignore them so that HTMLGenericFormElementImpl::
1765  // defaultEventHandler() can call focusNextPrev().
1766  if (e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab) {
1767  e->ignore();
1768  return;
1769  }
1771 }
1772 
1773 // -------------------------------------------------------------------------
1774 
1775 RenderSelect::RenderSelect(HTMLSelectElementImpl *element)
1776  : RenderFormElement(element)
1777 {
1778  m_ignoreSelectEvents = false;
1779  m_multiple = element->multiple();
1780  m_size = element->size();
1781  m_useListBox = (m_multiple || m_size > 1);
1782  m_selectionChanged = true;
1783  m_optionsChanged = true;
1784 
1785  if (m_useListBox) {
1786  setQWidget(createListBox());
1787  } else {
1788  setQWidget(createComboBox());
1789  getProxyStyle(); // We always need it to make sure popups are big enough
1790  }
1791 }
1792 
1793 void RenderSelect::clearItemFlags(int index, Qt::ItemFlags flags)
1794 {
1795  if (m_useListBox) {
1796  QListWidgetItem *item = static_cast<QListWidget *>(m_widget)->item(index);
1797  item->setFlags(item->flags() & ~flags);
1798  } else {
1799  KComboBox *combo = static_cast<KComboBox *>(m_widget);
1800  if (QStandardItemModel *model = qobject_cast<QStandardItemModel *>(combo->model())) {
1801  QStandardItem *item = model->item(index);
1802  item->setFlags(item->flags() & ~flags);
1803  }
1804  }
1805 }
1806 
1807 void RenderSelect::setStyle(RenderStyle *_style)
1808 {
1809  RenderFormElement::setStyle(_style);
1810  if (!m_useListBox) {
1811  KHTMLProxyStyle *proxyStyle = static_cast<KHTMLProxyStyle *>(getProxyStyle());
1812  proxyStyle->noBorder = shouldDisableNativeBorders();
1813  }
1814 }
1815 
1816 void RenderSelect::updateFromElement()
1817 {
1818  m_ignoreSelectEvents = true;
1819 
1820  // change widget type
1821  bool oldMultiple = m_multiple;
1822  unsigned oldSize = m_size;
1823  bool oldListbox = m_useListBox;
1824 
1825  m_multiple = element()->multiple();
1826  m_size = element()->size();
1827  m_useListBox = (m_multiple || m_size > 1);
1828 
1829  if (oldMultiple != m_multiple || oldSize != m_size) {
1830  if (m_useListBox != oldListbox) {
1831  // type of select has changed
1832  if (m_useListBox) {
1833  setQWidget(createListBox());
1834  } else {
1835  setQWidget(createComboBox());
1836  }
1837 
1838  // Call setStyle() to fix unwanted font size change (#142722)
1839  // and to update our proxy style properties
1840  setStyle(style());
1841  }
1842 
1843  if (m_useListBox && oldMultiple != m_multiple) {
1844  static_cast<QListWidget *>(m_widget)->setSelectionMode(m_multiple ?
1847  }
1848  m_selectionChanged = true;
1849  m_optionsChanged = true;
1850  }
1851 
1852  // update contents listbox/combobox based on options in m_element
1853  if (m_optionsChanged) {
1854  if (element()->m_recalcListItems) {
1855  element()->recalcListItems();
1856  }
1857  const QVector<HTMLGenericFormElementImpl *> listItems = element()->listItems();
1858  int listIndex;
1859 
1860  if (m_useListBox) {
1861  static_cast<QListWidget *>(m_widget)->clear();
1862  } else {
1863  static_cast<KComboBox *>(m_widget)->clear();
1864  }
1865 
1866  for (listIndex = 0; listIndex < int(listItems.size()); listIndex++) {
1867  if (listItems[listIndex]->id() == ID_OPTGROUP) {
1868  DOMString text = listItems[listIndex]->getAttribute(ATTR_LABEL);
1869  if (text.isNull()) {
1870  text = "";
1871  }
1872 
1873  text = text.implementation()->collapseWhiteSpace(false, false);
1874 
1875  if (m_useListBox) {
1876  QListWidgetItem *item = new QListWidgetItem(QString(text.implementation()->s, text.implementation()->l));
1877  static_cast<QListWidget *>(m_widget)->insertItem(listIndex, item);
1878  } else {
1879  static_cast<KComboBox *>(m_widget)->insertItem(listIndex, QString(text.implementation()->s, text.implementation()->l));
1880  }
1881 
1882  bool disabled = !listItems[listIndex]->getAttribute(ATTR_DISABLED).isNull();
1883  if (disabled) {
1884  clearItemFlags(listIndex, Qt::ItemIsSelectable | Qt::ItemIsEnabled);
1885  } else {
1886  clearItemFlags(listIndex, Qt::ItemIsSelectable);
1887  }
1888  } else if (listItems[listIndex]->id() == ID_OPTION) {
1889  HTMLOptionElementImpl *optElem = static_cast<HTMLOptionElementImpl *>(listItems[listIndex]);
1890 
1891  DOMString domText = optElem->text();
1892  // Prefer label if set
1893  DOMString label = optElem->getAttribute(ATTR_LABEL);
1894  if (!label.isEmpty()) {
1895  domText = label;
1896  }
1897  domText = domText.implementation()->collapseWhiteSpace(false, false);
1898 
1899  QString text;
1900 
1901  ElementImpl *parentOptGroup = optElem->parentNode()->id() == ID_OPTGROUP ?
1902  static_cast<ElementImpl *>(optElem->parentNode()) : nullptr;
1903 
1904  if (parentOptGroup) {
1905  text = QLatin1String(" ") + domText.string();
1906  } else {
1907  text = domText.string();
1908  }
1909 
1910  if (m_useListBox) {
1911  static_cast<QListWidget *>(m_widget)->insertItem(listIndex, text);
1912  } else {
1913  static_cast<KComboBox *>(m_widget)->insertItem(listIndex, text);
1914  }
1915 
1916  bool disabled = !optElem->getAttribute(ATTR_DISABLED).isNull();
1917  if (parentOptGroup) {
1918  disabled = disabled || !parentOptGroup->getAttribute(ATTR_DISABLED).isNull();
1919  }
1920 
1921  if (disabled) {
1922  clearItemFlags(listIndex, Qt::ItemIsSelectable | Qt::ItemIsEnabled);
1923  }
1924  } else {
1925  KHTMLAssert(false);
1926  }
1927 
1928  m_selectionChanged = true;
1929  }
1930 
1931  // QComboBox caches the size hint unless you call setFont (ref: TT docu)
1932  if (!m_useListBox) {
1933  KComboBox *that = static_cast<KComboBox *>(m_widget);
1934  that->setFont(that->font());
1935  }
1936  setNeedsLayoutAndMinMaxRecalc();
1937  m_optionsChanged = false;
1938  }
1939 
1940  // update selection
1941  if (m_selectionChanged) {
1942  updateSelection();
1943  }
1944 
1945  m_ignoreSelectEvents = false;
1946 
1947  RenderFormElement::updateFromElement();
1948 }
1949 
1950 short RenderSelect::baselinePosition(bool f) const
1951 {
1952  if (m_useListBox) {
1953  return RenderFormElement::baselinePosition(f);
1954  }
1955 
1956  int bTop = shouldDisableNativeBorders() ? borderTop() : 0;
1957  int bBottom = shouldDisableNativeBorders() ? borderBottom() : 0;
1958  int ret = (height() - RenderWidget::paddingTop() - RenderWidget::paddingBottom() - bTop - bBottom + 1) / 2;
1959  ret += marginTop() + RenderWidget::paddingTop() + bTop;
1960  ret += ((fontMetrics(f).ascent()) / 2) - 2;
1961  return ret;
1962 }
1963 
1964 void RenderSelect::calcMinMaxWidth()
1965 {
1966  KHTMLAssert(!minMaxKnown());
1967 
1968  if (m_optionsChanged) {
1969  updateFromElement();
1970  }
1971 
1972  // ### ugly HACK FIXME!!!
1973  setMinMaxKnown();
1974  layoutIfNeeded();
1975  setNeedsLayoutAndMinMaxRecalc();
1976  // ### end FIXME
1977 
1978  RenderFormElement::calcMinMaxWidth();
1979 }
1980 
1981 void RenderSelect::layout()
1982 {
1983  KHTMLAssert(needsLayout());
1984  KHTMLAssert(minMaxKnown());
1985 
1986  // ### maintain selection properly between type/size changes, and work
1987  // out how to handle multiselect->singleselect (probably just select
1988  // first selected one)
1989 
1990  // calculate size
1991  if (m_useListBox) {
1992  QListWidget *w = static_cast<QListWidget *>(m_widget);
1993 
1994  int width = 0;
1995  int height = 0;
1996 
1997  QAbstractItemModel *m = w->model();
2000  so.font = w->font();
2001 
2002  for (int rowIndex = 0; rowIndex < w->count(); rowIndex++) {
2003  QModelIndex mi = m->index(rowIndex, 0);
2004  QSize s = d->sizeHint(so, mi);
2005  width = qMax(width, s.width());
2006  height = qMax(height, s.height());
2007  }
2008 
2009  if (!height) {
2010  height = w->fontMetrics().height();
2011  }
2012  if (!width) {
2013  width = w->fontMetrics().width('x');
2014  }
2015 
2016  int size = m_size;
2017  // check if multiple and size was not given or invalid
2018  // Internet Exploder sets size to qMin(number of elements, 4)
2019  // Netscape seems to simply set it to "number of elements"
2020  // the average of that is IMHO qMin(number of elements, 10)
2021  // so I did that ;-)
2022  if (size < 1) {
2023  size = qMin(w->count(), 10);
2024  }
2025 
2026  QStyleOptionFrame opt;
2027  opt.initFrom(w);
2028  opt.lineWidth = w->lineWidth();
2029  opt.midLineWidth = w->midLineWidth();
2030  opt.frameShape = w->frameShape();
2032  QRect o = opt.rect;
2033  int hfw = (r.left() - o.left()) + (o.right() - r.right());
2034  int vfw = (r.top() - o.top()) + (o.bottom() - r.bottom());
2035 
2036  width += hfw + w->verticalScrollBar()->sizeHint().width();
2037  // FIXME BASELINE: the 3 lines below could be removed.
2038  int lhs = m_widget->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
2039  if (lhs > 0) {
2040  width += lhs;
2041  }
2042  height = size * height + vfw;
2043 
2044  assert(includesPadding());
2045  width -= RenderWidget::paddingLeft() + RenderWidget::paddingRight();
2046  height -= RenderWidget::paddingTop() + RenderWidget::paddingBottom();
2047 
2048  setIntrinsicWidth(width);
2049  setIntrinsicHeight(height);
2050  } else {
2051  QSize s(m_widget->sizeHint());
2052  int w = s.width();
2053  int h = s.height();
2054 
2055  if (shouldDisableNativeBorders()) {
2056  const int dfw = 2 * m_widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, m_widget);
2057  w -= dfw;
2058  h -= dfw;
2059  }
2060 
2061  setIntrinsicWidth(w);
2062  setIntrinsicHeight(h);
2063  }
2064 
2065  /// uuh, ignore the following line..
2066  setNeedsLayout(true);
2067  RenderFormElement::layout();
2068 
2069  // and now disable the widget in case there is no <option> given
2070  const QVector<HTMLGenericFormElementImpl *> listItems = element()->listItems();
2071 
2072  bool foundOption = false;
2073  for (int i = 0; i < listItems.size() && !foundOption; i++) {
2074  foundOption = (listItems[i]->id() == ID_OPTION);
2075  }
2076 
2077  m_widget->setEnabled(foundOption && ! element()->disabled());
2078 }
2079 
2080 void RenderSelect::slotSelected(int index) // emitted by the combobox only
2081 {
2082  if (m_ignoreSelectEvents) {
2083  return;
2084  }
2085 
2086  KHTMLAssert(!m_useListBox);
2087 
2088  const QVector<HTMLGenericFormElementImpl *> listItems = element()->listItems();
2089  if (index >= 0 && index < int(listItems.size())) {
2090  bool found = (listItems[index]->id() == ID_OPTION);
2091 
2092  if (!found) {
2093  // this one is not selectable, we need to find an option element
2094  while (index < listItems.size()) {
2095  if (listItems[index]->id() == ID_OPTION) {
2096  found = true;
2097  break;
2098  }
2099  ++index;
2100  }
2101 
2102  if (!found) {
2103  while (index >= 0) {
2104  if (listItems[index]->id() == ID_OPTION) {
2105  found = true;
2106  break;
2107  }
2108  --index;
2109  }
2110  }
2111  }
2112 
2113  if (found) {
2114  bool changed = false;
2115 
2116  for (int i = 0; i < listItems.size(); ++i)
2117  if (listItems[i]->id() == ID_OPTION && i != index) {
2118  HTMLOptionElementImpl *opt = static_cast<HTMLOptionElementImpl *>(listItems[i]);
2119  changed |= (opt->m_selected == true);
2120  opt->m_selected = false;
2121  }
2122 
2123  HTMLOptionElementImpl *opt = static_cast<HTMLOptionElementImpl *>(listItems[index]);
2124  changed |= (opt->m_selected == false);
2125  opt->m_selected = true;
2126 
2127  if (index != static_cast<ComboBoxWidget *>(m_widget)->currentIndex()) {
2128  static_cast<ComboBoxWidget *>(m_widget)->setCurrentIndex(index);
2129  }
2130 
2131  // When selecting an optgroup item, and we move forward to we
2132  // shouldn't emit onChange. Hence this bool, the if above doesn't do it.
2133  if (changed) {
2134  ref();
2135  element()->onChange();
2136  deref();
2137  }
2138  }
2139  }
2140 }
2141 
2142 void RenderSelect::slotSelectionChanged() // emitted by the listbox only
2143 {
2144  if (m_ignoreSelectEvents) {
2145  return;
2146  }
2147 
2148  // don't use listItems() here as we have to avoid recalculations - changing the
2149  // option list will make use update options not in the way the user expects them
2150  const QVector<HTMLGenericFormElementImpl *> listItems = element()->m_listItems;
2151  for (int i = 0; i < listItems.count(); i++)
2152  // don't use setSelected() here because it will cause us to be called
2153  // again with updateSelection.
2154  if (listItems[i]->id() == ID_OPTION)
2155  static_cast<HTMLOptionElementImpl *>(listItems[i])
2156  ->m_selected = static_cast<QListWidget *>(m_widget)->item(i)->isSelected();
2157 
2158  ref();
2159  element()->onChange();
2160  deref();
2161 }
2162 
2163 void RenderSelect::setOptionsChanged(bool _optionsChanged)
2164 {
2165  m_optionsChanged = _optionsChanged;
2166 }
2167 
2168 void RenderSelect::setPadding()
2169 {
2170  RenderFormElement::setPadding();
2171 }
2172 
2173 ListBoxWidget *RenderSelect::createListBox()
2174 {
2175  ListBoxWidget *lb = new ListBoxWidget(view()->widget());
2176  lb->setSelectionMode(m_multiple ? QListWidget::ExtendedSelection : QListWidget::SingleSelection);
2177  connect(lb, SIGNAL(itemSelectionChanged()), this, SLOT(slotSelectionChanged()));
2178  m_ignoreSelectEvents = false;
2179  lb->setMouseTracking(true);
2180 
2181  return lb;
2182 }
2183 
2184 ComboBoxWidget *RenderSelect::createComboBox()
2185 {
2186  ComboBoxWidget *cb = new ComboBoxWidget(view()->widget());
2187  connect(cb, SIGNAL(activated(int)), this, SLOT(slotSelected(int)));
2188  return cb;
2189 }
2190 
2191 void RenderSelect::updateSelection()
2192 {
2193  const QVector<HTMLGenericFormElementImpl *> listItems = element()->listItems();
2194  int i;
2195  if (m_useListBox) {
2196  // if multi-select, we select only the new selected index
2197  QListWidget *listBox = static_cast<QListWidget *>(m_widget);
2198  for (i = 0; i < int(listItems.size()); i++)
2199  listBox->item(i)->setSelected(listItems[i]->id() == ID_OPTION &&
2200  static_cast<HTMLOptionElementImpl *>(listItems[i])->selectedBit());
2201  } else {
2202  bool found = false;
2203  int firstOption = i = listItems.size();
2204  while (i--)
2205  if (listItems[i]->id() == ID_OPTION) {
2206  if (found) {
2207  static_cast<HTMLOptionElementImpl *>(listItems[i])->m_selected = false;
2208  } else if (static_cast<HTMLOptionElementImpl *>(listItems[i])->selectedBit()) {
2209  static_cast<KComboBox *>(m_widget)->setCurrentIndex(i);
2210  found = true;
2211  }
2212  firstOption = i;
2213  }
2214 
2215  if (!found && firstOption != listItems.size()) {
2216  // select first option (IE7/Gecko behaviour)
2217  static_cast<HTMLOptionElementImpl *>(listItems[firstOption])->m_selected = true;
2218  static_cast<KComboBox *>(m_widget)->setCurrentIndex(firstOption);
2219  }
2220  }
2221 
2222  m_selectionChanged = false;
2223 }
2224 
2225 // -------------------------------------------------------------------------
2226 
2227 TextAreaWidget::TextAreaWidget(int wrap, QWidget *parent)
2228  : KTextEdit(parent)
2229 {
2230  m_kwp->setIsRedirected(true);
2231 
2232  if (wrap != DOM::HTMLTextAreaElementImpl::ta_NoWrap) {
2233  setLineWrapMode(QTextEdit::WidgetWidth);
2234  } else {
2235  setLineWrapMode(QTextEdit::NoWrap);
2236  }
2237 
2238  setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
2239  setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
2240 
2241  KCursor::setAutoHideCursor(viewport(), true);
2242  setAcceptRichText(false);
2243  setMouseTracking(true);
2244 }
2245 
2246 TextAreaWidget::~TextAreaWidget()
2247 {
2248 }
2249 
2250 void TextAreaWidget::scrollContentsBy(int dx, int dy)
2251 {
2253  update();
2254 }
2255 
2256 bool TextAreaWidget::event(QEvent *e)
2257 {
2258 #if 0
2259  if (e->type() == QEvent::AccelAvailable && isReadOnly()) {
2260  QKeyEvent *ke = (QKeyEvent *) e;
2261  if (ke->modifiers() & Qt::ControlModifier) {
2262  switch (ke->key()) {
2263  case Qt::Key_Left:
2264  case Qt::Key_Right:
2265  case Qt::Key_Up:
2266  case Qt::Key_Down:
2267  case Qt::Key_Home:
2268  case Qt::Key_End:
2269  ke->accept();
2270  default:
2271  break;
2272  }
2273  }
2274  }
2275 #endif
2276  // accept all wheel events so that they are not propagated to the view
2277  // once either end of the widget is reached.
2278  bool ret = KTextEdit::event(e);
2279  if (e->type() == QEvent::Wheel) {
2280  e->accept();
2281  ret = true;
2282  }
2283  return ret;
2284 }
2285 
2286 void TextAreaWidget::keyPressEvent(QKeyEvent *e)
2287 {
2288  // The ComboBoxWidget::keyPressEvent() comment about having to
2289  // deal with events coming from EventPropagator::sendEvent()
2290  // directly applies here, too.
2291  if ((e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab) &&
2292  tabChangesFocus()) {
2293  e->ignore();
2294  return;
2295  }
2297 }
2298 
2299 // -------------------------------------------------------------------------
2300 
2301 RenderTextArea::RenderTextArea(HTMLTextAreaElementImpl *element)
2302  : RenderFormElement(element)
2303 {
2304  TextAreaWidget *edit = new TextAreaWidget(element->wrap(), view());
2305  setQWidget(edit);
2306  const KHTMLSettings *settings = view()->part()->settings();
2307  edit->setCheckSpellingEnabled(settings->autoSpellCheck());
2308  edit->setTabChangesFocus(! settings->allowTabulation());
2309 
2310  connect(edit, SIGNAL(textChanged()), this, SLOT(slotTextChanged()));
2311 
2312  setText(element->value().string());
2313  m_textAlignment = edit->alignment();
2314 }
2315 
2316 RenderTextArea::~RenderTextArea()
2317 {
2318  element()->m_value = text();
2319 }
2320 
2321 void RenderTextArea::handleFocusOut()
2322 {
2323  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2324 
2325  if (w && element()->m_changed) {
2326  element()->m_changed = false;
2327  element()->onChange();
2328  }
2329 }
2330 
2331 void RenderTextArea::calcMinMaxWidth()
2332 {
2333  KHTMLAssert(!minMaxKnown());
2334 
2335  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2336  const QFontMetrics &m = style()->fontMetrics();
2337  w->setTabStopWidth(8 * m.width(" "));
2338  int lvs = qMax(0, w->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
2339  int lhs = qMax(0, w->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing));
2340  int llm = qMax(0, w->style()->pixelMetric(QStyle::PM_LayoutLeftMargin));
2341  int lrm = qMax(0, w->style()->pixelMetric(QStyle::PM_LayoutRightMargin));
2342  int lbm = qMax(0, w->style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
2343  int ltm = qMax(0, w->style()->pixelMetric(QStyle::PM_LayoutTopMargin));
2344 
2345  QStyleOptionFrame opt;
2346  opt.initFrom(w);
2347  opt.lineWidth = w->lineWidth();
2348  opt.midLineWidth = w->midLineWidth();
2349  opt.frameShape = w->frameShape();
2350  QRect r = w->style()->subElementRect(QStyle::SE_ShapedFrameContents, &opt, w);
2351  QRect o = opt.rect;
2352  int hfw = (r.left() - o.left()) + (o.right() - r.right());
2353  int vfw = (r.top() - o.top()) + (o.bottom() - r.bottom());
2354 
2355  QSize size(qMax(element()->cols(), 1L)*m.width('x') + hfw + llm + lrm +
2356  w->verticalScrollBar()->sizeHint().width() + lhs,
2357  qMax(element()->rows(), 1L)*m.lineSpacing() + vfw + lbm + ltm +
2358  (w->lineWrapMode() == QTextEdit::NoWrap ?
2359  w->horizontalScrollBar()->sizeHint().height() + lvs : 0)
2360  );
2361 
2362  assert(includesPadding());
2363  size.rwidth() -= RenderWidget::paddingLeft() + RenderWidget::paddingRight();
2364  size.rheight() -= RenderWidget::paddingTop() + RenderWidget::paddingBottom();
2365 
2366  setIntrinsicWidth(size.width());
2367  setIntrinsicHeight(size.height());
2368 
2369  RenderFormElement::calcMinMaxWidth();
2370 }
2371 
2372 void RenderTextArea::setStyle(RenderStyle *_style)
2373 {
2374  RenderFormElement::setStyle(_style);
2375 
2376  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2377 
2378  if (m_textAlignment != textAlignment()) {
2379  m_textAlignment = textAlignment();
2380  bool unsubmittedFormChange = element()->m_unsubmittedFormChange;
2381  bool blocked = w->blockSignals(true);
2382  int cx = w->horizontalScrollBar()->value();
2383  int cy = w->verticalScrollBar()->value();
2384  QTextCursor tc = w->textCursor();
2385  // Set alignment on all textarea's paragraphs
2386  w->selectAll();
2387  w->setAlignment(m_textAlignment);
2388  w->setTextCursor(tc);
2389  w->horizontalScrollBar()->setValue(cx);
2390  w->verticalScrollBar()->setValue(cy);
2391  w->blockSignals(blocked);
2392  element()->m_unsubmittedFormChange = unsubmittedFormChange;
2393  }
2394 
2395  if (style()->overflowX() == OSCROLL) {
2396  w->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2397  } else if (style()->overflowX() == OHIDDEN) {
2398  w->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
2399  } else {
2400  w->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
2401  }
2402  if (style()->overflowY() == OSCROLL) {
2403  w->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
2404  } else if (style()->overflowY() == OHIDDEN) {
2405  w->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
2406  } else {
2407  w->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
2408  }
2409 }
2410 
2411 short RenderTextArea::scrollWidth() const
2412 {
2413  return RenderObject::scrollWidth();
2414 }
2415 
2416 int RenderTextArea::scrollHeight() const
2417 {
2418  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2419  int contentHeight = qRound(w->document()->size().height());
2420  return qMax(contentHeight, RenderObject::clientHeight());
2421 }
2422 
2423 void RenderTextArea::setText(const QString &newText)
2424 {
2425  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2426 
2427  // When this is called, m_value in the element must have just
2428  // been set to new value --- see if we have any work to do
2429 
2430  QString oldText = text();
2431  int oldTextLen = oldText.length();
2432  int newTextLen = newText.length();
2433  if (newTextLen != oldTextLen || newText != oldText) {
2434  bool blocked = w->blockSignals(true);
2435  int cx = w->horizontalScrollBar()->value();
2436  int cy = w->verticalScrollBar()->value();
2437  // Not using setPlaintext as it resets text alignment property
2438  int minLen = qMin(newTextLen, oldTextLen);
2439  int ex = 0;
2440  while (ex < minLen && (newText.at(ex) == oldText.at(ex))) {
2441  ++ex;
2442  }
2443  QTextCursor tc = w->textCursor();
2446  tc.insertText(newText.right(newTextLen - ex));
2447 
2448  if (oldTextLen == 0) {
2450  } else {
2452  }
2453  w->setTextCursor(tc);
2454  w->horizontalScrollBar()->setValue(cx);
2455  w->verticalScrollBar()->setValue(cy);
2456  w->blockSignals(blocked);
2457  }
2458 }
2459 
2460 void RenderTextArea::updateFromElement()
2461 {
2462  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2463  w->setReadOnly(element()->readOnly());
2464  w->setPlaceholderText(element()->placeholder().string());
2465  RenderFormElement::updateFromElement();
2466 }
2467 
2468 QString RenderTextArea::text()
2469 {
2470  // ### We may want to cache this when physical, since the DOM no longer caches,
2471  // but seeing how text() has always been called on textChanged(), it's probably not needed
2472 
2473  QString txt;
2474  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2475 #ifdef __GNUC__
2476 #warning "Physical wrap mode needs testing (also in ::selection*)"
2477 #endif
2478  if (element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical) {
2479  QTextCursor tc(w->document());
2480  while (!tc.atEnd()) {
2482  txt += tc.selectedText();
2483  if (tc.movePosition(QTextCursor::Right)) {
2484  txt += QLatin1String("\n");
2486  } else {
2487  break;
2488  }
2489  }
2490  } else {
2491  txt = w->toPlainText();
2492  }
2493  return txt;
2494 }
2495 
2496 void RenderTextArea::highLightWord(unsigned int length, unsigned int pos)
2497 {
2498  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2499  if (w) {
2500  w->highlightWord(length, pos);
2501  }
2502 }
2503 
2504 void RenderTextArea::slotTextChanged()
2505 {
2506  element()->m_changed = true;
2507  if (element()->m_value != text()) {
2508  element()->m_unsubmittedFormChange = true;
2509  }
2510 }
2511 
2512 void RenderTextArea::select()
2513 {
2514  static_cast<TextAreaWidget *>(m_widget)->selectAll();
2515 }
2516 
2517 long RenderTextArea::selectionStart()
2518 {
2519  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2520  return w->textCursor().selectionStart();
2521 }
2522 
2523 long RenderTextArea::selectionEnd()
2524 {
2525  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2526  return w->textCursor().selectionEnd();
2527 }
2528 
2529 static void setPhysWrapPos(QTextCursor &otc, bool selStart, int idx)
2530 {
2531  QTextCursor tc = otc;
2532  tc.setPosition(0);
2534  while (!tc.atEnd()) {
2535  if (tc.movePosition(QTextCursor::Down) && tc.position() < idx) {
2536  --idx;
2537  }
2538  if (tc.position() >= idx) {
2539  break;
2540  }
2541  }
2543 }
2544 
2545 void RenderTextArea::setSelectionStart(long offset)
2546 {
2547  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2548  QTextCursor tc = w->textCursor();
2549  if (element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical) {
2550  setPhysWrapPos(tc, true /*selStart*/, offset);
2551  } else {
2552  tc.setPosition(offset);
2553  }
2554  w->setTextCursor(tc);
2555 }
2556 
2557 void RenderTextArea::setSelectionEnd(long offset)
2558 {
2559  TextAreaWidget *w = static_cast<TextAreaWidget *>(m_widget);
2560  QTextCursor tc = w->textCursor();
2561  if (element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical) {
2562  setPhysWrapPos(tc, false /*selStart*/, offset);
2563  } else {
2565  }
2566  w->setTextCursor(tc);
2567 }
2568 
2569 void RenderTextArea::setSelectionRange(long start, long end)
2570 {
2571  setSelectionStart(start);
2572  setSelectionEnd(end);
2573 }
2574 // ---------------------------------------------------------------------------
2575 
Settings for the HTML view.
int position() const const
PreferLocalFile
void setBottom(int y)
ScrollBarAsNeeded
void setStyleSheet(const QString &styleSheet)
static void rebuildKSycoca(QWidget *parent)
ControlModifier
Qt::KeyboardModifiers modifiers() const const
void setBackgroundMode(Qt::BGMode mode)
virtual QSize sizeHint() const const override
QString & append(QChar ch)
QEvent::Type type() const const
int ascent() const const
CE_ComboBoxLabel
QAbstractItemModel * model() const const
QString toDisplayString(QUrl::FormattingOptions options) const const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const =0
int width() const const
virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const override
QString name(const QVariant &location)
QString writableLocation(QStandardPaths::StandardLocation type)
SolidPattern
bool isSelected() const const
void setRenderHint(QPainter::RenderHint hint, bool on)
int right() const const
virtual QSize minimumSizeHint() const const override
static KServiceTypeTrader * self()
Qt::ItemFlags flags() const const
QSize globalStrut()
QStyle * style() const const
virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const const =0
This file is part of the HTML rendering engine for KDE.
const QObjectList & children() const const
QString selectedText() const const
QTextStream & right(QTextStream &stream)
void translate(int dx, int dy)
bool isVisible() const const
QPoint mapToGlobal(const QPoint &pos) const const
void save()
SE_PushButtonContents
virtual void keyPressEvent(QKeyEvent *e) override
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
virtual int exec()
TransparentMode
Renders and displays HTML in a QScrollArea.
Definition: khtmlview.h:97
int height() const const
int x() const const
int y() const const
QString itemText(int index) const const
bool event(QEvent *) override
bool exists() const const
QString & remove(int position, int n)
KGuiItem cancel()
Qt::ItemFlags flags() const const
virtual QPoint globalPositionHint() const
const QPoint & globalPos() const const
QCA_EXPORT ProviderList providers()
QAction * addAction(const QString &text)
void ref()
QAction * spelling(const QObject *recvr, const char *slot, QObject *parent)
NoContextMenu
void setBrushOrigin(int x, int y)
typedef Alignment
int x() const const
int y() const const
bool movePosition(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode, int n)
void setModified(bool)
bool insert(Part *part, qint64 *insertId=nullptr)
QTextStream & left(QTextStream &stream)
virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const const override
void initFrom(const QWidget *widget)
void setBuddy(QWidget *buddy)
void setPath(const QString &path, QUrl::ParsingMode mode)
KHTMLPart * part() const
Returns a pointer to the KHTMLPart that is rendering the page.
Definition: khtmlview.h:139
virtual bool event(QEvent *event) override
void clear()
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
int count(const T &value) const const
void ignore()
QIcon itemIcon(int index) const const
void deref()
void setLayout(QLayout *layout)
void installEventFilter(QObject *filterObj)
KGuiItem stop()
int top() const const
void setPen(const QColor &color)
void setFocus()
virtual void hidePopup()
void setTop(int y)
QString label(StandardShortcut id)
int left() const const
void insertText(const QString &text)
void setFlags(Qt::ItemFlags flags)
void setFlags(Qt::ItemFlags flags)
void setWidth(int width)
bool isEmpty() const const
QString trimmed() const const
bool sendEvent(QObject *receiver, QEvent *event)
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool event(QEvent *) override
QAbstractItemDelegate * itemDelegate() const const
virtual QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *option, QStyle::SubControl sc, const QWidget *widget) const const override
void setBrush(const QBrush &brush)
This class implements the basic string we use in the DOM.
Definition: dom_string.h:44
virtual bool eventFilter(QObject *watched, QEvent *event)
QAction * addSeparator()
void hide()
virtual QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const const override
QListWidgetItem * item(int row) const const
QScrollBar * verticalScrollBar() const const
QRect intersected(const QRect &rectangle) const const
QAction * exec()
bool isWindow() const const
QString right(int n) const const
const QList< QKeySequence > & replace()
const QList< QKeySequence > & forward()
static void setAutoHideCursor(QWidget *w, bool enable, bool customEventFilter=false)
int key() const const
void accept()
bool blockSignals(bool block)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
void setFont(const QFont &)
virtual void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const const override
void restore()
virtual void mouseMoveEvent(QMouseEvent *e) override
QString i18n(const char *text, const TYPE &arg...)
This library provides a full-featured HTML parser and widget.
void setRight(int x)
const QList< QKeySequence > & end()
KService::List query(const QString &servicetype, const QString &constraint=QString()) const
bool hasFrame() const const
PM_DefaultFrameWidth
int width() const const
QFontMetrics fontMetrics() const const
KIOFILEWIDGETS_EXPORT QString dir(const QString &fileClass)
void drawRects(const QRectF *rectangles, int rectCount)
QStyle * style()
void setStandardButtons(QDialogButtonBox::StandardButtons buttons)
QSize expandedTo(const QSize &otherSize) const const
bool isNull() const const
void keyPressEvent(QKeyEvent *) override
const QChar at(int position) const const
void setWindowTitle(const QString &)
int height() const const
int height() const const
int count(const T &value) const const
void translate(int dx, int dy)
TextShowMnemonic
void adjust(int dx1, int dy1, int dx2, int dy2)
int bottom() const const
Base Class for all rendering tree objects.
QPoint topLeft() const const
int length() const const
virtual bool event(QEvent *e) override
void setX(int x)
void setY(int y)
void init(const QWidget *widget)
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const const =0
void setText(const QString &text)
DOMStringImpl * implementation() const
Definition: dom_string.h:145
void update(Part *part, const QByteArray &data, qint64 dataSize)
QIcon fromTheme(const QString &name)
bool atEnd() const const
QSize size(int flags, const QString &text, int tabStops, int *tabArray) const const
void show()
virtual QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const const =0
int width(const QString &text, int len) const const
KIOCORE_EXPORT CopyJob * move(const QUrl &src, const QUrl &dest, JobFlags flags=DefaultFlags)
QAbstractItemModel * model() const const
const QList< QKeySequence > & selectAll()
void setPoints(int nPoints, const int *points)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int size() const const
virtual void setText(const QString &)
void setStyle(QStyle *style)
virtual void showPopup()
void setSelected(bool select)
const KHTMLSettings * settings() const
virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const const =0
Key_Left
void setEnabled(bool)
int lineSpacing() const const
int zoomLevel() const
Retrieve the current zoom level.
Definition: khtmlview.cpp:1113
bool mkpath(const QString &dirPath) const const
QUrl fromLocalFile(const QString &localFile)
void sorry(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
void addLayout(QLayout *layout, int stretch)
virtual void scrollContentsBy(int dx, int dy) override
typedef ItemFlags
void setPosition(int pos, QTextCursor::MoveMode m)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:07 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.