QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsphotowidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsphotowidgetwrapper.cpp
3  --------------------------------------
4  Date : 5.1.2014
5  Copyright : (C) 2014 Matthias Kuhn
6  Email : matthias at opengis dot ch
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 "qgsphotowidgetwrapper.h"
17 #include "qgspixmaplabel.h"
18 #include "qgsproject.h"
19 
20 #include <QGridLayout>
21 #include <QFileDialog>
22 #include <QSettings>
23 #include <QUrl>
24 
25 #include "qgsfilterlineedit.h"
26 
28  : QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
29  , mPhotoLabel( nullptr )
30  , mPhotoPixmapLabel( nullptr )
31  , mLineEdit( nullptr )
32  , mButton( nullptr )
33 {
34 #ifdef WITH_QTWEBKIT
35  mWebView = nullptr;
36 #endif
37 }
38 
39 void QgsPhotoWidgetWrapper::selectFileName()
40 {
41  if ( !mLineEdit )
42  return;
43 
44  QString fileName = QFileDialog::getOpenFileName( nullptr, tr( "Select a picture" ), QFileInfo( mLineEdit->text() ).absolutePath() );
45 
46  if ( fileName.isNull() )
47  return;
48 
49  QString projPath = QDir::toNativeSeparators( QDir::cleanPath( QgsProject::instance()->fileInfo().absolutePath() ) );
50  QString filePath = QDir::toNativeSeparators( QDir::cleanPath( QFileInfo( fileName ).absoluteFilePath() ) );
51 
52  if ( filePath.startsWith( projPath ) )
53  filePath = QDir( projPath ).relativeFilePath( filePath );
54 
55  mLineEdit->setText( filePath );
56 }
57 
58 void QgsPhotoWidgetWrapper::loadPixmap( const QString& fileName )
59 {
60  if ( fileName.isEmpty() )
61  {
62 #ifdef WITH_QTWEBKIT
63  if ( mWebView )
64  {
65  mWebView->setUrl( QString() );
66  }
67 #endif
68  clearPicture();
69  return;
70  }
71 
72  QString filePath = fileName;
73 
74  if ( QUrl( fileName ).isRelative() )
75  filePath = QDir( QgsProject::instance()->fileInfo().absolutePath() ).filePath( fileName );
76 
77 #ifdef WITH_QTWEBKIT
78  if ( mWebView )
79  {
80  mWebView->setUrl( filePath );
81  }
82 #endif
83 
84  QPixmap pm( filePath );
85  if ( !pm.isNull() && mPhotoLabel )
86  {
87  QSize size( config( "Width" ).toInt(), config( "Height" ).toInt() );
88  if ( size.width() == 0 && size.height() > 0 )
89  {
90  size.setWidth( size.height() * pm.size().width() / pm.size().height() );
91  }
92  else if ( size.width() > 0 && size.height() == 0 )
93  {
94  size.setHeight( size.width() * pm.size().height() / pm.size().width() );
95  }
96 
97  if ( mPhotoPixmapLabel )
98  {
99  mPhotoPixmapLabel->setPixmap( pm );
100 
101  if ( size.width() != 0 || size.height() != 0 )
102  {
103  mPhotoPixmapLabel->setMinimumSize( size );
104  mPhotoPixmapLabel->setMaximumSize( size );
105  }
106  }
107  else // mPhotoLabel is checked in the outer if branch
108  {
109  mPhotoLabel->setMinimumSize( size );
110  pm = pm.scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
111  mPhotoLabel->setPixmap( pm );
112  }
113  }
114  else
115  {
116  clearPicture();
117  }
118 }
119 
120 void QgsPhotoWidgetWrapper::clearPicture()
121 {
122  if ( mPhotoLabel )
123  {
124  mPhotoLabel->clear();
125  mPhotoLabel->setMinimumSize( QSize( 0, 0 ) );
126 
127  if ( mPhotoPixmapLabel )
128  mPhotoPixmapLabel->setPixmap( QPixmap() );
129  else
130  mPhotoLabel->setPixmap( QPixmap() );
131  }
132 }
133 
135 {
136  QVariant v;
137 
138  if ( mLineEdit )
139  {
140  if ( mLineEdit->text() == QSettings().value( "qgis/nullValue", "NULL" ).toString() )
141  v = QVariant( QVariant::String );
142  else
143  v = mLineEdit->text();
144  }
145 
146  return v;
147 }
148 
150 {
151  if ( mLineEdit )
152  {
153  whileBlocking( mLineEdit )->clear();
154  }
155  if ( mPhotoLabel )
156  mPhotoLabel->clear();
157  if ( mPhotoPixmapLabel )
158  mPhotoPixmapLabel->clear();
159 }
160 
162 {
163  QWidget* container = new QWidget( parent );
164  QGridLayout* layout = new QGridLayout();
166  QgsPixmapLabel* label = new QgsPixmapLabel();
167  label->setObjectName( "PhotoLabel" );
168  QPushButton* pb = new QPushButton( tr( "..." ) );
169  pb->setObjectName( "FileChooserButton" );
170 
171  layout->addWidget( label, 0, 0, 1, 2 );
172  layout->addWidget( le, 1, 0 );
173  layout->addWidget( pb, 1, 1 );
174  layout->setMargin( 0 );
175  layout->setContentsMargins( 0, 0, 0, 0 );
176 
177  container->setLayout( layout );
178 
179  return container;
180 }
181 
183 {
184  QWidget* container;
185 
186  mLineEdit = qobject_cast<QLineEdit*>( editor );
187 #ifdef WITH_QTWEBKIT
188  mWebView = qobject_cast<QWebView*>( editor );
189 #endif
190 
191  if ( mLineEdit )
192  {
193  container = mLineEdit->parentWidget();
194  }
195 #ifdef WITH_QTWEBKIT
196  else if ( mWebView )
197  {
198  container = mWebView->parentWidget();
199  mLineEdit = container->findChild<QLineEdit*>();
200  }
201 #endif
202  else
203  {
204  container = editor;
205  mLineEdit = container->findChild<QLineEdit*>();
206  }
207 
208  mButton = container->findChild<QPushButton*>( "FileChooserButton" );
209  if ( !mButton )
210  mButton = container->findChild<QPushButton*>();
211 
212  mPhotoLabel = container->findChild<QLabel*>( "PhotoLabel" );
213  if ( !mPhotoLabel )
214  mPhotoLabel = container->findChild<QLabel*>();
215 
216  mPhotoPixmapLabel = qobject_cast<QgsPixmapLabel*>( mPhotoLabel );
217  if ( mButton )
218  connect( mButton, SIGNAL( clicked() ), this, SLOT( selectFileName() ) );
219 
220  if ( mLineEdit )
221  {
222 
223  QgsFilterLineEdit *fle = qobject_cast<QgsFilterLineEdit*>( mLineEdit );
224  if ( fle )
225  {
226  fle->setNullValue( QSettings().value( "qgis/nullValue", "NULL" ).toString() );
227  }
228 
229  connect( mLineEdit, SIGNAL( textChanged( QString ) ), this, SLOT( valueChanged( QString ) ) );
230  connect( mLineEdit, SIGNAL( textChanged( QString ) ), this, SLOT( loadPixmap( QString ) ) );
231  }
232 }
233 
235 {
236 #ifdef WITH_QTWEBKIT
237  return mPhotoLabel || mLineEdit || mButton || mWebView;
238 #else
239  return mPhotoLabel || mLineEdit || mButton;
240 #endif
241 }
242 
244 {
245  if ( mLineEdit )
246  {
247  if ( value.isNull() )
248  {
249  whileBlocking( mLineEdit )->setText( QSettings().value( "qgis/nullValue", "NULL" ).toString() );
250  clearPicture();
251  }
252  else
253  mLineEdit->setText( value.toString() );
254  }
255  else
256  {
257  loadPixmap( value.toString() );
258  }
259 }
260 
262 {
263  if ( mLineEdit )
264  mLineEdit->setEnabled( enabled );
265 
266  if ( mButton )
267  mButton->setEnabled( enabled );
268 }
269 
270 void QgsPhotoWidgetWrapper::updateConstraintWidgetStatus( bool constraintValid )
271 {
272  if ( mLineEdit )
273  {
274  if ( constraintValid )
275  mLineEdit->setStyleSheet( QString() );
276  else
277  {
278  mLineEdit->setStyleSheet( "QgsFilterLineEdit { background-color: #dd7777; }" );
279  }
280  }
281 }
void setStyleSheet(const QString &styleSheet)
QSize size() const
QString toNativeSeparators(const QString &pathName)
void setHeight(int height)
QString relativeFilePath(const QString &fileName) const
void setContentsMargins(int left, int top, int right, int bottom)
void setPixmap(const QPixmap &)
int width() const
void valueChanged()
Will call the value() method to determine the emitted value.
QVariant value() const override
Will be used to access the widget&#39;s value.
void addWidget(QWidget *widget, int row, int column, QFlags< Qt::AlignmentFlag > alignment)
Manages an editor widget Widget and wrapper share the same parent.
void setPixmap(const QPixmap &)
QString filePath(const QString &fileName) const
void clear()
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isNull() const
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
QgsPhotoWidgetWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *editor=nullptr, QWidget *parent=nullptr)
void setMinimumSize(const QSize &)
void setEnabled(bool)
void setLayout(QLayout *layout)
bool isNull() const
void setWidth(int width)
void setObjectName(const QString &name)
bool isEmpty() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QLineEdit subclass with built in support for clearing the widget&#39;s value and handling custom null val...
QPixmap scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const
void setMargin(int margin)
void setEnabled(bool enabled) override
bool isNull() const
void setMaximumSize(const QSize &)
bool valid() const override
Return true if the widget has been properly initialized.
QString cleanPath(const QString &path)
QVariant value(const QString &key, const QVariant &defaultValue) const
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:333
void showIndeterminateState() override
Sets the widget to display in an indeterminate "mixed value" state.
QWidget * parentWidget() const
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
int height() const
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFlags< QFileDialog::Option > options)
QgsEditorWidgetConfig config() const
Returns the whole config.
void setNullValue(const QString &nullValue)
Sets the string representation for null values in the widget.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setValue(const QVariant &value) override
QObject * parent() const
Represents a vector layer which manages a vector based data sets.
QString toString() const
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
The QgsPixmapLabel class shows a pixmap and adjusts its size to the space given to the widget by the ...
T findChild(const QString &name) const