Implement stylesheets in caf instead of ResInsight

This commit is contained in:
Gaute Lindkvist 2019-11-11 11:19:55 +01:00
parent 285433cbb8
commit 7a2a0d3f2f
13 changed files with 396 additions and 342 deletions

View File

@ -86,7 +86,6 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.h
${CMAKE_CURRENT_LIST_DIR}/RiuMdiMaximizeWindowGuard.h
${CMAKE_CURRENT_LIST_DIR}/RiuMainWindowTools.h
${CMAKE_CURRENT_LIST_DIR}/RiuComparisonViewMover.h
${CMAKE_CURRENT_LIST_DIR}/RiuWidgetStyleSheet.h
)
set (SOURCE_GROUP_SOURCE_FILES
@ -172,7 +171,6 @@ ${CMAKE_CURRENT_LIST_DIR}/RiuDraggableOverlayFrame.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuMdiMaximizeWindowGuard.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuMainWindowTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuComparisonViewMover.cpp
${CMAKE_CURRENT_LIST_DIR}/RiuWidgetStyleSheet.cpp
)
list(APPEND CODE_HEADER_FILES

View File

@ -680,6 +680,7 @@ void RiuMainWindow::createDockPanels()
m_projectTreeView = new caf::PdmUiTreeView( this );
m_projectTreeView->enableSelectionManagerUpdating( true );
m_styleSheet.applyToWidgetAndChildren( m_projectTreeView );
RiaApplication* app = RiaApplication::instance();
m_projectTreeView->enableAppendOfClassNameToUiItemText( app->preferences()->appendClassNameToUiText() );

View File

@ -46,6 +46,7 @@ RiuMainWindowBase::RiuMainWindowBase()
, m_blockSubWindowProjectTreeSelection( false )
{
setDockNestingEnabled( true );
m_styleSheet = createStyleSheet();
}
//--------------------------------------------------------------------------------------------------
@ -313,6 +314,17 @@ void RiuMainWindowBase::removeViewerFromMdiArea( QMdiArea* mdiArea, QWidget* vie
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::UiStyleSheet RiuMainWindowBase::createStyleSheet()
{
caf::UiStyleSheet styleSheet;
styleSheet.set( "background-color", QColor( Qt::lightGray ).name() );
styleSheet.set( "border", "1px dashed black" );
return styleSheet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -18,6 +18,8 @@
#pragma once
#include "cafUiStyleSheet.h"
#include <QMainWindow>
class QMdiArea;
@ -83,7 +85,8 @@ public:
bool isBlockingViewSelectionOnSubWindowActivated() const;
protected:
void removeViewerFromMdiArea( QMdiArea* mdiArea, QWidget* viewer );
void removeViewerFromMdiArea( QMdiArea* mdiArea, QWidget* viewer );
caf::UiStyleSheet createStyleSheet();
protected slots:
void slotDockWidgetToggleViewActionTriggered();
@ -91,6 +94,7 @@ protected slots:
protected:
caf::PdmUiTreeView* m_projectTreeView;
caf::UiStyleSheet m_styleSheet;
bool m_allowActiveViewChangeFromSelection; // To be used in selectedObjectsChanged() to control
// whether to select the corresponding active view or not
private:

View File

@ -225,11 +225,11 @@ void RiuMultiPlotWindow::setSelectionsVisible( bool visible )
{
if ( visible && caf::SelectionManager::instance()->isSelected( plotWidget->plotDefinition(), 0 ) )
{
plotWidget->setWidgetState( RiuWidgetStyleSheet::SELECTED );
plotWidget->setWidgetState( "selected" );
}
else
{
plotWidget->setWidgetState( RiuWidgetStyleSheet::DEFAULT );
caf::UiStyleSheet::clearWidgetStates( plotWidget );
}
}
}
@ -361,7 +361,7 @@ void RiuMultiPlotWindow::dragEnterEvent( QDragEnterEvent* event )
RiuQwtPlotWidget* source = dynamic_cast<RiuQwtPlotWidget*>( event->source() );
if ( source )
{
setWidgetState( RiuWidgetStyleSheet::DRAG_TARGET_INTO );
setWidgetState( "dragTargetInto" );
event->acceptProposedAction();
}
}
@ -376,7 +376,7 @@ void RiuMultiPlotWindow::dragMoveEvent( QDragMoveEvent* event )
RiuQwtPlotWidget* source = dynamic_cast<RiuQwtPlotWidget*>( event->source() );
if ( source && willAcceptDroppedPlot( source ) )
{
setWidgetState( RiuWidgetStyleSheet::DRAG_TARGET_INTO );
setWidgetState( "dragTargetInto" );
QRect originalGeometry = source->geometry();
QPoint offset = source->dragStartPosition();
@ -387,7 +387,7 @@ void RiuMultiPlotWindow::dragMoveEvent( QDragMoveEvent* event )
int insertBeforeIndex = visiblePlotWidgets.size();
for ( int visibleIndex = 0; visibleIndex < visiblePlotWidgets.size(); ++visibleIndex )
{
visiblePlotWidgets[visibleIndex]->setWidgetState( RiuWidgetStyleSheet::DEFAULT );
caf::UiStyleSheet::clearWidgetStates( visiblePlotWidgets[visibleIndex] );
if ( visiblePlotWidgets[visibleIndex]->frameIsInFrontOfThis( newRect ) )
{
@ -396,13 +396,13 @@ void RiuMultiPlotWindow::dragMoveEvent( QDragMoveEvent* event )
}
if ( insertBeforeIndex >= 0 && insertBeforeIndex < visiblePlotWidgets.size() )
{
visiblePlotWidgets[insertBeforeIndex]->setWidgetState( RiuWidgetStyleSheet::DRAG_TARGET_BEFORE );
visiblePlotWidgets[insertBeforeIndex]->setWidgetState( "dragTargetBefore" );
}
if ( insertBeforeIndex > 0 )
{
int insertAfterIndex = insertBeforeIndex - 1;
visiblePlotWidgets[insertAfterIndex]->setWidgetState( RiuWidgetStyleSheet::DRAG_TARGET_AFTER );
visiblePlotWidgets[insertAfterIndex]->setWidgetState( "dragTargetAfter" );
}
event->acceptProposedAction();
}
@ -414,11 +414,11 @@ void RiuMultiPlotWindow::dragMoveEvent( QDragMoveEvent* event )
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::dragLeaveEvent( QDragLeaveEvent* event )
{
setWidgetState( RiuWidgetStyleSheet::DEFAULT );
caf::UiStyleSheet::clearWidgetStates( this );
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
m_plotWidgets[tIdx]->setWidgetState( RiuWidgetStyleSheet::DEFAULT );
caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] );
}
}
@ -427,11 +427,11 @@ void RiuMultiPlotWindow::dragLeaveEvent( QDragLeaveEvent* event )
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::dropEvent( QDropEvent* event )
{
setWidgetState( RiuWidgetStyleSheet::DEFAULT );
caf::UiStyleSheet::clearWidgetStates( this );
for ( int tIdx = 0; tIdx < m_plotWidgets.size(); ++tIdx )
{
m_plotWidgets[tIdx]->setWidgetState( RiuWidgetStyleSheet::DEFAULT );
caf::UiStyleSheet::clearWidgetStates( m_plotWidgets[tIdx] );
}
if ( this->geometry().contains( event->pos() ) )
@ -468,7 +468,7 @@ void RiuMultiPlotWindow::dropEvent( QDropEvent* event )
if ( insertAfter != plotToMove )
{
m_plotDefinition->movePlotsToThis( {plotToMove}, insertAfter );
m_plotDefinition->movePlotsToThis( { plotToMove }, insertAfter );
}
}
}
@ -514,11 +514,11 @@ void RiuMultiPlotWindow::onSelectionManagerSelectionChanged( const std::set<int>
}
if ( isSelected )
{
plotWidget->setWidgetState( RiuWidgetStyleSheet::SELECTED );
plotWidget->setWidgetState( "selected" );
}
else
{
plotWidget->setWidgetState( RiuWidgetStyleSheet::DEFAULT );
caf::UiStyleSheet::clearWidgetStates( plotWidget );
}
}
}
@ -526,7 +526,7 @@ void RiuMultiPlotWindow::onSelectionManagerSelectionChanged( const std::set<int>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuMultiPlotWindow::setWidgetState( RiuWidgetStyleSheet::StateTag widgetState )
void RiuMultiPlotWindow::setWidgetState( const QString& widgetState )
{
m_dropTargetStyleSheet.setWidgetState( m_dropTargetPlaceHolder, widgetState );
}
@ -692,15 +692,15 @@ void RiuMultiPlotWindow::clearGridLayout()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuWidgetStyleSheet RiuMultiPlotWindow::createDropTargetStyleSheet()
caf::UiStyleSheet RiuMultiPlotWindow::createDropTargetStyleSheet()
{
RiuWidgetStyleSheet styleSheet;
caf::UiStyleSheet styleSheet;
styleSheet.set( "background-color", "white" );
styleSheet.set( "border", "1px dashed black" );
styleSheet.set( "font-size", "14pt" );
styleSheet.state( RiuWidgetStyleSheet::DRAG_TARGET_INTO ).set( "border", "1px dashed lime" );
styleSheet.state( RiuWidgetStyleSheet::DRAG_TARGET_INTO ).set( "background-color", "#DDFFDD" );
styleSheet.property( "dragTargetInto" ).set( "border", "1px dashed lime" );
styleSheet.property( "dragTargetInto" ).set( "background-color", "#DDFFDD" );
return styleSheet;
}

View File

@ -20,7 +20,7 @@
#pragma once
#include "RiuInterfaceToViewWindow.h"
#include "RiuWidgetStyleSheet.h"
#include "cafUiStyleSheet.h"
#include "cafPdmPointer.h"
#include "cafSelectionChangedReceiver.h"
@ -93,15 +93,15 @@ protected:
virtual void onSelectionManagerSelectionChanged( const std::set<int>& changedSelectionLevels ) override;
void setWidgetState( RiuWidgetStyleSheet::StateTag widgetState );
void setWidgetState( const QString& widgetState );
virtual bool showYAxis( int row, int column ) const;
void reinsertPlotWidgets();
int alignCanvasTops();
void clearGridLayout();
RiuWidgetStyleSheet createDropTargetStyleSheet();
void clearGridLayout();
caf::UiStyleSheet createDropTargetStyleSheet();
QList<QPointer<RiuQwtPlotWidget>> visiblePlotWidgets() const;
QList<QPointer<RiuQwtPlotLegend>> visibleLegends() const;
@ -125,7 +125,7 @@ protected:
caf::PdmPointer<RimMultiPlotWindow> m_plotDefinition;
QPointer<QLabel> m_dropTargetPlaceHolder;
RiuWidgetStyleSheet m_dropTargetStyleSheet;
caf::UiStyleSheet m_dropTargetStyleSheet;
private:
friend class RiaPlotWindowRedrawScheduler;

View File

@ -422,8 +422,9 @@ void RiuQwtPlotWidget::scheduleReplot()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::setWidgetState( RiuWidgetStyleSheet::StateTag widgetState )
void RiuQwtPlotWidget::setWidgetState( const QString& widgetState )
{
caf::UiStyleSheet::clearWidgetStates( this );
m_plotStyleSheet.setWidgetState( this, widgetState );
}
@ -608,18 +609,18 @@ void RiuQwtPlotWidget::onAxisSelected( QwtScaleWidget* scale, bool toggleItemInS
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuWidgetStyleSheet RiuQwtPlotWidget::createPlotStyleSheet() const
caf::UiStyleSheet RiuQwtPlotWidget::createPlotStyleSheet() const
{
QColor backgroundColor = QColor( "white" );
QColor highlightColor = QApplication::palette().highlight().color();
QColor blendedHighlightColor = RiaColorTools::blendQColors( highlightColor, backgroundColor, 1, 20 );
QColor nearlyBackgroundColor = RiaColorTools::blendQColors( highlightColor, backgroundColor, 1, 40 );
RiuWidgetStyleSheet styleSheet;
caf::UiStyleSheet styleSheet;
styleSheet.set( "background-color", backgroundColor.name() );
styleSheet.set( "border", "1 px solid transparent" );
styleSheet.state( RiuWidgetStyleSheet::SELECTED ).set( "border", QString( "1px solid %1" ).arg( highlightColor.name() ) );
styleSheet.property( "selected" ).set( "border", QString( "1px solid %1" ).arg( highlightColor.name() ) );
if ( m_draggable )
{
@ -629,21 +630,20 @@ RiuWidgetStyleSheet RiuQwtPlotWidget::createPlotStyleSheet() const
.arg( nearlyBackgroundColor.name() )
.arg( backgroundColor.name() ) );
styleSheet.state( RiuWidgetStyleSheet::HOVER ).set( "background", backgroundGradient );
styleSheet.state( RiuWidgetStyleSheet::HOVER )
.set( "border", QString( "1px dashed %1" ).arg( blendedHighlightColor.name() ) );
styleSheet.pseudoState( "hover" ).set( "background", backgroundGradient );
styleSheet.pseudoState( "hover" ).set( "border", QString( "1px dashed %1" ).arg( blendedHighlightColor.name() ) );
}
styleSheet.state( RiuWidgetStyleSheet::DRAG_TARGET_BEFORE ).set( "border-left", "1px solid lime" );
styleSheet.state( RiuWidgetStyleSheet::DRAG_TARGET_AFTER ).set( "border-right", "1px solid lime" );
styleSheet.property( "dropTargetBefore" ).set( "border-left", "1px solid lime" );
styleSheet.property( "dropTargetAfter" ).set( "border-right", "1px solid lime" );
return styleSheet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuWidgetStyleSheet RiuQwtPlotWidget::createCanvasStyleSheet() const
caf::UiStyleSheet RiuQwtPlotWidget::createCanvasStyleSheet() const
{
RiuWidgetStyleSheet styleSheet;
caf::UiStyleSheet styleSheet;
styleSheet.set( "background-color", "#FAFAFA" );
styleSheet.set( "border", "1px solid LightGray" );
return styleSheet;
@ -654,7 +654,7 @@ RiuWidgetStyleSheet RiuQwtPlotWidget::createCanvasStyleSheet() const
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::setDefaults()
{
setEnabledAxes( {QwtPlot::xTop, QwtPlot::yLeft} );
setEnabledAxes( { QwtPlot::xTop, QwtPlot::yLeft } );
RiuQwtPlotTools::setCommonPlotBehaviour( this );
}
@ -796,7 +796,7 @@ void RiuQwtPlotWidget::highlightCurve( const QwtPlotCurve* closestCurve )
symbol->setPen( blendedSymbolLineColor, symbol->pen().width(), symbol->pen().style() );
}
}
CurveColors curveColors = {curveColor, symbolColor, symbolLineColor};
CurveColors curveColors = { curveColor, symbolColor, symbolLineColor };
m_originalCurveColors.insert( std::make_pair( plotCurve, curveColors ) );
m_originalCurveColors.insert( std::make_pair( plotCurve, curveColors ) );
m_originalZValues.insert( std::make_pair( plotCurve, zValue ) );

View File

@ -19,7 +19,7 @@
#pragma once
#include "RiuWidgetStyleSheet.h"
#include "cafUiStyleSheet.h"
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
@ -98,7 +98,7 @@ public:
QPoint dragStartPosition() const;
void scheduleReplot();
void setWidgetState( RiuWidgetStyleSheet::StateTag widgetState );
void setWidgetState( const QString& widgetState );
protected:
QSize sizeHint() const override;
@ -125,8 +125,8 @@ private:
void resetCurveHighlighting();
void onAxisSelected( QwtScaleWidget* scale, bool toggleItemInSelection );
RiuWidgetStyleSheet createPlotStyleSheet() const;
RiuWidgetStyleSheet createCanvasStyleSheet() const;
caf::UiStyleSheet createPlotStyleSheet() const;
caf::UiStyleSheet createCanvasStyleSheet() const;
private:
caf::PdmPointer<RimPlot> m_plotDefinition;
@ -146,8 +146,8 @@ private:
std::map<QwtPlotCurve*, CurveColors> m_originalCurveColors;
std::map<QwtPlotCurve*, double> m_originalZValues;
RiuWidgetStyleSheet m_plotStyleSheet;
RiuWidgetStyleSheet m_canvasStyleSheet;
caf::UiStyleSheet m_plotStyleSheet;
caf::UiStyleSheet m_canvasStyleSheet;
friend class RiaPlotWindowRedrawScheduler;
};

