src/gui/styles/qs60style.cpp
changeset 22 79de32ba3296
parent 19 fcece45ef507
child 23 89e065397ea6
--- a/src/gui/styles/qs60style.cpp	Mon May 03 13:17:34 2010 +0300
+++ b/src/gui/styles/qs60style.cpp	Fri May 14 16:40:13 2010 +0300
@@ -122,6 +122,8 @@
 
 qint64 QS60StylePrivate::m_webPaletteKey = 0;
 
+QPointer<QWidget> QS60StylePrivate::m_pressedWidget = 0;
+
 const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameElementsData[] = {
     {SE_ButtonNormal,           QS60StyleEnums::SP_QsnFrButtonTbCenter},
     {SE_ButtonPressed,          QS60StyleEnums::SP_QsnFrButtonTbCenterPressed},
@@ -138,6 +140,8 @@
     {SE_PanelBackground,        QS60StyleEnums::SP_QsnFrSetOptCenter},
     {SE_ButtonInactive,         QS60StyleEnums::SP_QsnFrButtonCenterInactive},
     {SE_Editor,                 QS60StyleEnums::SP_QsnFrInputCenter},
+    {SE_TableItemPressed,       QS60StyleEnums::SP_QsnFrGridCenterPressed},
+    {SE_ListItemPressed,        QS60StyleEnums::SP_QsnFrListPressed},
 };
 
 static const int frameElementsCount =
@@ -294,6 +298,12 @@
     case SE_DropArea:
         drawPart(QS60StyleEnums::SP_QgnGrafOrgBgGrid, painter, rect, flags | SF_PointNorth);
         break;
+    case SE_TableItemPressed:
+        drawFrame(SF_TableItemPressed, painter, rect, flags | SF_PointNorth);
+        break;
+    case SE_ListItemPressed:
+        drawFrame(SF_ListItemPressed, painter, rect, flags | SF_PointNorth);
+        break;
     default:
         break;
     }
@@ -542,6 +552,7 @@
     QRect endRect;
 
     if (orientation == Qt::Horizontal) {
+        startRect.setHeight(rect.height());
         startRect.setWidth(qMin((rect.width() >> 1) - 1, startRect.width()));
         endRect = startRect.translated(rect.width() - startRect.width(), 0);
         middleRect.adjust(startRect.width(), 0, -startRect.width(), 0);
@@ -551,6 +562,7 @@
             endRect.adjust(overlap, 0, 0, 0);
         }
     } else {
+        startRect.setWidth(rect.width());
         startRect.setHeight(qMin((rect.height() >> 1) - 1, startRect.height()));
         endRect = startRect.translated(0, rect.height() - startRect.height());
         middleRect.adjust(0, startRect.height(), 0, -startRect.height());
@@ -939,6 +951,11 @@
             backgroundBrush.style() == Qt::NoBrush) ? true : false;
 }
 
+bool QS60StylePrivate::isWidgetPressed(const QWidget *widget)
+{
+    return (widget && widget == m_pressedWidget);
+}
+
 /*!
   \class QS60Style
   \brief The QS60Style class provides a look and feel suitable for applications on S60.
@@ -1357,14 +1374,13 @@
             optionComboBox.palette.setColor(QPalette::Inactive, QPalette::WindowText,
                 optionComboBox.palette.text().color() );
             QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
-            painter->save();
-            painter->setClipRect(editRect);
+            const int frameW = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
 
             if (!comboBox->currentIcon.isNull()) {
-                QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
-                QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode);
+                const QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
+                const QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode);
                 QRect iconRect(editRect);
-                iconRect.setWidth(comboBox->iconSize.width() + 4);
+                iconRect.setWidth(comboBox->iconSize.width() + frameW);
                 iconRect = alignedRect(comboBox->direction,
                                        Qt::AlignLeft | Qt::AlignVCenter,
                                        iconRect.size(), editRect);
@@ -1373,17 +1389,19 @@
                 drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
 
                 if (comboBox->direction == Qt::RightToLeft)
-                    editRect.translate(-4 - comboBox->iconSize.width(), 0);
+                    editRect.setRight(editRect.right() - frameW - comboBox->iconSize.width());
                 else
-                    editRect.translate(comboBox->iconSize.width() + 4, 0);
+                    editRect.setLeft(comboBox->iconSize.width() + frameW);
             }
             if (!comboBox->currentText.isEmpty() && !comboBox->editable) {
+                const Qt::TextElideMode elideMode = (comboBox->direction == Qt::LeftToRight) ? Qt::ElideRight : Qt::ElideLeft;
+                const QString text = comboBox->fontMetrics.elidedText(comboBox->currentText, elideMode, editRect.width());
+
                 QCommonStyle::drawItemText(painter,
                             editRect.adjusted(QS60StylePrivate::pixelMetric(PM_FrameCornerWidth), 0, -1, 0),
                             visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter),
-                            comboBox->palette, comboBox->state & State_Enabled, comboBox->currentText);
+                            comboBox->palette, comboBox->state & State_Enabled, text);
             }
-            painter->restore();
         }
         break;
 #endif //QT_NO_COMBOBOX
@@ -1424,73 +1442,37 @@
             // draw themed background for table unless background brush has been defined.
             if (vopt->backgroundBrush == Qt::NoBrush) {
                 if (itemView) {
-                    const QModelIndex index = vopt->index;
-                    //todo: Draw cell background only once - for the first cell.
-                    QStyleOptionViewItemV4 voptAdj2 = voptAdj;
-                    const QModelIndex indexFirst = itemView->model()->index(0, 0);
-                    const QModelIndex indexLast = itemView->model()->index(
-                            itemView->model()->rowCount() - 1, itemView->model()->columnCount() -1);
-                    if (itemView->viewport())
-                        voptAdj2.rect = QRect( itemView->visualRect(indexFirst).topLeft(),
-                                itemView->visualRect(indexLast).bottomRight()).intersect(itemView->viewport()->rect());
                     drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);
                 }
             } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);}
 
-            // draw the focus rect
-            if (isSelected || hasFocus ) {
-                QRect highlightRect = option->rect.adjusted(1,1,-1,-1);
-                QAbstractItemView::SelectionBehavior selectionBehavior =
-                    itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems;
-                if (selectionBehavior != QAbstractItemView::SelectItems) {
-                    // set highlight rect so that it is continuous from cell to cell, yet sligthly
-                    // smaller than cell rect
-                    int xBeginning = 0, yBeginning = 0, xEnd = 0, yEnd = 0;
-                    if (selectionBehavior == QAbstractItemView::SelectRows) {
-                        yBeginning = 1; yEnd = -1;
-                        if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning)
-                            xBeginning = 1;
-                        else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End)
-                            xEnd = -1;
-                    } else if (selectionBehavior == QAbstractItemView::SelectColumns) {
-                        xBeginning = 1; xEnd = -1;
-                        if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning)
-                            yBeginning = 1;
-                        else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End)
-                            yEnd = -1;
-                    }
-                    highlightRect = option->rect.adjusted(xBeginning, yBeginning, xEnd, yEnd);
-                }
-                if (vopt->showDecorationSelected &&
-                    (vopt->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()))
-                    QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, highlightRect, flags);
-                else
-                    painter->fillRect(highlightRect, vopt->palette.highlight());
-            }
-
              // draw the icon
              const QIcon::Mode mode = (voptAdj.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled;
-             const QIcon::State state = voptAdj.state & State_Open ? QIcon::On : QIcon::Off;
+             const QIcon::State state = (voptAdj.state & State_Open) ? QIcon::On : QIcon::Off;
              voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state);
 
              // Draw selection check mark. Show check mark only in multi selection modes.
              if (itemView) {
                  const bool singleSelection =
                      (itemView->selectionMode() == QAbstractItemView::SingleSelection ||
-                      itemView->selectionMode() == QAbstractItemView::NoSelection);
+                      itemView->selectionMode() == QAbstractItemView::NoSelection)||
+                     (itemView->selectionModel()->selectedIndexes().count() < 2 );
+
+                 const bool selectItemsOnly = (itemView->selectionBehavior() == QAbstractItemView::SelectItems);
+
                  const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget);
 
                  QStyleOptionViewItemV4 checkMarkOption(voptAdj);
-                 // Draw selection mark.
-                 if (voptAdj.state & State_Selected && !singleSelection) {
+                 if (selectionRect.isValid())
                      checkMarkOption.rect = selectionRect;
-                     drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget);
-                     if ( textRect.right() > selectionRect.left() )
+                 // Draw selection mark.
+                 if (isSelected && !singleSelection && selectItemsOnly) {
+                     proxy()->drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget);
+                     // @todo: this should happen in the rect retrievel i.e. subElementRect()
+                     if (textRect.right() > selectionRect.left())
                          textRect.setRight(selectionRect.left());
                  } else if (singleSelection &&
-                     voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator &&
-                     selectionRect.isValid()) {
-                     checkMarkOption.rect = selectionRect;
+                     voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator) {
                      checkMarkOption.state = checkMarkOption.state & ~State_HasFocus;
 
                      switch (vopt->checkState) {
@@ -1562,7 +1544,6 @@
                     QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
                 const int tabOverlap =
                     QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness;
-                //todo: draw navi wipe behind tabbar - must be drawn with first draw
 
                 if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive||
                         skinElement==QS60StylePrivate::SE_TabBarTabEastActive||
@@ -1666,7 +1647,7 @@
                     painter->drawPixmap(tr.left() + tabOverlap,
                                         tr.center().y() - (tabIcon.height() >> 1),
                                         tabIcon);
-                tr.setLeft(tr.left() + iconSize.width() + 4);
+                tr.setLeft(tr.left() + iconSize.width() + 4); //todo: magic four
             }
 
             QCommonStyle::drawItemText(painter, tr, alignment, optionTab.palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
@@ -1985,14 +1966,14 @@
             // We need to reduce the focus frame size if LayoutSpacing is smaller than FocusFrameMargin
             // Otherwise, we would overlay adjacent widgets.
             const int frameHeightReduction =
-                    qMin(0, pixelMetric(QStyle::PM_LayoutVerticalSpacing)
-                            - pixelMetric(QStyle::PM_FocusFrameVMargin));
+                    qMin(0, pixelMetric(PM_LayoutVerticalSpacing)
+                            - pixelMetric(PM_FocusFrameVMargin));
             const int frameWidthReduction =
-                    qMin(0, pixelMetric(QStyle::PM_LayoutHorizontalSpacing)
-                            - pixelMetric(QStyle::PM_FocusFrameHMargin));
+                    qMin(0, pixelMetric(PM_LayoutHorizontalSpacing)
+                            - pixelMetric(PM_FocusFrameHMargin));
             const int rounding =
-                    qMin(pixelMetric(QStyle::PM_FocusFrameVMargin),
-                            pixelMetric(QStyle::PM_LayoutVerticalSpacing));
+                    qMin(pixelMetric(PM_FocusFrameVMargin),
+                            pixelMetric(PM_LayoutVerticalSpacing));
             const QRect frameRect =
                     option->rect.adjusted(-frameWidthReduction, -frameHeightReduction,
                             frameWidthReduction, frameHeightReduction);
@@ -2037,7 +2018,10 @@
             if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color())
                 if ((qstyleoption_cast<const QStyleOptionFocusRect *>(option) &&
                     (qobject_cast<const QRadioButton *>(widget) || qobject_cast<const QCheckBox *>(widget))))
-                        QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
+                        QS60StylePrivate::drawSkinElement(
+                            QS60StylePrivate::isWidgetPressed(widget) ? 
+                                QS60StylePrivate::SE_ListItemPressed : 
+                                QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
             else
                 commonStyleDraws = true;
             }
@@ -2257,6 +2241,57 @@
         break;
 #ifndef QT_NO_ITEMVIEWS
     case PE_PanelItemViewItem:
+        if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
+            const bool isSelected = (vopt->state & State_Selected);
+            const bool hasFocus = (vopt->state & State_HasFocus);
+            const bool isPressed = QS60StylePrivate::isWidgetPressed(widget);
+
+            if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()) {
+                QRect highlightRect = vopt->rect.adjusted(1,1,-1,-1);
+                const QAbstractItemView *itemView = qobject_cast<const QAbstractItemView *>(widget);
+                QAbstractItemView::SelectionBehavior selectionBehavior =
+                    itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems;
+                // Set the draw area for highlights (focus, select rect or pressed rect)
+                if (hasFocus || isSelected || isPressed) {
+                    if (selectionBehavior != QAbstractItemView::SelectItems) {
+                        // set highlight rect so that it is continuous from cell to cell, yet sligthly
+                        // smaller than cell rect
+                        int xBeginning = 0, yBeginning = 0, xEnd = 0, yEnd = 0;
+                        if (selectionBehavior == QAbstractItemView::SelectRows) {
+                            yBeginning = 1; yEnd = -1;
+                            if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning)
+                                xBeginning = 1;
+                            else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End)
+                                xEnd = -1;
+                        } else if (selectionBehavior == QAbstractItemView::SelectColumns) {
+                            xBeginning = 1; xEnd = -1;
+                            if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning)
+                                yBeginning = 1;
+                            else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End)
+                                yEnd = -1;
+                        }
+                        highlightRect = option->rect.adjusted(xBeginning, yBeginning, xEnd, yEnd);
+                    }
+                }
+                bool tableView = false;
+                if (itemView && qobject_cast<const QTableView *>(widget))
+                    tableView = true;
+
+                QS60StylePrivate::SkinElements element;
+                QRect elementRect = option->rect;
+
+                //draw item is drawn as pressed, if it already has focus.
+                if (isPressed && (hasFocus || isSelected)) {
+                    element = tableView ? QS60StylePrivate::SE_TableItemPressed : QS60StylePrivate::SE_ListItemPressed;
+                } else if (hasFocus || (isSelected && selectionBehavior != QAbstractItemView::SelectItems)) {
+                    element = QS60StylePrivate::SE_ListHighlight;
+                    elementRect = highlightRect;
+                }
+                QS60StylePrivate::drawSkinElement(element, painter, elementRect, flags);
+            } else {
+                QCommonStyle::drawPrimitive(element, option, painter, widget);
+            }
+        }
         break;
 #endif //QT_NO_ITEMVIEWS
 
@@ -2433,7 +2468,7 @@
                 const int contentHeight =
                         qMax(qMax(iconHeight, decoratorHeight) + pixelMetric(PM_ButtonMargin),
                              textHeight + 2*pixelMetric(PM_ButtonMargin));
-                sz.setHeight(contentHeight);
+                sz.setHeight(qMax(sz.height(), contentHeight));
                 sz += QSize(2 * pixelMetric(PM_ButtonMargin), 0);
             }
             break;
@@ -2814,7 +2849,7 @@
                     const int tabOverlapNoBorder =
                         QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap);
                     const int tabOverlap =
-                        tabOverlapNoBorder-QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
+                        tabOverlapNoBorder - QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
                     const QTabWidget *tab = qobject_cast<const QTabWidget *>(widget);
                     int gain = (tab) ? tabOverlap * tab->count() : 0;
                     switch (twf->shape) {
@@ -2880,7 +2915,7 @@
                         ret = QRect();
                     } else {
                         if (menuItem->direction == Qt::RightToLeft)
-                            ret.translate(ret.width()-indicatorWidth, 0);
+                            ret.translate(ret.width() - indicatorWidth, 0);
                         ret.setWidth(indicatorWidth);
                     }
                 } else {
@@ -3067,8 +3102,11 @@
 void QS60Style::polish(QApplication *application)
 {
     Q_D(QS60Style);
+    QCommonStyle::polish(qApp);
     d->m_originalPalette = application->palette();
     d->setThemePalette(application);
+    if (QS60StylePrivate::isTouchSupported())
+        qApp->installEventFilter(this);
 }
 
 /*!
@@ -3077,10 +3115,14 @@
 void QS60Style::unpolish(QApplication *application)
 {
     Q_UNUSED(application)
+
     Q_D(QS60Style);
+    QCommonStyle::unpolish(qApp);
     const QPalette newPalette = QApplication::style()->standardPalette();
     QApplication::setPalette(newPalette);
     QApplicationPrivate::setSystemPalette(d->m_originalPalette);
+    if (QS60StylePrivate::isTouchSupported())
+        qApp->removeEventFilter(this);
 }
 
 /*!
@@ -3227,9 +3269,40 @@
 */
 bool QS60Style::eventFilter(QObject *object, QEvent *event)
 {
+    Q_D(QS60Style);
+    switch(event->type()) {
+        case QEvent::MouseButtonPress: {
+            QWidget *w = QApplication::widgetAt(QCursor::pos());
+            if (w) {
+                QWidget *focusW = w->focusProxy();
+                if (qobject_cast<QAbstractItemView *>(focusW) ||
+                    qobject_cast<QRadioButton *>(focusW) ||
+                    qobject_cast<QCheckBox *>(focusW))
+                    d->m_pressedWidget = focusW;
+                else if (qobject_cast<QAbstractItemView *>(w)||
+                        qobject_cast<QRadioButton *>(w) ||
+                        qobject_cast<QCheckBox *>(w))
+                    d->m_pressedWidget = w;
+
+                if ( d->m_pressedWidget)
+                    d->m_pressedWidget->update();
+            }
+            break;
+        }
+        case QEvent::MouseButtonRelease: {
+            const QWidget *w = QApplication::widgetAt(QCursor::pos());
+            if (w && d->m_pressedWidget) {
+                d->m_pressedWidget->update();
+                d->m_pressedWidget = 0;
+            }
+            break;
+        }
+        default:
+            break;
+    }
+
 #ifdef Q_WS_S60
 #ifndef QT_NO_PROGRESSBAR
-    Q_D(QS60Style);
     switch(event->type()) {
     case QEvent::StyleChange:
     case QEvent::Show:
@@ -3242,15 +3315,17 @@
         break;
     case QEvent::Destroy:
     case QEvent::Hide:
-        d->stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim);
-        d->m_bars.removeAll(reinterpret_cast<QProgressBar *>(object));
+        if (QProgressBar *bar = reinterpret_cast<QProgressBar *>(object)) {
+            d->stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim);
+            d->m_bars.removeAll(bar);
+        }
         break;
     default:
         break;
     }
 #endif // QT_NO_PROGRESSBAR
 #endif // Q_WS_S60
-    return QStyle::eventFilter(object, event);
+    return QCommonStyle::eventFilter(object, event);
 }
 
 /*!