📄 render_form.cpp
字号:
RenderBlock::setStyle(_style);
// WinIE renders fieldsets with display:inline like they're inline-blocks. For us,
// an inline-block is just a block element with replaced set to true and inline set
// to true. Ensure that if we ended up being inline that we set our replaced flag
// so that we're treated like an inline-block.
if (isInline())
setReplaced(true);
}
// -------------------------------------------------------------------------
RenderFileButton::RenderFileButton(HTMLInputElementImpl *element)
: RenderFormElement(element)
{
#if APPLE_CHANGES
KWQFileButton *w = new KWQFileButton(view()->part());
connect(w, SIGNAL(textChanged(const QString &)),this,SLOT(slotTextChanged(const QString &)));
connect(w, SIGNAL(clicked()), this, SLOT(slotClicked()));
setQWidget(w);
#else
QHBox *w = new QHBox(view()->viewport());
m_edit = new LineEditWidget(w);
connect(m_edit, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
connect(m_edit, SIGNAL(textChanged(const QString &)),this,SLOT(slotTextChanged(const QString &)));
m_button = new QPushButton(i18n("Browse..."), w);
m_button->setFocusPolicy(QWidget::ClickFocus);
connect(m_button,SIGNAL(clicked()), this, SLOT(slotClicked()));
w->setStretchFactor(m_edit, 2);
w->setFocusProxy(m_edit);
setQWidget(w);
#endif
}
void RenderFileButton::calcMinMaxWidth()
{
KHTMLAssert( !minMaxKnown() );
#if APPLE_CHANGES
// Let the widget tell us how big it wants to be.
int size = element()->size();
QSize s(static_cast<KWQFileButton *>(widget())->sizeForCharacterWidth(size > 0 ? size : 20));
#else
const QFontMetrics &fm = style()->fontMetrics();
QSize s;
int size = element()->size();
int h = fm.lineSpacing();
int w = fm.width( 'x' ) * (size > 0 ? size : 17); // "some"
w += 6 + fm.width( m_button->text() ) + 2*fm.width( ' ' );
s = QSize(w + 2 + 2*m_edit->frameWidth(),
QMAX(h, 14) + 2 + 2*m_edit->frameWidth())
.expandedTo(QApplication::globalStrut());
#endif
setIntrinsicWidth( s.width() );
setIntrinsicHeight( s.height() );
RenderFormElement::calcMinMaxWidth();
}
#if !APPLE_CHANGES
void RenderFileButton::handleFocusOut()
{
if ( m_edit && m_edit->edited() ) {
element()->onChange();
m_edit->setEdited( false );
}
}
#endif
void RenderFileButton::slotClicked()
{
#if APPLE_CHANGES
RenderFormElement::slotClicked();
#else
QString file_name = KFileDialog::getOpenFileName(QString::null, QString::null, 0, i18n("Browse..."));
if (!file_name.isNull()) {
element()->m_value = DOMString(file_name);
m_edit->setText(file_name);
}
#endif
}
void RenderFileButton::updateFromElement()
{
#if APPLE_CHANGES
static_cast<KWQFileButton *>(widget())->setFilename(element()->value().string());
#else
m_edit->blockSignals(true);
m_edit->setText(element()->value().string());
m_edit->blockSignals(false);
int ml = element()->maxLength();
if ( ml <= 0 || ml > 1024 )
ml = 1024;
m_edit->setMaxLength( ml );
m_edit->setEdited( false );
#endif
RenderFormElement::updateFromElement();
}
void RenderFileButton::slotReturnPressed()
{
if (element()->form())
element()->form()->prepareSubmit();
}
void RenderFileButton::slotTextChanged(const QString &string)
{
element()->m_value = DOMString(string);
element()->onChange();
}
void RenderFileButton::select()
{
#if !APPLE_CHANGES
m_edit->selectAll();
#endif
}
#if APPLE_CHANGES
void RenderFileButton::click(bool sendMouseEvents)
{
static_cast<KWQFileButton *>(widget())->click(sendMouseEvents);
}
#endif
// -------------------------------------------------------------------------
RenderLabel::RenderLabel(HTMLGenericFormElementImpl *element)
: RenderFormElement(element)
{
}
// -------------------------------------------------------------------------
RenderLegend::RenderLegend(HTMLGenericFormElementImpl *element)
: RenderBlock(element)
{
}
// -------------------------------------------------------------------------------
ComboBoxWidget::ComboBoxWidget(QWidget *parent)
: KComboBox(false, parent)
{
setAutoMask(true);
if (listBox()) listBox()->installEventFilter(this);
setMouseTracking(true);
}
bool ComboBoxWidget::event(QEvent *e)
{
#if !APPLE_CHANGES
if (e->type()==QEvent::KeyPress)
{
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
switch(ke->key())
{
case Key_Return:
case Key_Enter:
popup();
ke->accept();
return true;
default:
return KComboBox::event(e);
}
}
#endif
return KComboBox::event(e);
}
bool ComboBoxWidget::eventFilter(QObject *dest, QEvent *e)
{
#if !APPLE_CHANGES
if (dest==listBox() && e->type()==QEvent::KeyPress)
{
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
bool forward = false;
switch(ke->key())
{
case Key_Tab:
forward=true;
case Key_BackTab:
// ugly hack. emulate popdownlistbox() (private in QComboBox)
// we re-use ke here to store the reference to the generated event.
ke = new QKeyEvent(QEvent::KeyPress, Key_Escape, 0, 0);
QApplication::sendEvent(dest,ke);
focusNextPrevChild(forward);
delete ke;
return true;
default:
return KComboBox::eventFilter(dest, e);
}
}
#endif
return KComboBox::eventFilter(dest, e);
}
// -------------------------------------------------------------------------
RenderSelect::RenderSelect(HTMLSelectElementImpl *element)
: RenderFormElement(element)
{
m_ignoreSelectEvents = false;
m_multiple = element->multiple();
m_size = element->size();
m_useListBox = (m_multiple || m_size > 1);
m_selectionChanged = true;
m_optionsChanged = true;
if(m_useListBox)
setQWidget(createListBox());
else
setQWidget(createComboBox());
}
#if APPLE_CHANGES
void RenderSelect::setWidgetWritingDirection()
{
QPainter::TextDirection d = style()->direction() == RTL ? QPainter::RTL : QPainter::LTR;
if (m_useListBox)
static_cast<KListBox *>(m_widget)->setWritingDirection(d);
else
static_cast<ComboBoxWidget *>(m_widget)->setWritingDirection(d);
}
void RenderSelect::setStyle(RenderStyle *s)
{
RenderFormElement::setStyle(s);
setWidgetWritingDirection();
}
#endif
void RenderSelect::updateFromElement()
{
m_ignoreSelectEvents = true;
// change widget type
bool oldMultiple = m_multiple;
unsigned oldSize = m_size;
bool oldListbox = m_useListBox;
m_multiple = element()->multiple();
m_size = element()->size();
m_useListBox = (m_multiple || m_size > 1);
if (oldMultiple != m_multiple || oldSize != m_size) {
if (m_useListBox != oldListbox) {
// type of select has changed
delete m_widget;
if(m_useListBox)
setQWidget(createListBox());
else
setQWidget(createComboBox());
#if APPLE_CHANGES
setWidgetWritingDirection();
#endif
}
if (m_useListBox && oldMultiple != m_multiple) {
static_cast<KListBox*>(m_widget)->setSelectionMode(m_multiple ? QListBox::Extended : QListBox::Single);
}
m_selectionChanged = true;
m_optionsChanged = true;
}
// update contents listbox/combobox based on options in m_element
if ( m_optionsChanged ) {
if (element()->m_recalcListItems)
element()->recalcListItems();
QMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
int listIndex;
if (m_useListBox)
static_cast<KListBox*>(m_widget)->clear();
else
static_cast<KComboBox*>(m_widget)->clear();
for (listIndex = 0; listIndex < int(listItems.size()); listIndex++) {
if (listItems[listIndex]->id() == ID_OPTGROUP) {
QString label = listItems[listIndex]->getAttribute(ATTR_LABEL).string();
label.replace(QChar('\\'), backslashAsCurrencySymbol());
// In WinIE, an optgroup can't start or end with whitespace (other than the indent
// we give it). We match this behavior.
label = label.stripWhiteSpace();
#if NOKIA_CHANGES
QString disabled = listItems[listIndex]->getAttribute(ATTR_DISABLED).string();
bool disable = (disabled.startsWith("disabled",false));
if (m_useListBox)
static_cast<KListBox*>(m_widget)->appendGroupLabel(label, disable);
else
static_cast<KComboBox*>(m_widget)->appendGroupLabel(label, disable);
#else
#if APPLE_CHANGES
if (m_useListBox)
static_cast<KListBox*>(m_widget)->appendGroupLabel(label);
else
static_cast<KComboBox*>(m_widget)->appendGroupLabel(label);
#else
if(m_useListBox) {
QListBoxText *item = new QListBoxText(label);
static_cast<KListBox*>(m_widget)
->insertItem(item, listIndex);
item->setSelectable(false);
}
else
static_cast<KComboBox*>(m_widget)->insertItem(label, listIndex);
#endif
#endif NOKIA_CHANGES
}
else if (listItems[listIndex]->id() == ID_OPTION) {
QString itemText = static_cast<HTMLOptionElementImpl*>(listItems[listIndex])->text().string();
itemText.replace(QChar('\\'), backslashAsCurrencySymbol());
// In WinIE, leading and trailing whitespace is ignored in options. We match this behavior.
itemText = itemText.stripWhiteSpace();
if (listItems[listIndex]->parentNode()->id() == ID_OPTGROUP)
itemText.prepend(" ");
#if APPLE_CHANGES
if (m_useListBox)
static_cast<KListBox*>(m_widget)->appendItem(itemText);
else
static_cast<KComboBox*>(m_widget)->appendItem(itemText);
#else
if(m_useListBox)
static_cast<KListBox*>(m_widget)->insertItem(itemText, listIndex);
else
static_cast<KComboBox*>(m_widget)->insertItem(itemText, listIndex);
#endif
}
else
KHTMLAssert(false);
m_selectionChanged = true;
}
#if APPLE_CHANGES
if (m_useListBox)
static_cast<KListBox*>(m_widget)->doneAppendingItems();
#endif
setNeedsLayoutAndMinMaxRecalc();
m_optionsChanged = false;
}
// update selection
if (m_selectionChanged) {
updateSelection();
}
m_ignoreSelectEvents = false;
RenderFormElement::updateFromElement();
}
#if APPLE_CHANGES
short RenderSelect::baselinePosition( bool f, bool isRootLineBox ) const
{
if (m_useListBox) {
// FIXME: Should get the hardcoded constant of 7 by calling a QListBox function,
// as we do for other widget classes.
return RenderWidget::baselinePosition( f, isRootLineBox ) - 7;
}
return RenderFormElement::baselinePosition( f, isRootLineBox );
}
#endif
void RenderSelect::calcMinMaxWidth()
{
KHTMLAssert( !minMaxKnown() );
if (m_optionsChanged)
updateFromElement();
// ### ugly HACK FIXME!!!
setMinMaxKnown();
layoutIfNeeded();
setNeedsLayoutAndMinMaxRecalc();
// ### end FIXME
RenderFormElement::calcMinMaxWidth();
}
void RenderSelect::layout( )
{
KHTMLAssert(needsLayout());
KHTMLAssert(minMaxKnown());
// ### maintain selection properly between type/size changes, and work
// out how to handle multiselect->singleselect (probably just select
// first selected one)
// calculate size
if(m_useListBox) {
KListBox* w = static_cast<KListBox*>(m_widget);
#if !APPLE_CHANGES
QListBoxItem* p = w->firstItem();
int width = 0;
int height = 0;
while(p) {
width = QMAX(width, p->width(p->listBox()));
height = QMAX(height, p->height(p->listBox()));
p = p->next();
}
#endif
int size = m_size;
// check if multiple and size was not given or invalid
// Internet Exploder sets size to QMIN(number of elements, 4)
// Netscape seems to simply set it to "number of elements"
// the average of that is IMHO QMIN(number of elements, 10)
// so I did that ;-)
if(size < 1)
size = QMIN(static_cast<KListBox*>(m_widget)->count(), 10);
#if APPLE_CHANGES
// Let the widget tell us how big it wants to be.
QSize s(w->sizeForNumberOfLines(size));
setIntrinsicWidth( s.width() );
setIntrinsicHeight( s.height() );
#else
width += 2*w->frameWidth() + w->verticalScrollBar()->sizeHint().width();
height = size*height + 2*w->frameWidth();
setIntrinsicWidth( width );
setIntrinsicHeight( height );
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -