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