diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2019-06-20 13:00:58 +0000 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2019-06-21 16:48:37 +0200 |
commit | 430b406e5e8249983fc030aa0f867372f5da74d2 (patch) | |
tree | fb5e326d134821ad60354fa8ca7344c95907fbf9 /vcl/qt5 | |
parent | 6540912ae1a570fd8c2318f77b757e07b87c0707 (diff) |
tdf#105884 Qt5 implement TabControl theming
Drawing a QTabWidget is a really complex procedure. The main
problems I had were the adjustment of the frame, which I totally
missed in the Qt code for a long time.
Then there is the frame gap, which Qt draws by simply overlapping
the items a bit with the frame. And all the calculations need the
tabs together with the pane. None of it really fits very good into
the way VCL handles drawing the TabControl and since I needed a
way back from the plugin into VCL for the nOverlap value, there is
this hack using a static. I hope nOverlap never changes.
Change-Id: I8fe6eb12d39a2ac7f6fb89424586cac76e12545b
Reviewed-on: https://gerrit.libreoffice.org/74480
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'vcl/qt5')
-rw-r--r-- | vcl/qt5/Qt5Graphics_Controls.cxx | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/vcl/qt5/Qt5Graphics_Controls.cxx b/vcl/qt5/Qt5Graphics_Controls.cxx index 6cefef623a73..73a47e5e5ffa 100644 --- a/vcl/qt5/Qt5Graphics_Controls.cxx +++ b/vcl/qt5/Qt5Graphics_Controls.cxx @@ -105,6 +105,10 @@ bool Qt5Graphics_Controls::isNativeControlSupported(ControlType type, ControlPar case ControlType::Slider: return (part == ControlPart::TrackHorzArea || part == ControlPart::TrackVertArea); + case ControlType::TabItem: + case ControlType::TabPane: + return ((part == ControlPart::Entire) || part == ControlPart::TabPaneWithHeader); + default: break; } @@ -112,7 +116,6 @@ bool Qt5Graphics_Controls::isNativeControlSupported(ControlType type, ControlPar return false; } -/// helper drawing methods namespace { void draw(QStyle::ControlElement element, QStyleOption* option, QImage* image, @@ -163,6 +166,27 @@ void lcl_drawFrame(QStyle::PrimitiveElement element, QImage* image, QStyle::Stat painter.setClipRegion(QRegion(aRect).subtracted(aRect.adjusted(fw, fw, -fw, -fw))); QApplication::style()->drawPrimitive(element, &option, &painter); } + +void lcl_fillQStyleOptionTab(const ImplControlValue& value, QStyleOptionTab& sot) +{ + const TabitemValue& rValue = static_cast<const TabitemValue&>(value); + if (rValue.isFirst()) + sot.position = rValue.isLast() ? QStyleOptionTab::OnlyOneTab : QStyleOptionTab::Beginning; + else if (rValue.isLast()) + sot.position = rValue.isFirst() ? QStyleOptionTab::OnlyOneTab : QStyleOptionTab::End; + else + sot.position = QStyleOptionTab::Middle; +} + +void lcl_fullQStyleOptionTabWidgetFrame(QStyleOptionTabWidgetFrame& option) +{ + option.state = QStyle::State_Enabled; + option.rightCornerWidgetSize = QSize(0, 0); + option.leftCornerWidgetSize = QSize(0, 0); + option.lineWidth = QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth); + option.midLineWidth = 0; + option.shape = QTabBar::RoundedNorth; +} } bool Qt5Graphics_Controls::drawNativeControl(ControlType type, ControlPart part, @@ -609,6 +633,34 @@ bool Qt5Graphics_Controls::drawNativeControl(ControlType type, ControlPart part, draw(QStyle::CE_ProgressBar, &option, m_image.get(), vclStateValue2StateFlag(nControlState, value)); } + else if (type == ControlType::TabItem && part == ControlPart::Entire) + { + QStyleOptionTab sot; + lcl_fillQStyleOptionTab(value, sot); + draw(QStyle::CE_TabBarTabShape, &sot, m_image.get(), + vclStateValue2StateFlag(nControlState, value)); + } + else if (type == ControlType::TabPane && part == ControlPart::Entire) + { + const TabPaneValue& rValue = static_cast<const TabPaneValue&>(value); + + // get the overlap size for the tabs, so they will overlap the frame + QStyleOptionTab tabOverlap; + tabOverlap.shape = QTabBar::RoundedNorth; + TabPaneValue::m_nOverlap + = QApplication::style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &tabOverlap); + + QStyleOptionTabWidgetFrame option; + lcl_fullQStyleOptionTabWidgetFrame(option); + option.tabBarRect = toQRect(rValue.m_aTabHeaderRect); + option.selectedTabRect + = rValue.m_aSelectedTabRect.IsEmpty() ? QRect() : toQRect(rValue.m_aSelectedTabRect); + option.tabBarSize = toQSize(rValue.m_aTabHeaderRect.GetSize()); + option.rect = m_image->rect(); + QRect aRect = QApplication::style()->subElementRect(QStyle::SE_TabWidgetTabPane, &option); + draw(QStyle::PE_FrameTabWidget, &option, m_image.get(), + vclStateValue2StateFlag(nControlState, value), aRect); + } else { returnVal = false; @@ -818,7 +870,7 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart auto nStyle = static_cast<DrawFrameFlags>(val.getNumericVal() & 0xFFF0); if (nStyle & DrawFrameFlags::NoDraw) { - int nFrameWidth + const int nFrameWidth = QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth); contentRect.adjust(nFrameWidth, nFrameWidth, -nFrameWidth, -nFrameWidth); } @@ -912,6 +964,31 @@ bool Qt5Graphics_Controls::getNativeControlRegion(ControlType type, ControlPart } break; } + case ControlType::TabItem: + { + QStyleOptionTab sot; + lcl_fillQStyleOptionTab(val, sot); + QSize aMinSize = QApplication::style()->sizeFromContents(QStyle::CT_TabBarTab, &sot, + contentRect.size()); + contentRect.setSize(aMinSize); + boundingRect = contentRect; + retVal = true; + break; + } + case ControlType::TabPane: + { + const TabPaneValue& rValue = static_cast<const TabPaneValue&>(val); + QStyleOptionTabWidgetFrame sotwf; + lcl_fullQStyleOptionTabWidgetFrame(sotwf); + QSize aMinSize = QApplication::style()->sizeFromContents( + QStyle::CT_TabWidget, &sotwf, + QSize(std::max(rValue.m_aTabHeaderRect.GetWidth(), controlRegion.GetWidth()), + rValue.m_aTabHeaderRect.GetHeight() + controlRegion.GetHeight())); + contentRect.setSize(aMinSize); + boundingRect = contentRect; + retVal = true; + break; + } default: break; } |