QGIS API Documentation 4.3.0-Master (bf28115e945)
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 }
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{
135 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
136 {
137 w->setDockMode( dockMode );
138 }
139}
140
142{
143 mPreviewVisible = visible;
144 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
145 {
146 w->setPreviewVisible( visible );
147 }
148}
149
150void QgsMaterialWidget::materialTypeChanged()
151{
152 std::unique_ptr<QgsAbstractMaterialSettings> currentSettings( settings() );
153 const QString existingType = currentSettings ? currentSettings->type() : QString();
154 const QString newType = mMaterialTypeComboBox->currentData().toString();
155 if ( existingType == newType )
156 return;
157
158 if ( QgsMaterialSettingsAbstractMetadata *am = QgsApplication::materialRegistry()->materialSettingsMetadata( newType ) )
159 {
160 // change material to a new (with different type)
161 // base new layer on existing materials's properties
162 std::unique_ptr<QgsAbstractMaterialSettings> newMaterial( am->create() );
163 if ( newMaterial )
164 {
165 if ( currentSettings )
166 {
167 QDomDocument doc;
168 QDomElement tempElem = doc.createElement( u"temp"_s );
169 currentSettings->writeXml( tempElem, QgsReadWriteContext() );
170 newMaterial->readXml( tempElem, QgsReadWriteContext() );
171 }
172
173 mCurrentSettings = std::move( newMaterial );
174 updateMaterialWidget();
175 emit changed();
176 }
177 }
178}
179
180void QgsMaterialWidget::materialWidgetChanged()
181{
182 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
183 {
184 mCurrentSettings = w->settings();
185 }
186 emit changed();
187}
188
189void QgsMaterialWidget::updateMaterialWidget()
190{
191 if ( mStackedWidget->currentWidget() != mPageDummy )
192 {
193 // stop updating from the original widget
194 if ( QgsMaterialSettingsWidget *w = qobject_cast<QgsMaterialSettingsWidget *>( mStackedWidget->currentWidget() ) )
195 disconnect( w, &QgsMaterialSettingsWidget::changed, this, &QgsMaterialWidget::materialWidgetChanged );
196 mStackedWidget->removeWidget( mStackedWidget->currentWidget() );
197 }
198
199 const QString settingsType = mCurrentSettings->type();
200 if ( QgsMaterialSettingsAbstractMetadata *am = QgsApplication::materialRegistry()->materialSettingsMetadata( settingsType ) )
201 {
202 if ( QgsMaterialSettingsWidget *w = am->createWidget() )
203 {
204 w->setSettings( mCurrentSettings.get(), mLayer );
205 w->setTechnique( mTechnique );
206 w->setPreviewVisible( mPreviewVisible );
207 w->setDockMode( dockMode() );
208 mStackedWidget->addWidget( w );
209 mStackedWidget->setCurrentWidget( w );
210 // start receiving updates from widget
211 connect( w, &QgsMaterialSettingsWidget::changed, this, &QgsMaterialWidget::materialWidgetChanged );
213 return;
214 }
215 }
216 // When anything is not right
217 mStackedWidget->setCurrentWidget( mPageDummy );
218}
219
220
221//
222// QgsMaterialWidgetDialog
223//
224
226 : QDialog( parent )
227{
229
230 QVBoxLayout *vLayout = new QVBoxLayout();
231 mWidget = new QgsMaterialWidget();
232 mWidget->setPreviewVisible( true );
233 vLayout->addWidget( mWidget, 1 );
234
235 if ( settings )
236 {
237 mWidget->setSettings( settings, nullptr );
238 }
239
240 mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Ok, Qt::Horizontal );
241 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
242 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
243 vLayout->addWidget( mButtonBox );
244 setLayout( vLayout );
245 setWindowTitle( tr( "Material" ) );
246
247 connect( mWidget, &QgsPanelWidget::panelAccepted, this, &QDialog::reject );
248}
249
250std::unique_ptr<QgsAbstractMaterialSettings> QgsMaterialWidgetDialog::settings()
251{
252 return mWidget->settings();
253}
254
256{
257 return mButtonBox;
258}
MaterialRenderingTechnique
Material rendering techniques.
Definition qgis.h:4388
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 setDockMode(bool dockMode) override
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
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.