QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsbinarywidgetwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsbinarywidgetwrapper.cpp
3  -------------------------
4  Date : November 2018
5  Copyright : (C) 2018 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 "qgsbinarywidgetwrapper.h"
17 #include "qgsvectorlayer.h"
18 #include "qgsvectordataprovider.h"
19 #include "qgsfileutils.h"
20 #include "qgsfocuskeeper.h"
21 #include "qgssettings.h"
22 #include "qgsmessagebar.h"
23 #include "qgsapplication.h"
24 #include <QHBoxLayout>
25 #include <QFileDialog>
26 #include <QLabel>
27 #include <QToolButton>
28 #include <QAction>
29 #include <QMenu>
30 #include <QMessageBox>
31 
32 QgsBinaryWidgetWrapper::QgsBinaryWidgetWrapper( QgsVectorLayer *layer, int fieldIdx, QWidget *editor, QWidget *parent, QgsMessageBar *messageBar )
33  : QgsEditorWidgetWrapper( layer, fieldIdx, editor, parent )
34  , mMessageBar( messageBar )
35 {
36 }
37 
38 
40 {
41  return mValue.isEmpty() || mValue.isNull() ? QVariant( QVariant::ByteArray ) : mValue;
42 }
43 
45 {
46  if ( mLabel )
47  mLabel->clear();
48 }
49 
51 {
52  if ( mSetAction )
53  mSetAction->setEnabled( enabled );
54  if ( mClearAction )
55  mClearAction->setEnabled( enabled && !mValue.isEmpty() );
56 }
57 
58 QWidget *QgsBinaryWidgetWrapper::createWidget( QWidget *parent )
59 {
60  QWidget *container = new QWidget( parent );
61  QHBoxLayout *layout = new QHBoxLayout();
62  container->setLayout( layout );
63  layout->setContentsMargins( 0, 0, 0, 0 );
64 
65  QLabel *label = new QLabel();
66  layout->addWidget( label, 1 );
67 
68  QToolButton *button = new QToolButton();
69  button->setText( QChar( 0x2026 ) );
70  layout->addWidget( button, 0 );
71 
72  container->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
73  return container;
74 }
75 
76 void QgsBinaryWidgetWrapper::initWidget( QWidget *editor )
77 {
78  mLabel = editor->findChild<QLabel *>();
79  mButton = editor->findChild<QToolButton *>();
80 
81  if ( mLabel )
82  {
83  QFont f = mLabel->font();
84  f.setItalic( true );
85  mLabel->setFont( f );
86  }
87 
88  if ( mButton )
89  {
90  mButton->setPopupMode( QToolButton::InstantPopup );
91 
92  mSetAction = new QAction( tr( "Embed File…" ), mButton );
93  connect( mSetAction, &QAction::triggered, this, &QgsBinaryWidgetWrapper::setContent );
94  mClearAction = new QAction( tr( "Clear Contents…" ), mButton );
95  connect( mClearAction, &QAction::triggered, this, &QgsBinaryWidgetWrapper::clear );
96  mSaveAction = new QAction( tr( "Save Contents to File…" ), mButton );
97  connect( mSaveAction, &QAction::triggered, this, &QgsBinaryWidgetWrapper::saveContent );
98  QMenu *menu = new QMenu( mButton );
99  menu->addAction( mSetAction );
100  menu->addAction( mClearAction );
101  menu->addSeparator();
102  menu->addAction( mSaveAction );
103  mButton->setMenu( menu );
104  }
105 }
106 
108 {
109  return mLabel && mButton;
110 }
111 
112 void QgsBinaryWidgetWrapper::updateValues( const QVariant &value, const QVariantList & )
113 {
114  mValue = value.isValid() && !value.isNull() && value.canConvert< QByteArray >() ? value.toByteArray() : QByteArray();
115  if ( mValue.length() == 0 )
116  mValue = QByteArray();
117 
118  if ( mLabel )
119  {
120  if ( !mValue.isEmpty() )
121  {
122  mLabel->setText( tr( "Binary (%1)" ).arg( QgsFileUtils::representFileSize( mValue.size() ) ) );
123  }
124  else
125  {
126  mLabel->setText( QgsApplication::nullRepresentation() );
127  }
128  }
129  if ( mSaveAction )
130  mSaveAction->setEnabled( !mValue.isEmpty() );
131  if ( mClearAction )
132  mClearAction->setEnabled( !mValue.isEmpty() );
133 }
134 
135 void QgsBinaryWidgetWrapper::saveContent()
136 {
137  QgsSettings s;
138 
139  QString file;
140  {
141  QgsFocusKeeper focusKeeper;
142 
143  file = QFileDialog::getSaveFileName( nullptr,
144  tr( "Save Contents to File" ),
145  defaultPath(),
146  tr( "All files" ) + " (*.*)" );
147  }
148  if ( file.isEmpty() )
149  {
150  return;
151  }
152 
153  QFileInfo fi( file );
154  s.setValue( QStringLiteral( "/UI/lastBinaryDir" ), fi.absolutePath() );
155 
156  QFile fileOut( file );
157  fileOut.open( QIODevice::WriteOnly );
158  fileOut.write( mValue );
159  fileOut.close();
160 
161  if ( mMessageBar )
162  mMessageBar->pushSuccess( QString(), tr( "Saved content to <a href=\"%1\">%2</a>" ).arg(
163  QUrl::fromLocalFile( file ).toString(), QDir::toNativeSeparators( file ) ) );
164 }
165 
166 void QgsBinaryWidgetWrapper::setContent()
167 {
168  QgsSettings s;
169 
170  QString file;
171  {
172  QgsFocusKeeper focusKeeper;
173 
174  file = QFileDialog::getOpenFileName( nullptr,
175  tr( "Embed File" ),
176  defaultPath(),
177  tr( "All files" ) + " (*.*)" );
178  }
179 
180  QFileInfo fi( file );
181  if ( file.isEmpty() || !fi.exists() )
182  {
183  return;
184  }
185 
186  s.setValue( QStringLiteral( "/UI/lastBinaryDir" ), fi.absolutePath() );
187 
188  QFile fileSource( file );
189  if ( !fileSource.open( QIODevice::ReadOnly ) )
190  {
191  return;
192  }
193 
194  updateValues( fileSource.readAll() );
196 }
197 
198 void QgsBinaryWidgetWrapper::clear()
199 {
200  {
201  QgsFocusKeeper focusKeeper;
202  if ( QMessageBox::question( nullptr, tr( "Clear Contents" ), tr( "Are you sure you want the clear this field's content?" ), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
203  return;
204  }
205 
206  updateValues( QByteArray() );
208 }
209 
210 QString QgsBinaryWidgetWrapper::defaultPath()
211 {
212  return QgsSettings().value( QStringLiteral( "/UI/lastBinaryDir" ), QDir::homePath() ).toString();
213 }
214 
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:174
QgsBinaryWidgetWrapper::valid
bool valid() const override
Returns true if the widget has been properly initialized.
Definition: qgsbinarywidgetwrapper.cpp:107
QgsBinaryWidgetWrapper::QgsBinaryWidgetWrapper
QgsBinaryWidgetWrapper(QgsVectorLayer *layer, int fieldIdx, QWidget *editor=nullptr, QWidget *parent=nullptr, QgsMessageBar *messageBar=nullptr)
Constructor for QgsBinaryWidgetWrapper.
Definition: qgsbinarywidgetwrapper.cpp:32
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QgsBinaryWidgetWrapper::initWidget
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
Definition: qgsbinarywidgetwrapper.cpp:76
QgsEditorWidgetWrapper
Manages an editor widget Widget and wrapper share the same parent.
Definition: qgseditorwidgetwrapper.h:48
qgsapplication.h
QgsFocusKeeper
Trick to keep a widget focused and avoid QT crashes.
Definition: qgsfocuskeeper.h:35
qgsfocuskeeper.h
QgsApplication::nullRepresentation
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
Definition: qgsapplication.cpp:1851
qgsvectordataprovider.h
QgsMessageBar
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
qgsbinarywidgetwrapper.h
qgsmessagebar.h
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:289
QgsEditorWidgetWrapper::emitValueChanged
void emitValueChanged()
Will call the value() method to determine the emitted value.
Definition: qgseditorwidgetwrapper.cpp:91
QgsBinaryWidgetWrapper::setEnabled
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
Definition: qgsbinarywidgetwrapper.cpp:50
qgsfileutils.h
QgsBinaryWidgetWrapper::value
QVariant value() const override
Will be used to access the widget's value.
Definition: qgsbinarywidgetwrapper.cpp:39
qgsvectorlayer.h
QgsMessageBar::pushSuccess
void pushSuccess(const QString &title, const QString &message)
Pushes a success message with default timeout to the message bar.
Definition: qgsmessagebar.cpp:194
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsFileUtils::representFileSize
static QString representFileSize(qint64 bytes)
Returns the human size from bytes.
Definition: qgsfileutils.cpp:24
qgssettings.h
QgsBinaryWidgetWrapper::createWidget
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
Definition: qgsbinarywidgetwrapper.cpp:58
QgsBinaryWidgetWrapper::showIndeterminateState
void showIndeterminateState() override
Sets the widget to display in an indeterminate "mixed value" state.
Definition: qgsbinarywidgetwrapper.cpp:44