///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2020 Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RiuGuiTheme.h" #include "RiaApplication.h" #include "RiaGuiApplication.h" #include "RiuThemesDirectory.h" #include "cafAppEnum.h" #include "cafPdmUiTreeViewEditor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "qwt_legend_label.h" #include "qwt_picker.h" #include "qwt_plot.h" #include "qwt_plot_curve.h" #include "qwt_plot_grid.h" #include "qwt_plot_marker.h" #include "qwt_symbol.h" RiaDefines::ThemeEnum RiuGuiTheme::s_currentTheme = RiaDefines::ThemeEnum::DEFAULT; QMap> RiuGuiTheme::s_variableValueMap = {}; QMap> RiuGuiTheme::s_variableGuiTextMap = {}; QMap>>> RiuGuiTheme::s_qwtPlotItemPropertiesMap = {}; QMap RiuGuiTheme::s_customStyleSheetApplicators = { { QString( "QwtPlot\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]::curve\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]\\s*\\{(" "?([\\n\\r]*\\s*((line-color|symbol-color):" "\\s*([a-zA-Z0-9#]+)\\s*;))*)[\\n\\r]*\\s*\\}" ), []( QRegularExpressionMatch& match ) { QRegExp plotNameRegExp( match.captured( "plotName" ) ); QRegExp itemNameRegExp( match.captured( "itemName" ) ); QRegularExpression lineColorRegExp( "line-color:\\s*([#0-9a-zA-Z]+)" ); QString lineColor = lineColorRegExp.match( match.captured( "properties" ) ).captured( 1 ); QRegularExpression symbolColorRegExp( "symbol-color:\\s*([#0-9a-zA-Z]+)" ); QString symbolColor = symbolColorRegExp.match( match.captured( "properties" ) ).captured( 1 ); if ( !lineColor.isEmpty() ) { storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "curve" ), match.captured( "itemName" ), "line-color", lineColor ); } if ( !symbolColor.isEmpty() ) { // Symbols get the same color assigned as curves. storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "curve" ), match.captured( "itemName" ), "symbol-color", symbolColor ); } if ( lineColor.isEmpty() && symbolColor.isEmpty() ) return; const QWidgetList topLevelWidgets = RiaGuiApplication::instance()->topLevelWidgets(); for ( QWidget* widget : topLevelWidgets ) { for ( QwtPlot* plotWidget : widget->findChildren() ) { if ( plotNameRegExp.exactMatch( plotWidget->property( "qss-class" ).toString() ) ) { for ( QwtPlotItem* item : plotWidget->itemList() ) { if ( QwtPlotCurve* curve = dynamic_cast( item ) ) { if ( itemNameRegExp.exactMatch( item->title().text() ) || match.captured( "itemName" ) == "*" ) { QPen pen = curve->pen(); pen.setColor( QColor( lineColor ) ); curve->setPen( pen ); if ( curve->symbol() && curve->symbol()->style() != QwtSymbol::NoSymbol ) { QPen pen = curve->symbol()->pen(); pen.setColor( QColor( symbolColor ) ); QwtSymbol* symbol = cloneCurveSymbol( curve ); symbol->setPen( pen ); curve->setSymbol( symbol ); } } } } } plotWidget->replot(); } } } }, { QString( "QwtPlot\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]::grid\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]\\s*\\{(" "?([\\n\\r]*\\s*((color):" "\\s*([a-zA-Z0-9#]+)\\s*;))*)[\\n\\r]*\\s*\\}" ), []( QRegularExpressionMatch& match ) { QRegExp plotNameRegExp( match.captured( "plotName" ) ); QRegExp itemNameRegExp( match.captured( "itemName" ) ); QRegularExpression colorRegExp( "color:\\s*([#0-9a-zA-Z]+)" ); QString color = colorRegExp.match( match.captured( "properties" ) ).captured( 1 ); const QWidgetList topLevelWidgets = RiaGuiApplication::instance()->topLevelWidgets(); if ( !color.isEmpty() ) { storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "grid" ), match.captured( "itemName" ), "color", color ); } for ( QWidget* widget : topLevelWidgets ) { for ( QwtPlot* plotWidget : widget->findChildren() ) { if ( plotNameRegExp.exactMatch( plotWidget->property( "qss-class" ).toString() ) || match.captured( "plotName" ) == "*" ) { for ( QwtPlotItem* item : plotWidget->itemList() ) { if ( QwtPlotGrid* grid = dynamic_cast( item ) ) { if ( itemNameRegExp.exactMatch( item->title().text() ) || match.captured( "itemName" ) == "*" ) { QPen pen = grid->majorPen(); pen.setColor( QColor( color ) ); grid->setPen( pen ); } } } } plotWidget->replot(); } } } }, { QString( "QwtPlot\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]::legend\\s*\\{(" "?([\\n\\r]*\\s*((text-color):" "\\s*([a-zA-Z0-9#]+)\\s*;))*)[\\n\\r]*\\s*\\}" ), []( QRegularExpressionMatch& match ) { QRegExp plotNameRegExp( match.captured( "plotName" ) ); QRegExp itemNameRegExp( match.captured( "itemName" ) ); QRegularExpression colorRegExp( "text-color:\\s*([#0-9a-zA-Z]+)" ); QString color = colorRegExp.match( match.captured( "properties" ) ).captured( 1 ); const QWidgetList topLevelWidgets = RiaGuiApplication::instance()->topLevelWidgets(); if ( !color.isEmpty() ) { storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "legend" ), match.captured( "itemName" ), "text-color", color ); } for ( QWidget* widget : topLevelWidgets ) { for ( QwtPlot* plotWidget : widget->findChildren() ) { if ( plotNameRegExp.exactMatch( plotWidget->property( "qss-class" ).toString() ) || match.captured( "plotName" ) == "*" ) { for ( QwtLegendLabel* label : plotWidget->findChildren() ) { QwtText text = label->text(); text.setColor( QColor( color ) ); label->setText( text ); label->repaint(); } } plotWidget->replot(); } } } }, { QString( "QwtPlot\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]::lineMarker\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]" "\\s*\\{(" "?([\\n\\r]*\\s*((color|text-color):" "\\s*([a-zA-Z0-9#]+)\\s*;))*)[\\n\\r]*\\s*\\}" ), []( QRegularExpressionMatch& match ) { QRegExp plotNameRegExp( match.captured( "plotName" ) ); QRegExp itemNameRegExp( match.captured( "itemName" ) ); QRegularExpression colorRegExp( "color:\\s*([#0-9a-zA-Z]+)" ); QString color = colorRegExp.match( match.captured( "properties" ) ).captured( 1 ); QRegularExpression textColorRegExp( "text-color:\\s*([#0-9a-zA-Z]+)" ); QString textColor = textColorRegExp.match( match.captured( "properties" ) ).captured( 1 ); const QWidgetList topLevelWidgets = RiaGuiApplication::instance()->topLevelWidgets(); if ( !color.isEmpty() ) { storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "lineMarker" ), match.captured( "itemName" ), "color", color ); } if ( !textColor.isEmpty() ) { storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "lineMarker" ), match.captured( "itemName" ), "text-color", textColor ); } for ( QWidget* widget : topLevelWidgets ) { for ( QwtPlot* plotWidget : widget->findChildren() ) { if ( plotNameRegExp.exactMatch( plotWidget->property( "qss-class" ).toString() ) || match.captured( "plotName" ) == "*" ) { for ( QwtPlotItem* item : plotWidget->itemList() ) { if ( QwtPlotMarker* marker = dynamic_cast( item ) ) { if ( marker->symbol() == nullptr || marker->symbol()->style() == QwtSymbol::NoSymbol ) { if ( itemNameRegExp.exactMatch( item->title().text() ) || match.captured( "itemName" ) == "*" ) { QPen pen = marker->linePen(); pen.setColor( QColor( color ) ); marker->setLinePen( pen ); marker->label().setColor( QColor( textColor ) ); } } } } } plotWidget->replot(); } } } }, { QString( "QwtPlot\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]::pointMarker\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]" "\\s*\\{(" "?([\\n\\r]*\\s*((color|text-color):" "\\s*([a-zA-Z0-9#]+)\\s*;))*)[\\n\\r]*\\s*\\}" ), []( QRegularExpressionMatch& match ) { QRegExp plotNameRegExp( match.captured( "plotName" ) ); QRegExp itemNameRegExp( match.captured( "itemName" ) ); QRegularExpression colorRegExp( "color:\\s*([#0-9a-zA-Z]+)" ); QString color = colorRegExp.match( match.captured( "properties" ) ).captured( 1 ); QRegularExpression textColorRegExp( "text-color:\\s*([#0-9a-zA-Z]+)" ); QString textColor = textColorRegExp.match( match.captured( "properties" ) ).captured( 1 ); const QWidgetList topLevelWidgets = RiaGuiApplication::instance()->topLevelWidgets(); if ( !color.isEmpty() ) { storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "pointMarker" ), match.captured( "itemName" ), "color", color ); } if ( !textColor.isEmpty() ) { storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "pointMarker" ), match.captured( "itemName" ), "text-color", textColor ); } for ( QWidget* widget : topLevelWidgets ) { for ( QwtPlot* plotWidget : widget->findChildren() ) { if ( plotNameRegExp.exactMatch( plotWidget->property( "qss-class" ).toString() ) || match.captured( "plotName" ) == "*" ) { for ( QwtPlotItem* item : plotWidget->itemList() ) { if ( QwtPlotMarker* marker = dynamic_cast( item ) ) { if ( marker->symbol() && marker->symbol()->style() != QwtSymbol::NoSymbol ) { if ( itemNameRegExp.exactMatch( item->title().text() ) || match.captured( "itemName" ) == "*" ) { QPen pen = marker->symbol()->pen(); pen.setColor( QColor( color ) ); QwtSymbol* symbol = cloneMarkerSymbol( marker ); symbol->setPen( pen ); marker->setSymbol( symbol ); marker->label().setColor( QColor( textColor ) ); } } } } } plotWidget->replot(); } } } }, { QString( "QwtPlot\\[\"(?[a-zA-Z0-9-_\\*]+)\"\\]::picker" "\\s*\\{(" "?([\\n\\r]*\\s*((text-color):" "\\s*([a-zA-Z0-9#]+)\\s*;))*)[\\n\\r]*\\s*\\}" ), []( QRegularExpressionMatch& match ) { QRegExp plotNameRegExp( match.captured( "plotName" ) ); QRegExp itemNameRegExp( match.captured( "itemName" ) ); QRegularExpression textColorRegExp( "text-color:\\s*([#a-zA-Z0-9]+)" ); QString textColor = textColorRegExp.match( match.captured( "properties" ) ).captured( 1 ); const QWidgetList topLevelWidgets = RiaGuiApplication::instance()->topLevelWidgets(); if ( !textColor.isEmpty() ) { storeQwtStyleSheetProperty( match.captured( "plotName" ), QString( "picker" ), "*", "text-color", textColor ); } for ( QWidget* widget : topLevelWidgets ) { for ( QwtPlot* plotWidget : widget->findChildren() ) { if ( plotNameRegExp.exactMatch( plotWidget->property( "qss-class" ).toString() ) || match.captured( "plotName" ) == "*" ) { QWidget* canvas = plotWidget->canvas(); if ( canvas ) { for ( QwtPicker* picker : canvas->findChildren() ) { QPen pen = picker->trackerPen(); pen.setColor( QColor( textColor ) ); picker->setTrackerPen( pen ); } } } plotWidget->replot(); } } } } }; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiaDefines::ThemeEnum RiuGuiTheme::currentGuiTheme() { return s_currentTheme; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuGuiTheme::updateGuiTheme( RiaDefines::ThemeEnum theme ) { s_currentTheme = theme; s_qwtPlotItemPropertiesMap.clear(); applyStyleSheet( theme ); const QWidgetList allWidgets = RiaGuiApplication::instance()->allWidgets(); for ( QWidget* widget : allWidgets ) { widget->style()->unpolish( widget ); widget->style()->polish( widget ); if ( caf::PdmUiTreeViewWidget* treeViewWidget = dynamic_cast( widget ) ) { treeViewWidget->setStyle( new caf::PdmUiTreeViewStyle ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiuGuiTheme::applyStyleSheet( RiaDefines::ThemeEnum theme ) { QString styleSheetPath = getStyleSheetPath( theme ); QFile styleSheetFile( styleSheetPath ); if ( styleSheetFile.exists() ) { if ( styleSheetFile.open( QIODevice::ReadOnly ) ) { RiaGuiApplication* app = RiaGuiApplication::instance(); QString styleSheet = styleSheetFile.readAll(); preparseStyleSheet( theme, styleSheet ); app->setStyleSheet( styleSheet ); } return true; } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuGuiTheme::changeVariableValue( RiaDefines::ThemeEnum theme, const QString& variableName, const QString& newValue ) { if ( !s_variableValueMap.keys().contains( theme ) ) { s_variableValueMap.insert( theme, {} ); } if ( !s_variableValueMap[theme].keys().contains( variableName ) ) { s_variableValueMap[theme].insert( variableName, newValue ); } else { s_variableValueMap[theme][variableName] = newValue; } } QMap RiuGuiTheme::getVariableValueMap( RiaDefines::ThemeEnum theme ) { if ( !s_variableValueMap.keys().contains( theme ) ) { QFile styleSheetFile( getStyleSheetPath( theme ) ); if ( styleSheetFile.exists() ) { if ( styleSheetFile.open( QIODevice::ReadOnly ) ) { QString styleSheet = styleSheetFile.readAll(); preparseStyleSheet( theme, styleSheet ); return s_variableValueMap[theme]; } } return QMap(); } else { return s_variableValueMap[theme]; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QMap RiuGuiTheme::getVariableGuiTextMap( RiaDefines::ThemeEnum theme ) { if ( !s_variableGuiTextMap.keys().contains( theme ) ) { QFile styleSheetFile( getStyleSheetPath( theme ) ); if ( styleSheetFile.exists() ) { if ( styleSheetFile.open( QIODevice::ReadOnly ) ) { QString styleSheet = styleSheetFile.readAll(); preparseStyleSheet( theme, styleSheet ); return s_variableGuiTextMap[theme]; } } return QMap(); } else { return s_variableGuiTextMap[theme]; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuGuiTheme::applyVariableValueMapToStyleSheet( RiaDefines::ThemeEnum theme ) { QFileInfo info( getStyleSheetPath( theme ) ); QString absoluteStyleSheetPath = QString( "%0/%1" ).arg( GUI_THEMES_DIR ).arg( info.fileName() ); QFile styleSheetFile( absoluteStyleSheetPath ); if ( styleSheetFile.exists() ) { QString styleSheet; if ( styleSheetFile.open( QIODevice::ReadOnly | QIODevice::Truncate | QIODevice::Text ) ) { styleSheet = styleSheetFile.readAll(); QRegularExpression variableRegExp( "(?[ \\t]*(?\\$[a-zA-z0-9_]+)[ \\t]*:[ " "\\t]*)(?[a-zA-Z-_0-9#]+)(?;[ \\t]*(\\/\\/[ " "\\t]*(?(.*)))?)" ); QRegularExpressionMatchIterator matchIterator = variableRegExp.globalMatch( styleSheet ); while ( matchIterator.hasNext() ) { QRegularExpressionMatch match = matchIterator.next(); styleSheet.replace( match.captured( 0 ), QString( "%0%1%2" ) .arg( match.captured( "prefix" ) ) .arg( s_variableValueMap[theme].value( match.captured( "name" ) ) ) .arg( match.captured( "suffix" ) ) ); } } if ( styleSheetFile.open( QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text ) ) { styleSheetFile.write( styleSheet.toLatin1() ); return styleSheet; } } return QString(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RiuGuiTheme::writeStyleSheetToFile( RiaDefines::ThemeEnum theme, const QString& styleSheet ) { QFileInfo info( getStyleSheetPath( theme ) ); QString absoluteStyleSheetPath = QString( "%0/%1" ).arg( GUI_THEMES_DIR ).arg( info.fileName() ); QFile styleSheetFile( absoluteStyleSheetPath ); if ( styleSheetFile.exists() ) { if ( styleSheetFile.open( QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text ) ) { QString modifiedStyleSheet = styleSheet; formatStyleSheetForWriting( modifiedStyleSheet ); styleSheetFile.write( modifiedStyleSheet.toLatin1() ); preparseStyleSheet( theme, modifiedStyleSheet ); RiaGuiApplication* app = RiaGuiApplication::instance(); app->setStyleSheet( modifiedStyleSheet ); const QWidgetList topLevelWidgets = RiaGuiApplication::instance()->allWidgets(); for ( QWidget* widget : topLevelWidgets ) { widget->style()->unpolish( widget ); widget->style()->polish( widget ); } return true; } } return false; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuGuiTheme::loadStyleSheet( RiaDefines::ThemeEnum theme ) { QFile styleSheetFile( getStyleSheetPath( theme ) ); QString styleSheet; if ( styleSheetFile.exists() ) { if ( styleSheetFile.open( QIODevice::ReadOnly ) ) { styleSheet = styleSheetFile.readAll(); } } return styleSheet; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QAbstractItemModel* RiuGuiTheme::getQssCompletionModel( QCompleter* completer ) { QFile file( ":utility/qss-keywords.txt" ); if ( !file.open( QFile::ReadOnly ) ) return new QStringListModel( completer ); QStringList words; while ( !file.atEnd() ) { QByteArray line = file.readLine(); if ( !line.isEmpty() ) words << QString::fromUtf8( line.trimmed() ); } return new QStringListModel( words, completer ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QColor RiuGuiTheme::getColorByVariableName( const QString& variable, RiaDefines::ThemeEnum theme /*= UNDEFINED */ ) { RiaDefines::ThemeEnum eTheme = s_currentTheme; if ( theme != RiaDefines::ThemeEnum::UNDEFINED ) { eTheme = theme; } if ( s_variableValueMap.keys().contains( eTheme ) && s_variableValueMap[eTheme].keys().contains( "$" + variable ) ) { return QColor( s_variableValueMap[eTheme]["$" + variable] ); } return Qt::black; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuGuiTheme::getQwtStyleSheetProperty( QString plotName, const QString& itemType, QString itemName, const QString& propertyName ) { if ( !s_qwtPlotItemPropertiesMap.keys().contains( plotName ) ) { if ( !s_qwtPlotItemPropertiesMap.keys().contains( "*" ) ) { return QString(); } else { plotName = "*"; } } if ( !s_qwtPlotItemPropertiesMap[plotName].keys().contains( itemType ) ) { if ( s_qwtPlotItemPropertiesMap.keys().contains( "*" ) && s_qwtPlotItemPropertiesMap["*"].keys().contains( itemType ) ) { plotName = "*"; } else { return QString(); } } if ( !s_qwtPlotItemPropertiesMap[plotName][itemType].keys().contains( itemName ) ) { if ( !s_qwtPlotItemPropertiesMap[plotName][itemType].keys().contains( "*" ) ) { if ( s_qwtPlotItemPropertiesMap.keys().contains( "*" ) && s_qwtPlotItemPropertiesMap["*"].keys().contains( itemType ) && s_qwtPlotItemPropertiesMap["*"][itemType].keys().contains( "*" ) ) { plotName = "*"; itemName = "*"; } else { return QString(); } } else { itemName = "*"; } } return s_qwtPlotItemPropertiesMap[plotName][itemType][itemName].value( propertyName ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuGuiTheme::styleQwtItem( QwtPlotItem* item ) { QwtPlot* plot = item->plot(); QString plotName; if ( plot && plot->property( "qss-class" ).isValid() ) { plotName = plot->property( "qss-class" ).toString(); } if ( QwtPlotCurve* curve = dynamic_cast( item ) ) { QPen pen = curve->pen(); QString color = getQwtStyleSheetProperty( plotName, "curve", curve->title().text(), "line-color" ); if ( !color.isEmpty() ) pen.setColor( QColor( color ) ); curve->setPen( pen ); if ( curve->symbol() && curve->symbol()->style() != QwtSymbol::NoSymbol ) { pen = curve->symbol()->pen(); QString symbolColor = getQwtStyleSheetProperty( plotName, "curve", curve->title().text(), "symbol-color" ); if ( !color.isEmpty() ) pen.setColor( QColor( symbolColor ) ); QwtSymbol* symbol = cloneCurveSymbol( curve ); symbol->setPen( pen ); curve->setSymbol( symbol ); } } else if ( QwtPlotGrid* grid = dynamic_cast( item ) ) { QPen pen = grid->majorPen(); QString color = getQwtStyleSheetProperty( plotName, "grid", grid->title().text(), "color" ); if ( !color.isEmpty() ) pen.setColor( QColor( color ) ); grid->setPen( pen ); } else if ( QwtPlotMarker* marker = dynamic_cast( item ) ) { if ( marker->symbol() == nullptr || marker->symbol()->style() == QwtSymbol::NoSymbol ) { QPen pen = marker->linePen(); QString color = getQwtStyleSheetProperty( plotName, "lineMarker", marker->title().text(), "color" ); if ( !color.isEmpty() ) pen.setColor( QColor( color ) ); marker->setLinePen( pen ); QString textColor = getQwtStyleSheetProperty( plotName, "lineMarker", marker->title().text(), "text-color" ); if ( !textColor.isEmpty() ) marker->label().setColor( QColor( textColor ) ); } else { QwtSymbol* symbol = cloneMarkerSymbol( marker ); QPen pen = symbol->pen(); QString color = getQwtStyleSheetProperty( plotName, "pointMarker", marker->title().text(), "color" ); if ( !color.isEmpty() ) pen.setColor( QColor( color ) ); symbol->setPen( pen ); marker->setSymbol( symbol ); QString textColor = getQwtStyleSheetProperty( plotName, "pointMarker", marker->title().text(), "text-color" ); if ( !textColor.isEmpty() ) marker->label().setColor( QColor( textColor ) ); } } else if ( QwtPlotMarker* marker = dynamic_cast( item ) ) { if ( marker->symbol() == nullptr || marker->symbol()->style() == QwtSymbol::NoSymbol ) { QPen pen = marker->linePen(); QString color = getQwtStyleSheetProperty( plotName, "lineMarker", marker->title().text(), "color" ); if ( !color.isEmpty() ) pen.setColor( QColor( color ) ); marker->setLinePen( pen ); QString textColor = getQwtStyleSheetProperty( plotName, "lineMarker", marker->title().text(), "text-color" ); if ( !textColor.isEmpty() ) marker->label().setColor( QColor( textColor ) ); } else { QwtSymbol* symbol = cloneMarkerSymbol( marker ); QPen pen = symbol->pen(); QString color = getQwtStyleSheetProperty( plotName, "pointMarker", marker->title().text(), "color" ); if ( !color.isEmpty() ) pen.setColor( QColor( color ) ); symbol->setPen( pen ); marker->setSymbol( symbol ); QString textColor = getQwtStyleSheetProperty( plotName, "pointMarker", marker->title().text(), "text-color" ); if ( !textColor.isEmpty() ) marker->label().setColor( QColor( textColor ) ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuGuiTheme::styleQwtItem( QwtPicker* item ) { QWidget* canvas = item->parentWidget(); if ( canvas ) { QwtPlot* plot = dynamic_cast( canvas->parentWidget() ); if ( plot ) { QString plotName; if ( plot && plot->property( "qss-class" ).isValid() ) { plotName = plot->property( "qss-class" ).toString(); } QPen pen = item->trackerPen(); QString textColor = getQwtStyleSheetProperty( plotName, "picker", "*", "text-color" ); if ( !textColor.isEmpty() ) pen.setColor( QColor( textColor ) ); item->setTrackerPen( pen ); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuGuiTheme::preparseStyleSheet( RiaDefines::ThemeEnum theme, QString& styleSheet ) { QMap colorRoleMap; colorRoleMap.insert( "AlternateBase", QPalette::ColorRole::AlternateBase ); colorRoleMap.insert( "Base", QPalette::ColorRole::Base ); colorRoleMap.insert( "BrightText", QPalette::ColorRole::BrightText ); colorRoleMap.insert( "Button", QPalette::ColorRole::Button ); colorRoleMap.insert( "ButtonText", QPalette::ColorRole::ButtonText ); colorRoleMap.insert( "Dark", QPalette::ColorRole::Dark ); colorRoleMap.insert( "Highlight", QPalette::ColorRole::Highlight ); colorRoleMap.insert( "HighlightedText", QPalette::ColorRole::HighlightedText ); colorRoleMap.insert( "Light", QPalette::ColorRole::Light ); colorRoleMap.insert( "Link", QPalette::ColorRole::Link ); colorRoleMap.insert( "LinkVisited", QPalette::ColorRole::LinkVisited ); colorRoleMap.insert( "Mid", QPalette::ColorRole::Mid ); colorRoleMap.insert( "Midlight", QPalette::ColorRole::Midlight ); colorRoleMap.insert( "NoRole", QPalette::ColorRole::NoRole ); colorRoleMap.insert( "Shadow", QPalette::ColorRole::Shadow ); colorRoleMap.insert( "Text", QPalette::ColorRole::Text ); colorRoleMap.insert( "ToolTipBase", QPalette::ColorRole::ToolTipBase ); colorRoleMap.insert( "ToolTipText", QPalette::ColorRole::ToolTipText ); colorRoleMap.insert( "Window", QPalette::ColorRole::Window ); colorRoleMap.insert( "WindowText", QPalette::ColorRole::WindowText ); QMap colorGroupMap; colorGroupMap.insert( "Active", QPalette::ColorGroup::Active ); colorGroupMap.insert( "Disabled", QPalette::ColorGroup::Disabled ); colorGroupMap.insert( "Inactive", QPalette::ColorGroup::Inactive ); QString regExp = "QPalette::("; regExp += colorRoleMap.keys().join( "|" ); regExp += "){1}(::("; regExp += colorGroupMap.keys().join( "|" ); regExp += "){1})?"; QRegularExpression paletteRegExp( regExp ); QRegularExpressionMatchIterator matchIterator = paletteRegExp.globalMatch( styleSheet ); QPalette palette = RiaGuiApplication::instance()->palette(); while ( matchIterator.hasNext() ) { QRegularExpressionMatch match = matchIterator.next(); QPalette::ColorGroup colorGroup = QPalette::ColorGroup::Active; if ( match.lastCapturedIndex() == 3 ) { colorGroup = colorGroupMap.value( match.captured( 3 ) ); } QColor color = palette.color( colorGroup, colorRoleMap.value( match.captured( 1 ) ) ); styleSheet.replace( match.captured( 0 ), color.name() ); } QRegularExpression variableRegExp( "[ \\t]*(?\\$[a-zA-z0-9_]+)[ \\t]*:[ \\t]*(?[a-zA-Z-_0-9#]+);[ \\t]*(\\/\\/[ " "\\t]*(?(.*)))?[\\n\\r]*" ); matchIterator = variableRegExp.globalMatch( styleSheet ); if ( !s_variableValueMap.keys().contains( theme ) ) { s_variableValueMap.insert( theme, {} ); } else { s_variableValueMap[theme].clear(); } while ( matchIterator.hasNext() ) { QRegularExpressionMatch match = matchIterator.next(); styleSheet.replace( match.captured( 0 ), "" ); QRegularExpression replaceRegExp( "(\\" + match.captured( "name" ) + ")([ ;\\n\\t]+)" ); QRegularExpressionMatchIterator replaceMatchIterator = replaceRegExp.globalMatch( styleSheet ); while ( replaceMatchIterator.hasNext() ) { QRegularExpressionMatch replaceMatch = replaceMatchIterator.next(); if ( s_variableValueMap[theme].keys().contains( match.captured( "name" ) ) ) { styleSheet = styleSheet.left( replaceMatch.capturedStart( 1 ) ) + s_variableValueMap[theme].value( match.captured( "name" ) ) + replaceMatch.captured( 2 ) + styleSheet.right( styleSheet.length() - replaceMatch.capturedEnd( 0 ) ); } else { styleSheet = styleSheet.left( replaceMatch.capturedStart( 0 ) ) + match.captured( "value" ) + replaceMatch.captured( 2 ) + styleSheet.right( styleSheet.length() - replaceMatch.capturedEnd( 0 ) ); } // Positions got updated, we need to reassign the iterator. replaceMatchIterator = replaceRegExp.globalMatch( styleSheet ); } if ( !s_variableValueMap[theme].keys().contains( match.captured( "name" ) ) ) { s_variableValueMap[theme].insert( match.captured( "name" ), match.captured( "value" ) ); s_variableGuiTextMap[theme].insert( match.captured( "name" ), match.captured( "descriptor" ) ); } } QMap::iterator applicatorIterator; for ( applicatorIterator = s_customStyleSheetApplicators.begin(); applicatorIterator != s_customStyleSheetApplicators.end(); applicatorIterator++ ) { matchIterator = QRegularExpression( applicatorIterator.key() ).globalMatch( styleSheet ); while ( matchIterator.hasNext() ) { QRegularExpressionMatch match = matchIterator.next(); applicatorIterator.value()( match ); styleSheet.replace( match.captured( 0 ), "" ); } } styleSheet = styleSheet.simplified(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RiuGuiTheme::getStyleSheetPath( RiaDefines::ThemeEnum theme ) { return QString( ":/themes/%0.qss" ).arg( caf::AppEnum( theme ).text().toLower() ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuGuiTheme::storeQwtStyleSheetProperty( const QString& plotName, const QString& itemType, const QString& itemName, const QString& propertyName, const QString& value ) { if ( !s_qwtPlotItemPropertiesMap.keys().contains( plotName ) ) { s_qwtPlotItemPropertiesMap.insert( plotName, QMap>>{} ); } if ( !s_qwtPlotItemPropertiesMap[plotName].keys().contains( itemType ) ) { s_qwtPlotItemPropertiesMap[plotName].insert( itemType, QMap>{} ); } if ( !s_qwtPlotItemPropertiesMap[plotName][itemType].keys().contains( itemName ) ) { s_qwtPlotItemPropertiesMap[plotName][itemType].insert( itemName, QMap{} ); } s_qwtPlotItemPropertiesMap[plotName][itemType][itemName].insert( propertyName, value ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- Qt::PenStyle RiuGuiTheme::getPenStyleFromString( const QString& style ) { if ( style == "solid" ) { return Qt::PenStyle::SolidLine; } else if ( style == "dash" ) { return Qt::PenStyle::DashLine; } else if ( style == "dot" ) { return Qt::PenStyle::DotLine; } else if ( style == "dash-dot" ) { return Qt::PenStyle::DashDotLine; } else if ( style == "dash-dot-dot" ) { return Qt::PenStyle::DashDotDotLine; } else { return Qt::PenStyle::NoPen; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QwtSymbol* RiuGuiTheme::cloneMarkerSymbol( QwtPlotMarker* marker ) { QwtSymbol* symbol = new QwtSymbol(); symbol->setBrush( marker->symbol()->brush() ); symbol->setPen( marker->symbol()->pen() ); symbol->setStyle( marker->symbol()->style() ); if ( marker->symbol()->style() == QwtSymbol::Style::Pixmap ) { symbol->setPixmap( marker->symbol()->pixmap() ); } else if ( marker->symbol()->style() == QwtSymbol::Style::Graphic ) { symbol->setGraphic( marker->symbol()->graphic() ); } symbol->setSize( marker->symbol()->size() ); symbol->setPinPoint( marker->symbol()->pinPoint() ); return symbol; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QwtSymbol* RiuGuiTheme::cloneCurveSymbol( QwtPlotCurve* curve ) { QwtSymbol* symbol = new QwtSymbol(); symbol->setBrush( curve->symbol()->brush() ); symbol->setPen( curve->symbol()->pen() ); symbol->setStyle( curve->symbol()->style() ); if ( curve->symbol()->style() == QwtSymbol::Style::Pixmap ) { symbol->setPixmap( curve->symbol()->pixmap() ); } else if ( curve->symbol()->style() == QwtSymbol::Style::Graphic ) { symbol->setGraphic( curve->symbol()->graphic() ); } symbol->setSize( curve->symbol()->size() ); symbol->setPinPoint( curve->symbol()->pinPoint() ); return symbol; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuGuiTheme::formatStyleSheetForWriting( QString& styleSheet ) { styleSheet.replace( "\\r", "" ); }