QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
17#include "qgsvectorlayer.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
33QgsBinaryWidgetWrapper::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
59QWidget *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
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
113void QgsBinaryWidgetWrapper::updateValues( const QVariant &value, const QVariantList & )
114{
115 mValue = value.isValid() && !QgsVariantUtils::isNull( value ) && 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
136void 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
167void 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
199void 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
211QString QgsBinaryWidgetWrapper::defaultPath()
212{
213 return QgsSettings().value( QStringLiteral( "/UI/lastBinaryDir" ), QDir::homePath() ).toString();
214}
215
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
void setEnabled(bool enabled) override
Is used to enable or disable the edit functionality of the managed widget.
void showIndeterminateState() override
Sets the widget to display in an indeterminate "mixed value" state.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
QVariant value() const override
Will be used to access the widget's value.
QgsBinaryWidgetWrapper(QgsVectorLayer *layer, int fieldIdx, QWidget *editor=nullptr, QWidget *parent=nullptr, QgsMessageBar *messageBar=nullptr)
Constructor for QgsBinaryWidgetWrapper.
bool valid() const override
Returns true if the widget has been properly initialized.
Manages an editor widget Widget and wrapper share the same parent.
void emitValueChanged()
Will call the value() method to determine the emitted value.
static QString representFileSize(qint64 bytes)
Returns the human size from bytes.
Trick to keep a widget focused and avoid QT crashes.
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
void pushSuccess(const QString &title, const QString &message)
Pushes a success message with default timeout to the message bar.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.