QGIS API Documentation 4.3.0-Master (6a28b93578f)
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
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 metalrough material type is available, default to it
89 const int metalroughIndex = mMaterialTypeComboBox->findData( u"metalrough"_s );
90 if ( metalroughIndex >= 0 )
91 mMaterialTypeComboBox->setCurrentIndex( metalroughIndex );
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 w->setMode( mMode );
102 }
103
104 mMaterialTypeComboBox->blockSignals( false );
105 materialTypeChanged();
106}
107
109{
110 mFilterByTechnique = enabled;
111 rebuildAvailableTypes();
112}
113
115{
116 mMode = mode;
117 rebuildAvailableTypes();
118}
119
121{
122 mMaterialTypeComboBox->setCurrentIndex( mMaterialTypeComboBox->findData( settings->type() ) );
123 mCurrentSettings.reset( settings->clone() );
124 mLayer = layer;
125 updateMaterialWidget();
126}
127
128std::unique_ptr< QgsAbstractMaterialSettings > QgsMaterialWidget::settings()
129{
130 return mCurrentSettings ? std::unique_ptr< QgsAbstractMaterialSettings >( mCurrentSettings->clone() ) : nullptr;
131}
132
133void QgsMaterialWidget::setType( const QString &type )
134{
135 mMaterialTypeComboBox->setCurrentIndex( mMaterialTypeComboBox->findData( type ) );
136 materialTypeChanged();
137}
138
140{
142 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
143 {
144 w->setDockMode( dockMode );
145 }
146}
147
149{
150 mPreviewVisible = visible;
151 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
152 {
153 w->setPreviewVisible( visible );
154 }
155}
156
157void QgsMaterialWidget::materialTypeChanged()
158{
159 std::unique_ptr<QgsAbstractMaterialSettings> currentSettings( settings() );
160 const QString existingType = currentSettings ? currentSettings->type() : QString();
161 const QString newType = mMaterialTypeComboBox->currentData().toString();
162 if ( existingType == newType )
163 return;
164
165 if ( QgsMaterialSettingsAbstractMetadata *am = QgsApplication::materialRegistry()->materialSettingsMetadata( newType ) )
166 {
167 // change material to a new (with different type)
168 // base new layer on existing materials's properties
169 std::unique_ptr<QgsAbstractMaterialSettings> newMaterial( am->create() );
170 if ( newMaterial )
171 {
172 if ( currentSettings )
173 {
174 QDomDocument doc;
175 QDomElement tempElem = doc.createElement( u"temp"_s );
176 currentSettings->writeXml( tempElem, QgsReadWriteContext() );
177 newMaterial->readXml( tempElem, QgsReadWriteContext() );
178 }
179
180 mCurrentSettings = std::move( newMaterial );
181 updateMaterialWidget();
182 emit changed();
183 }
184 }
185}
186
187void QgsMaterialWidget::materialWidgetChanged()
188{
189 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
190 {
191 mCurrentSettings = w->settings();
192 }
193 emit changed();
194}
195
196void QgsMaterialWidget::updateMaterialWidget()
197{
198 if ( mStackedWidget->currentWidget() != mPageDummy )
199 {
200 // stop updating from the original widget
201 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
202 disconnect( w, &QgsMaterialSettingsWidget::changed, this, &QgsMaterialWidget::materialWidgetChanged );
203 mStackedWidget->removeWidget( mStackedWidget->currentWidget() );
204 }
205
206 const QString settingsType = mCurrentSettings->type();
207 if ( QgsMaterialSettingsAbstractMetadata *am = QgsApplication::materialRegistry()->materialSettingsMetadata( settingsType ) )
208 {
209 if ( QgsMaterialSettingsWidget *w = am->createWidget() )
210 {
211 w->setSettings( mCurrentSettings.get(), mLayer );
212 w->setTechnique( mTechnique );
213 w->setMode( mMode );
214 w->setPreviewVisible( mPreviewVisible );
215 w->setDockMode( dockMode() );
216 mStackedWidget->addWidget( w );
217 mStackedWidget->setCurrentWidget( w );
218 // start receiving updates from widget
219 connect( w, &QgsMaterialSettingsWidget::changed, this, &QgsMaterialWidget::materialWidgetChanged );
221 return;
222 }
223 }
224 // When anything is not right
225 mStackedWidget->setCurrentWidget( mPageDummy );
226}
227
228
229//
230// QgsMaterialWidgetDialog
231//
232
234 : QDialog( parent )
235{
237
238 QVBoxLayout *vLayout = new QVBoxLayout();
239 mWidget = new QgsMaterialWidget();
240 mWidget->setPreviewVisible( true );
241 vLayout->addWidget( mWidget, 1 );
242
243 if ( settings )
244 {
245 mWidget->setSettings( settings, nullptr );
246 }
247
248 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Ok, Qt::Horizontal );
249 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
250 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
251 vLayout->addWidget( mButtonBox );
252 setLayout( vLayout );
253 setWindowTitle( tr( "Material" ) );
254
255 connect( mWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
256}
257
259{
260 mWidget->setTechnique( technique );
261}
262
264{
265 mWidget->setFilterByTechnique( enabled );
266}
267
268std::unique_ptr<QgsAbstractMaterialSettings> QgsMaterialWidgetDialog::settings()
269{
270 return mWidget->settings();
271}
272
274{
275 return mButtonBox;
276}
MaterialWidgetMode
Modes for material settings widgets.
Definition qgis.h:4429
MaterialRenderingTechnique
Material rendering techniques.
Definition qgis.h:4411
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:225
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.
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.
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 setDockMode(bool dockMode) override
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
void setMode(Qgis::MaterialWidgetMode mode)
Sets the widget display mode.
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.
A PBR metal rough shading material used for rendering.
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
bool dockMode() const
Returns the dock mode state.
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.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
A container for the context for various read/write operations on objects.
Represents a vector layer which manages a vector based dataset.