QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 "qgssettings.h"
21 #include "qgsmessagebar.h"
22 #include "qgsapplication.h"
23 #include <QHBoxLayout>
24 #include <QFileDialog>
25 #include <QLabel>
26 #include <QToolButton>
27 #include <QAction>
28 #include <QMenu>
29 #include <QMessageBox>
30 
31 QgsBinaryWidgetWrapper::QgsBinaryWidgetWrapper( QgsVectorLayer *layer, int fieldIdx, QWidget *editor, QWidget *parent, QgsMessageBar *messageBar )
32  : QgsEditorWidgetWrapper( layer, fieldIdx, editor, parent )
33  , mMessageBar( messageBar )
34 {
35 }
36 
37 
39 {
40  return mValue.isEmpty() || mValue.isNull() ? QVariant( QVariant::ByteArray ) : mValue;
41 }
42 
44 {
45  if ( mLabel )
46  mLabel->clear();
47 }
48 
50 {
51  if ( mSetAction )
52  mSetAction->setEnabled( enabled );
53  if ( mClearAction )
54  mClearAction->setEnabled( enabled && !mValue.isEmpty() );
55 }
56 
57 QWidget *QgsBinaryWidgetWrapper::createWidget( QWidget *parent )
58 {
59  QWidget *container = new QWidget( parent );
60  QHBoxLayout *layout = new QHBoxLayout();
61  container->setLayout( layout );
62  layout->setMargin( 0 );
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  QString file = QFileDialog::getSaveFileName( nullptr,
139  tr( "Save Contents to File" ),
140  defaultPath(),
141  tr( "All files" ) + " (*.*)" );
142  if ( file.isEmpty() )
143  {
144  return;
145  }
146 
147  QFileInfo fi( file );
148  s.setValue( QStringLiteral( "/UI/lastBinaryDir" ), fi.absolutePath() );
149 
150  QFile fileOut( file );
151  fileOut.open( QIODevice::WriteOnly );
152  fileOut.write( mValue );
153  fileOut.close();
154 
155  if ( mMessageBar )
156  mMessageBar->pushSuccess( QString(), tr( "Saved content to <a href=\"%1\">%2</a>" ).arg(
157  QUrl::fromLocalFile( file ).toString(), QDir::toNativeSeparators( file ) ) );
158 }
159 
160 void QgsBinaryWidgetWrapper::setContent()
161 {
162  QgsSettings s;
163  QString file = QFileDialog::getOpenFileName( nullptr,
164  tr( "Embed File" ),
165  defaultPath(),
166  tr( "All files" ) + " (*.*)" );
167  QFileInfo fi( file );
168  if ( file.isEmpty() || !fi.exists() )
169  {
170  return;
171  }
172 
173  s.setValue( QStringLiteral( "/UI/lastBinaryDir" ), fi.absolutePath() );
174 
175  QFile fileSource( file );
176  if ( !fileSource.open( QIODevice::ReadOnly ) )
177  {
178  return;
179  }
180 
181  updateValues( fileSource.readAll() );
183 }
184 
185 void QgsBinaryWidgetWrapper::clear()
186 {
187  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 )
188  return;
189 
190  updateValues( QByteArray() );
192 }
193 
194 QString QgsBinaryWidgetWrapper::defaultPath()
195 {
196  return QgsSettings().value( QStringLiteral( "/UI/lastBinaryDir" ), QDir::homePath() ).toString();
197 }
198 
void emitValueChanged()
Will call the value() method to determine the emitted value.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Manages an editor widget Widget and wrapper share the same parent.
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:45
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
void pushSuccess(const QString &title, const QString &message)
Pushes a success message with default timeout to the message bar.
static QString representFileSize(qint64 bytes)
Returns the human size from bytes.
void showIndeterminateState() override
Sets the widget to display in an indeterminate "mixed value" state.
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
bool valid() const override
Returns true if the widget has been properly initialized.
QgsBinaryWidgetWrapper(QgsVectorLayer *layer, int fieldIdx, QWidget *editor=nullptr, QWidget *parent=nullptr, QgsMessageBar *messageBar=nullptr)
Constructor for QgsBinaryWidgetWrapper.
Represents a vector layer which manages a vector based data sets.
QVariant value() const override
Will be used to access the widget&#39;s value.