1 /***************************************************************************
2     qgslayerpropertieswidget.cpp
3     ----------------------------
4     begin                : June 2012
5     copyright            : (C) 2012 by Arunmozhi
6     email                : aruntheguy at gmail.com
7  ***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 
16 #include "qgspainteffectpropertieswidget.h"
17 
18 #include <QFile>
19 #include <QStandardItem>
20 #include <QKeyEvent>
21 #include <QMessageBox>
22 
23 #include "qgspainteffectregistry.h"
24 #include "qgspainteffect.h"
25 #include "qgspainteffectwidget.h"
26 #include "qgseffectstack.h"
27 #include "qgsapplication.h"
28 #include "qgslogger.h"
29 
_initWidgetFunction(const QString & name,QgsPaintEffectWidgetFunc f)30 static bool _initWidgetFunction( const QString &name, QgsPaintEffectWidgetFunc f )
31 {
32   QgsPaintEffectRegistry *registry = QgsApplication::paintEffectRegistry();
33 
34   QgsPaintEffectAbstractMetadata *abstractMetadata = registry->effectMetadata( name );
35   if ( !abstractMetadata )
36   {
37     QgsDebugMsg( QStringLiteral( "Failed to find paint effect entry in registry: %1" ).arg( name ) );
38     return false;
39   }
40   QgsPaintEffectMetadata *metadata = dynamic_cast<QgsPaintEffectMetadata *>( abstractMetadata );
41   if ( !metadata )
42   {
43     QgsDebugMsg( QStringLiteral( "Failed to cast paint effect's metadata: " ) .arg( name ) );
44     return false;
45   }
46   metadata->setWidgetFunction( f );
47   return true;
48 }
49 
_initWidgetFunctions()50 static void _initWidgetFunctions()
51 {
52   static bool sInitialized = false;
53   if ( sInitialized )
54     return;
55 
56   _initWidgetFunction( QStringLiteral( "blur" ), QgsBlurWidget::create );
57   _initWidgetFunction( QStringLiteral( "dropShadow" ), QgsShadowEffectWidget::create );
58   _initWidgetFunction( QStringLiteral( "innerShadow" ), QgsShadowEffectWidget::create );
59   _initWidgetFunction( QStringLiteral( "drawSource" ), QgsDrawSourceWidget::create );
60   _initWidgetFunction( QStringLiteral( "outerGlow" ), QgsGlowWidget::create );
61   _initWidgetFunction( QStringLiteral( "innerGlow" ), QgsGlowWidget::create );
62   _initWidgetFunction( QStringLiteral( "transform" ), QgsTransformWidget::create );
63   _initWidgetFunction( QStringLiteral( "color" ), QgsColorEffectWidget::create );
64 
65   sInitialized = true;
66 }
67 
68 
QgsPaintEffectPropertiesWidget(QgsPaintEffect * effect,QWidget * parent)69 QgsPaintEffectPropertiesWidget::QgsPaintEffectPropertiesWidget( QgsPaintEffect *effect, QWidget *parent )
70   : QWidget( parent )
71   , mEffect( effect )
72 {
73   setupUi( this );
74   _initWidgetFunctions();
75 
76   populateEffectTypes();
77   // update effect type combo box
78   if ( effect )
79   {
80     int idx = mEffectTypeCombo->findData( effect->type() );
81     mEffectTypeCombo->setCurrentIndex( idx );
82   }
83   // set the corresponding widget
84   updateEffectWidget( effect );
85   connect( mEffectTypeCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsPaintEffectPropertiesWidget::effectTypeChanged );
86 }
87 
88 
populateEffectTypes()89 void QgsPaintEffectPropertiesWidget::populateEffectTypes()
90 {
91   QgsPaintEffectRegistry *registry = QgsApplication::paintEffectRegistry();
92   QStringList types = registry->effects();
93 
94   const auto constTypes = types;
95   for ( const QString &type : constTypes )
96   {
97     //don't show stack effect
98     if ( type == QLatin1String( "effectStack" ) )
99       continue;
100 
101     mEffectTypeCombo->addItem( registry->effectMetadata( type )->visibleName(), type );
102   }
103 }
104 
updateEffectWidget(QgsPaintEffect * effect)105 void QgsPaintEffectPropertiesWidget::updateEffectWidget( QgsPaintEffect *effect )
106 {
107   if ( !effect )
108   {
109     stackedWidget->setCurrentWidget( pageDummy );
110     return;
111   }
112 
113   if ( stackedWidget->currentWidget() != pageDummy )
114   {
115     // stop updating from the original widget
116     if ( QgsPaintEffectWidget *pew = qobject_cast< QgsPaintEffectWidget * >( stackedWidget->currentWidget() ) )
117       disconnect( pew, &QgsPaintEffectWidget::changed, this, &QgsPaintEffectPropertiesWidget::emitSignalChanged );
118     stackedWidget->removeWidget( stackedWidget->currentWidget() );
119   }
120 
121   QgsPaintEffectRegistry *registry = QgsApplication::paintEffectRegistry();
122   QgsPaintEffectAbstractMetadata *am = registry->effectMetadata( effect->type() );
123   if ( am )
124   {
125     QgsPaintEffectWidget *w = am->createWidget();
126     if ( w )
127     {
128       w->setPaintEffect( effect );
129       stackedWidget->addWidget( w );
130       stackedWidget->setCurrentWidget( w );
131       // start receiving updates from widget
132       connect( w, &QgsPaintEffectWidget::changed, this, &QgsPaintEffectPropertiesWidget::emitSignalChanged );
133       return;
134     }
135   }
136   // When anything is not right
137   stackedWidget->setCurrentWidget( pageDummy );
138 }
139 
effectTypeChanged()140 void QgsPaintEffectPropertiesWidget::effectTypeChanged()
141 {
142   QgsPaintEffect *effect = mEffect;
143   if ( !effect )
144     return;
145 
146   QString newEffectType = mEffectTypeCombo->currentData().toString();
147   if ( effect->type() == newEffectType )
148     return;
149 
150   // get creation function for new effect from registry
151   QgsPaintEffectRegistry *registry = QgsApplication::paintEffectRegistry();
152   QgsPaintEffectAbstractMetadata *am = registry->effectMetadata( newEffectType );
153   if ( !am ) // check whether the metadata is assigned
154     return;
155 
156   // change effect to a new (with different type)
157   // base new effect on existing effect's properties
158   QgsPaintEffect *newEffect = am->createPaintEffect( effect->properties() );
159   if ( !newEffect )
160     return;
161 
162   updateEffectWidget( newEffect );
163   emit changeEffect( newEffect );
164 
165   mEffect = newEffect;
166 }
167 
emitSignalChanged()168 void QgsPaintEffectPropertiesWidget::emitSignalChanged()
169 {
170   emit changed();
171 }
172