View File

@ -1,207 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiuWidgetStyleSheet.h"
#include "cafAssert.h"
#include <QDebug>
#include <QStringList>
#include <QStyle>
#include <QWidget>
namespace caf
{
template <>
void RiuWidgetStyleSheet::StateTagEnum::setUp()
{
addItem( RiuWidgetStyleSheet::DEFAULT, "", "" );
addItem( RiuWidgetStyleSheet::SELECTED, "selected", "selected" );
addItem( RiuWidgetStyleSheet::DRAG_TARGET_BEFORE, "dragTargetBefore", "drop before" );
addItem( RiuWidgetStyleSheet::DRAG_TARGET_AFTER, "dragTargetAfter", "drop after" );
addItem( RiuWidgetStyleSheet::DRAG_TARGET_INTO, "dragTargetInto", "drop into" );
addItem( RiuWidgetStyleSheet::HOVER, "hover", "hover" );
setDefault( RiuWidgetStyleSheet::DEFAULT );
}
} // namespace caf
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuWidgetStyleSheet::State::State( const QString& stateString )
: m_stateString( stateString )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuWidgetStyleSheet::State::set( const QString& key, const QString& value )
{
m_content[key] = value;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiuWidgetStyleSheet::State::get( const QString& key ) const
{
auto it = m_content.find( key );
return it != m_content.end() ? it->second : "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiuWidgetStyleSheet::State::fullText( const QString& className, const QString& objectName ) const
{
QString styleContent;
for ( auto keyValuePair : m_content )
{
styleContent += QString( " %1: %2;\n" ).arg( keyValuePair.first ).arg( keyValuePair.second );
}
QString objectNameTag = !objectName.isEmpty() ? QString( "#%1" ).arg( objectName ) : "";
QString fullStyleSheet =
QString( "%1%2%3\n{\n%4}" ).arg( className ).arg( objectNameTag ).arg( m_stateString ).arg( styleContent );
return fullStyleSheet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RiuWidgetStyleSheet::RiuWidgetStyleSheet()
{
// Add the default state
m_states.insert( std::make_pair( DEFAULT, State( "" ) ) );
}
//--------------------------------------------------------------------------------------------------
/// Set keys and values directly to the default state
//--------------------------------------------------------------------------------------------------
void RiuWidgetStyleSheet::set( const QString& key, const QString& value )
{
state( DEFAULT ).set( key, value );
}
//--------------------------------------------------------------------------------------------------
/// Get values directly from the default state
//--------------------------------------------------------------------------------------------------
QString RiuWidgetStyleSheet::get( const QString& key ) const
{
auto it = m_states.find( DEFAULT );
return it != m_states.end() ? it->second.get( key ) : "";
}
//--------------------------------------------------------------------------------------------------
/// Access a particular state in the stylesheet
//--------------------------------------------------------------------------------------------------
RiuWidgetStyleSheet::State& RiuWidgetStyleSheet::state( StateTag stateTag )
{
auto itBoolPair = m_states.insert( std::make_pair( stateTag, State( buildStateString( stateTag ) ) ) );
auto it = itBoolPair.first;
return it->second;
}
//--------------------------------------------------------------------------------------------------
/// Apply the current stylesheet to the provided widget instance
//--------------------------------------------------------------------------------------------------
void RiuWidgetStyleSheet::applyToWidget( QWidget* widget ) const
{
CAF_ASSERT( !widget->objectName().isEmpty() &&
"The widget is required to have an object name set with setObjectName" );
QString completeStyleSheet = fullText( QString( widget->metaObject()->className() ), widget->objectName() );
// qDebug().noquote() << completeStyleSheet;
widget->setStyleSheet( completeStyleSheet );
refreshWidget( widget );
}
//--------------------------------------------------------------------------------------------------
/// Put the provided widget into the provided state
//--------------------------------------------------------------------------------------------------
void RiuWidgetStyleSheet::setWidgetState( QWidget* widget, StateTag widgetState ) const
{
// Set all existing dynamic properties to false
for ( QByteArray existingProperty : widget->dynamicPropertyNames() )
{
widget->setProperty( existingProperty, false );
}
// Set current property state to true
QString propertyName = RiuWidgetStyleSheet::propertyName( widgetState );
if ( !propertyName.isEmpty() )
{
widget->setProperty( propertyName.toLatin1(), true );
}
// Trigger style update
this->refreshWidget( widget );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiuWidgetStyleSheet::fullText( const QString& className, const QString& objectName ) const
{
QStringList textForAllStates;
for ( auto it = m_states.begin(); it != m_states.end(); ++it )
{
textForAllStates.push_back( it->second.fullText( className, objectName ) );
}
return textForAllStates.join( "\n" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiuWidgetStyleSheet::refreshWidget( QWidget* widget ) const
{
widget->style()->unpolish( widget );
widget->style()->polish( widget );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiuWidgetStyleSheet::buildStateString( StateTag state )
{
QString stateString;
if ( state >= PSEUDO_STATE_LIMIT )
{
stateString += ":" + StateTagEnum::uiText( state );
}
else
{
stateString += QString( "[%1=true]" ).arg( propertyName( state ) );
}
return stateString;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString RiuWidgetStyleSheet::propertyName( StateTag state )
{
if ( state < PSEUDO_STATE_LIMIT )
{
return StateTagEnum::text( state );
}
return "";
}

View File

@ -1,89 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2019- 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 <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "cafAppEnum.h"
#include <QString>
#include <map>
class RiuWidgetStyleSheetManager;
class QWidget;
//==================================================================================================
// ResInsight widget class. Meant to create and apply style sheets to particular widget instances.
// without "bleeding" the look into other widgets.
//==================================================================================================
class RiuWidgetStyleSheet
{
public:
enum StateTag
{
DEFAULT = 0x0000,
// Dynamic Properties (Applied to a widget using setWidgetState())
SELECTED = 0x0001,
DRAG_TARGET_BEFORE = 0x0002,
DRAG_TARGET_AFTER = 0x0004,
DRAG_TARGET_INTO = 0x0008,
// Pseudo States (Qt sets the widget into these states automatically)
// And we have no way of forcing the widget to be in this state.
// However we can define the look when the widget is in the state
PSEUDO_STATE_LIMIT = 0x1000,
HOVER = 0x1000
};
typedef caf::AppEnum<StateTag> StateTagEnum;
class State
{
public:
State( const QString& stateString );
void set( const QString& key, const QString& value );
QString get( const QString& key ) const;
private:
friend class RiuWidgetStyleSheet;
QString fullText( const QString& className, const QString& objectName ) const;
private:
QString m_stateString;
std::map<QString, QString> m_content;
};
public:
RiuWidgetStyleSheet();
void set( const QString& key, const QString& value );
QString get( const QString& key ) const;
State& state( StateTag stateTag );
void applyToWidget( QWidget* widget ) const;
void setWidgetState( QWidget* widget, StateTag widgetState ) const;
private:
friend class RiuWidgetStyleSheetManager;
QString fullText( const QString& className, const QString& objectName ) const;
void refreshWidget( QWidget* widget ) const;
static QString buildStateString( StateTag stateTag );
static QString propertyName( StateTag stateTag );
private:
std::map<StateTag, State> m_states;
};

View File

@ -163,6 +163,8 @@ set( PROJECT_FILES
cafStyleSheetTools.cpp
cafPdmUiTabbedPropertyViewDialog.h
cafPdmUiTabbedPropertyViewDialog.cpp
cafUiStyleSheet.h
cafUiStyleSheet.cpp
)
add_library( ${PROJECT_NAME}

View File

@ -0,0 +1,236 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2019- Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// This library 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.
//
// This library 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 <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafUiStylesheet.h"
#include <QStringList>
#include <QStyle>
#include <QVariant>
#include <QWidget>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::UiStyleSheet::State::State(const QString& stateTag, Type type)
: m_type(type)
{
if (type == PseudoState)
{
if (!stateTag.isEmpty())
{
m_stateTag = ":" + stateTag;
}
}
else
{
m_stateTag = QString("[%1=true]").arg(stateTag);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::UiStyleSheet::State::Type caf::UiStyleSheet::State::type() const
{
return m_type;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::UiStyleSheet::State::set(const QString& key, const QString& value)
{
m_content[key] = value;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString caf::UiStyleSheet::State::get(const QString& key) const
{
auto it = m_content.find(key);
if (it != m_content.end())
{
return it->second;
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString caf::UiStyleSheet::State::fullText(const QString& className, const QString& objectName, bool applyToSubClasses /*= true*/) const
{
QString classNameTag = applyToSubClasses ? className : QString(".%1").arg(className);
QString objectNameTag = !objectName.isEmpty() ? QString("#%1").arg(objectName) : "";
QStringList content;
for (auto keyValuePair : m_content)
{
content << QString(" %1: %2").arg(keyValuePair.first).arg(keyValuePair.second);
}
QString format("%1%2%3\n{\n%4}");
QString stateStyleSheet = format.arg(classNameTag).arg(objectNameTag).arg(m_stateTag).arg(content.join(";\n"));
return stateStyleSheet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::UiStyleSheet::UiStyleSheet()
{
// Add a default state (blank tag)
m_states.insert(std::make_pair("", State("", State::PseudoState)));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::UiStyleSheet::set(const QString& key, const QString& value)
{
pseudoState("").set(key, value);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString caf::UiStyleSheet::get(const QString& key) const
{
auto it = m_states.find("");
if (it != m_states.end())
{
return it->second.get(key);
}
return "";
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::UiStyleSheet::State& caf::UiStyleSheet::property(QString stateTag)
{
auto itBoolResult = m_states.insert(std::make_pair(stateTag, State(stateTag, State::PropertyState)));
return itBoolResult.first->second;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
caf::UiStyleSheet::State& caf::UiStyleSheet::pseudoState(QString stateTag)
{
auto itBoolResult = m_states.insert(std::make_pair(stateTag, State(stateTag, State::PseudoState)));
return itBoolResult.first->second;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::UiStyleSheet::applyToWidget(QWidget* widget, bool applyToSubClasses /*= true*/) const
{
if (widget->objectName().isEmpty())
{
// If widget has no object name we use the pointer as a name.
widget->setObjectName(QString("%1").arg(reinterpret_cast<std::uintptr_t>(widget)));
}
QString completeStyleSheet = fullText(QString(widget->metaObject()->className()), widget->objectName(), applyToSubClasses);
widget->setStyleSheet(completeStyleSheet);
refreshWidget(widget);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::UiStyleSheet::applyToWidgetAndChildren(QWidget* widget)
{
QString completeStyleSheet = fullText("*", "", false);
widget->setStyleSheet(completeStyleSheet);
refreshWidget(widget);
}
//--------------------------------------------------------------------------------------------------
/// Clear all existing properties
//--------------------------------------------------------------------------------------------------
void caf::UiStyleSheet::clearWidgetStates(QWidget* widget)
{
for (QByteArray existingProperty : widget->dynamicPropertyNames())
{
widget->setProperty(existingProperty, QVariant());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::UiStyleSheet::setWidgetState(QWidget* widget, QString stateTag, bool on /*= true*/) const
{
// Set current property state to true
if (!stateTag.isEmpty())
{
auto it = m_states.find(stateTag);
if (it != m_states.end() && it->second.type() == State::PropertyState)
{
widget->setProperty(stateTag.toLatin1(), QVariant(on));
}
}
// Trigger style update
this->refreshWidget(widget);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString caf::UiStyleSheet::fullText(const QString& className, const QString& objectName, bool applyToSubClasses) const
{
QStringList stateTexts;
for (auto it = m_states.begin(); it != m_states.end(); ++it)
{
stateTexts << it->second.fullText(className, objectName, applyToSubClasses);
}
return stateTexts.join("\n");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::UiStyleSheet::refreshWidget(QWidget* widget) const
{
widget->style()->unpolish(widget);
widget->style()->polish(widget);
}

View File

@ -0,0 +1,97 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2019- Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// This library 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.
//
// This library 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 <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <QString>
#include <map>
class QWidget;
namespace caf
{
//==================================================================================================
// Class used to apply stylesheets to Qt widgets without "bleeding" into other widgets
//==================================================================================================
class UiStyleSheet
{
public:
class State
{
public:
enum Type
{
// Qt Pseudo-states applied automatically by Qt: https://doc.qt.io/qt-5/stylesheet-reference.html
PseudoState,
// State set by property syntax
PropertyState
};
State(const QString& stateTag, Type type);
Type type() const;
void set(const QString& key, const QString& value);
QString get(const QString& key) const;
private:
friend class UiStyleSheet;
QString fullText(const QString& className, const QString& objectName, bool applyToSubClasses) const;
private:
Type m_type;
QString m_stateTag;
std::map<QString, QString> m_content;
};
public:
UiStyleSheet();
void set(const QString& key, const QString& value);
QString get(const QString& key) const;
State& property(QString stateTag);
State& pseudoState(QString stateTag);
void applyToWidget(QWidget* widget, bool applyToSubClasses = true) const;
void applyToWidgetAndChildren(QWidget* widget);
static void clearWidgetStates(QWidget* widget);
void setWidgetState(QWidget* widget, QString stateTag, bool on = true) const;
private:
QString fullText(const QString& className, const QString& objectName, bool applyToSubClasses) const;
void refreshWidget(QWidget* widget) const;
private:
std::map<QString, State> m_states;
};
}