QGIS API Documentation 4.1.0-Master (3b8ef1f72a3)
Loading...
Searching...
No Matches
qgsmaterialwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaterialwidget.h
3 --------------------------------------
4 Date : July 2020
5 Copyright : (C) 2020 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot 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 "qgsmaterialwidget.h"
17
19#include "qgsapplication.h"
20#include "qgsgui.h"
21#include "qgsmaterialregistry.h"
24#include "qgsreadwritecontext.h"
25#include "qgsvectorlayer.h"
26
27#include <QDialogButtonBox>
28#include <QString>
29
30#include "moc_qgsmaterialwidget.cpp"
31
32using namespace Qt::StringLiterals;
33
34//
35// QgsMaterialWidget
36//
37
39 : QgsPanelWidget( parent )
40{
41 setupUi( this );
42
43 const QStringList materialTypes = QgsApplication::materialRegistry()->materialSettingsTypes();
44 for ( const QString &type : materialTypes )
45 {
46 if ( type == "null"_L1 )
47 continue;
48
49 mMaterialTypeComboBox->addItem( QgsApplication::materialRegistry()->materialSettingsMetadata( type )->icon(), QgsApplication::materialRegistry()->materialSettingsMetadata( type )->visibleName(), type );
50 }
51
52 mMaterialTypeComboBox->setCurrentIndex( -1 );
53 connect( mMaterialTypeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsMaterialWidget::materialTypeChanged );
54 materialTypeChanged();
55
56 setSettings( new QgsPhongMaterialSettings(), nullptr );
57}
58
60
62{
63 mTechnique = technique;
64 rebuildAvailableTypes();
65}
66
67void QgsMaterialWidget::rebuildAvailableTypes()
68{
69 const QString prevType = mMaterialTypeComboBox->currentData().toString();
70 mMaterialTypeComboBox->blockSignals( true );
71 mMaterialTypeComboBox->clear();
72
73 const QStringList materialTypes = QgsApplication::materialRegistry()->materialSettingsTypes();
74 for ( const QString &type : materialTypes )
75 {
76 if ( mFilterByTechnique && !QgsApplication::materialRegistry()->materialSettingsMetadata( type )->supportsTechnique( mTechnique ) )
77 continue;
78
79 else if ( type == "null"_L1 && !mFilterByTechnique )
80 continue; // don't expose null as an option if we're showing in a generic mode
81
82 mMaterialTypeComboBox->addItem( QgsApplication::materialRegistry()->materialSettingsMetadata( type )->icon(), QgsApplication::materialRegistry()->materialSettingsMetadata( type )->visibleName(), type );
83 }
84
85 const int prevIndex = mMaterialTypeComboBox->findData( prevType );
86 if ( prevIndex == -1 )
87 {
88 // if phong material type is available, default to it (for now?)
89 const int phongIndex = mMaterialTypeComboBox->findData( u"phong"_s );
90 if ( phongIndex >= 0 )
91 mMaterialTypeComboBox->setCurrentIndex( phongIndex );
92 else
93 mMaterialTypeComboBox->setCurrentIndex( 0 );
94 }
95 else
96 mMaterialTypeComboBox->setCurrentIndex( prevIndex );
97
98 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
99 {
100 w->setTechnique( mTechnique );
101 }
102
103 mMaterialTypeComboBox->blockSignals( false );
104 materialTypeChanged();
105}
106
108{
109 mFilterByTechnique = enabled;
110 rebuildAvailableTypes();
111}
112
114{
115 mMaterialTypeComboBox->setCurrentIndex( mMaterialTypeComboBox->findData( settings->type() ) );
116 mCurrentSettings.reset( settings->clone() );
117 mLayer = layer;
118 updateMaterialWidget();
119}
120
121std::unique_ptr< QgsAbstractMaterialSettings > QgsMaterialWidget::settings()
122{
123 return mCurrentSettings ? std::unique_ptr< QgsAbstractMaterialSettings >( mCurrentSettings->clone() ) : nullptr;
124}
125
126void QgsMaterialWidget::setType( const QString &type )
127{
128 mMaterialTypeComboBox->setCurrentIndex( mMaterialTypeComboBox->findData( type ) );
129 materialTypeChanged();
130}
131
133{
134 mPreviewVisible = visible;
135 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
136 {
137 w->setPreviewVisible( visible );
138 }
139}
140
141void QgsMaterialWidget::materialTypeChanged()
142{
143 std::unique_ptr<QgsAbstractMaterialSettings> currentSettings( settings() );
144 const QString existingType = currentSettings ? currentSettings->type() : QString();
145 const QString newType = mMaterialTypeComboBox->currentData().toString();
146 if ( existingType == newType )
147 return;
148
149 if ( QgsMaterialSettingsAbstractMetadata *am = QgsApplication::materialRegistry()->materialSettingsMetadata( newType ) )
150 {
151 // change material to a new (with different type)
152 // base new layer on existing materials's properties
153 std::unique_ptr<QgsAbstractMaterialSettings> newMaterial( am->create() );
154 if ( newMaterial )
155 {
156 if ( currentSettings )
157 {
158 QDomDocument doc;
159 QDomElement tempElem = doc.createElement( u"temp"_s );
160 currentSettings->writeXml( tempElem, QgsReadWriteContext() );
161 newMaterial->readXml( tempElem, QgsReadWriteContext() );
162 }
163
164 mCurrentSettings = std::move( newMaterial );
165 updateMaterialWidget();
166 emit changed();
167 }
168 }
169}
170
171void QgsMaterialWidget::materialWidgetChanged()
172{
173 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
174 {
175 mCurrentSettings = w->settings();
176 }
177 emit changed();
178}
179
180void QgsMaterialWidget::updateMaterialWidget()
181{
182 if ( mStackedWidget->currentWidget() != mPageDummy )
183 {
184 // stop updating from the original widget
185 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
186 disconnect( w, &QgsMaterialSettingsWidget::changed, this, &QgsMaterialWidget::materialWidgetChanged );
187 mStackedWidget->removeWidget( mStackedWidget->currentWidget() );
188 }
189
190 const QString settingsType = mCurrentSettings->type();
191 if ( QgsMaterialSettingsAbstractMetadata *am = QgsApplication::materialRegistry()->materialSettingsMetadata( settingsType ) )
192 {
193 if ( QgsMaterialSettingsWidget *w = am->createWidget() )
194 {
195 w->setSettings( mCurrentSettings.get(), mLayer );
196 w->setTechnique( mTechnique );
197 w->setPreviewVisible( mPreviewVisible );
198 mStackedWidget->addWidget( w );
199 mStackedWidget->setCurrentWidget( w );
200 // start receiving updates from widget
201 connect( w, &QgsMaterialSettingsWidget::changed, this, &QgsMaterialWidget::materialWidgetChanged );
202 return;
203 }
204 }
205 // When anything is not right
206 mStackedWidget->setCurrentWidget( mPageDummy );
207}
208
209
210//
211// QgsMaterialWidgetDialog
212//
213
215 : QDialog( parent )
216{
218
219 QVBoxLayout *vLayout = new QVBoxLayout();
220 mWidget = new QgsMaterialWidget();
221 mWidget->setPreviewVisible( true );
222 vLayout->addWidget( mWidget, 1 );
223
224 if ( settings )
225 {
226 mWidget->setSettings( settings, nullptr );
227 }
228
229 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Ok, Qt::Horizontal );
230 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
231 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
232 vLayout->addWidget( mButtonBox );
233 setLayout( vLayout );
234 setWindowTitle( tr( "Material" ) );
235
236 connect( mWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
237}
238
239std::unique_ptr<QgsAbstractMaterialSettings> QgsMaterialWidgetDialog::settings()
240{
241 return mWidget->settings();
242}
243
245{
246 return mButtonBox;
247}
MaterialRenderingTechnique
Material rendering techniques.
Definition qgis.h:4327
Abstract base class for material settings.
static QgsMaterialRegistry * materialRegistry()
Returns registry of available 3D materials.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition qgsgui.cpp:224
QStringList materialSettingsTypes() const
Returns a list of all available material settings types.
Stores metadata about one 3D material settings class.
Base class for 3D material settings widgets.
void changed()
Emitted when the material definition is changed.
std::unique_ptr< QgsAbstractMaterialSettings > settings()
Returns the current settings defined by the dialog.
QDialogButtonBox * buttonBox()
Returns the dialog's button box.
QgsMaterialWidgetDialog(const QgsAbstractMaterialSettings *settings, QWidget *parent=nullptr)
Constructor for QgsMaterialWidgetDialog, initially showing the specified material settings.
A widget allowing users to customize a 3d material.
QgsMaterialWidget(QWidget *parent=nullptr)
Constructor for QgsMaterialWidget.
void changed()
Emitted when the material defined by the widget is changed.
std::unique_ptr< QgsAbstractMaterialSettings > settings()
Returns the current settings defined by the widget.
void setSettings(const QgsAbstractMaterialSettings *settings, QgsVectorLayer *layer)
Sets the widget state to match material settings.
void setType(const QString &type)
Sets the current material type.
void setFilterByTechnique(bool enabled)
Sets whether available materials should be filtered by technique.
void setTechnique(Qgis::MaterialRenderingTechnique technique)
Sets the required rendering technique which the material must support.
Qgis::MaterialRenderingTechnique technique() const
Returns the required rendering technique which the material must support.
~QgsMaterialWidget() override
void setPreviewVisible(bool visible)
Sets whether the material preview widget should be visible.
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
QgsPanelWidget(QWidget *parent=nullptr)
Base class for any widget that can be shown as an inline panel.
Basic shading material used for rendering based on the Phong shading model with three color component...
A container for the context for various read/write operations on objects.
Represents a vector layer which manages a vector based dataset.