-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE] New form widget for binary (blob) fields
This widget is available for binary fields only (and is the default widget used for binary fields). It offers a label showing whether the blob field is empty or not, and if non-empty shows the content size (in bytes/kb/etc). A drop down menu button allows users to save the current binary contents of the field out to a disk based file, clear the contents of a blob field, or embed binary contents by picking a file from their system.
- Loading branch information
1 parent
608d03c
commit d96ce7a
Showing
6 changed files
with
356 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/*************************************************************************** | ||
qgsbinarywidgetfactory.cpp | ||
------------------------- | ||
Date : November 2018 | ||
Copyright : (C) 2018 Nyall Dawson | ||
Email : nyall dot dawson at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgsbinarywidgetfactory.h" | ||
|
||
#include "qgsbinarywidgetwrapper.h" | ||
#include "qgsdummyconfigdlg.h" | ||
#include "qgsvectorlayer.h" | ||
#include "qgsvectordataprovider.h" | ||
|
||
QgsBinaryWidgetFactory::QgsBinaryWidgetFactory( const QString &name ) | ||
: QgsEditorWidgetFactory( name ) | ||
{ | ||
} | ||
|
||
QgsEditorWidgetWrapper *QgsBinaryWidgetFactory::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const | ||
{ | ||
return new QgsBinaryWidgetWrapper( vl, fieldIdx, editor, parent ); | ||
} | ||
|
||
QgsEditorConfigWidget *QgsBinaryWidgetFactory::configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const | ||
{ | ||
return new QgsDummyConfigDlg( vl, fieldIdx, parent, QObject::tr( "A widget for interacting with binary (BLOB) fields." ) ); | ||
} | ||
|
||
unsigned int QgsBinaryWidgetFactory::fieldScore( const QgsVectorLayer *vl, int fieldIdx ) const | ||
{ | ||
const QgsField field = vl->fields().field( fieldIdx ); | ||
const QVariant::Type type = field.type(); | ||
// ByteArray fields only | ||
return type == QVariant::ByteArray ? 20 : 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/*************************************************************************** | ||
qgsbinarywidgetfactory.h | ||
----------------------- | ||
Date : November 2018 | ||
Copyright : (C) 2018 Nyall Dawson | ||
Email : nyall dot dawson at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSBINARYWIDGETFACTORY_H | ||
#define QGSBINARYWIDGETFACTORY_H | ||
|
||
#include "qgseditorwidgetfactory.h" | ||
#include "qgis_gui.h" | ||
|
||
SIP_NO_FILE | ||
|
||
/** | ||
* \ingroup gui | ||
* \class QgsBinaryWidgetFactory | ||
* Editor widget factory for binary (BLOB) widgets. | ||
* \note not available in Python bindings | ||
* \since QGIS 3.6 | ||
*/ | ||
|
||
class GUI_EXPORT QgsBinaryWidgetFactory : public QgsEditorWidgetFactory | ||
{ | ||
public: | ||
explicit QgsBinaryWidgetFactory( const QString &name ); | ||
|
||
// QgsEditorWidgetFactory interface | ||
public: | ||
QgsEditorWidgetWrapper *create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const override; | ||
QgsEditorConfigWidget *configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const override; | ||
|
||
unsigned int fieldScore( const QgsVectorLayer *vl, int fieldIdx ) const override; | ||
}; | ||
|
||
#endif // QGSBINARYWIDGETFACTORY_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
/*************************************************************************** | ||
qgsbinarywidgetwrapper.cpp | ||
------------------------- | ||
Date : November 2018 | ||
Copyright : (C) 2018 Nyall Dawson | ||
Email : nyall dot dawson at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgsbinarywidgetwrapper.h" | ||
#include "qgsvectorlayer.h" | ||
#include "qgsvectordataprovider.h" | ||
#include "qgsfileutils.h" | ||
#include "qgssettings.h" | ||
#include <QHBoxLayout> | ||
#include <QFileDialog> | ||
#include <QLabel> | ||
#include <QToolButton> | ||
#include <QAction> | ||
#include <QMenu> | ||
#include <QMessageBox> | ||
|
||
QgsBinaryWidgetWrapper::QgsBinaryWidgetWrapper( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) | ||
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent ) | ||
|
||
{ | ||
} | ||
|
||
|
||
QVariant QgsBinaryWidgetWrapper::value() const | ||
{ | ||
return mValue; | ||
} | ||
|
||
void QgsBinaryWidgetWrapper::showIndeterminateState() | ||
{ | ||
if ( mLabel ) | ||
mLabel->clear(); | ||
} | ||
|
||
void QgsBinaryWidgetWrapper::setEnabled( bool enabled ) | ||
{ | ||
if ( mSetAction ) | ||
mSetAction->setEnabled( enabled ); | ||
if ( mClearAction ) | ||
mClearAction->setEnabled( enabled && !mValue.isEmpty() ); | ||
} | ||
|
||
QWidget *QgsBinaryWidgetWrapper::createWidget( QWidget *parent ) | ||
{ | ||
QWidget *container = new QWidget( parent ); | ||
QHBoxLayout *layout = new QHBoxLayout(); | ||
container->setLayout( layout ); | ||
layout->setMargin( 0 ); | ||
layout->setContentsMargins( 0, 0, 0, 0 ); | ||
|
||
QLabel *label = new QLabel(); | ||
layout->addWidget( label, 1 ); | ||
|
||
QToolButton *button = new QToolButton(); | ||
button->setText( QChar( 0x2026 ) ); | ||
layout->addWidget( button, 0 ); | ||
|
||
container->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); | ||
return container; | ||
} | ||
|
||
void QgsBinaryWidgetWrapper::initWidget( QWidget *editor ) | ||
{ | ||
mLabel = editor->findChild<QLabel *>(); | ||
mButton = editor->findChild<QToolButton *>(); | ||
|
||
if ( mLabel ) | ||
{ | ||
QFont f = mLabel->font(); | ||
f.setItalic( true ); | ||
mLabel->setFont( f ); | ||
} | ||
|
||
if ( mButton ) | ||
{ | ||
mButton->setPopupMode( QToolButton::InstantPopup ); | ||
|
||
mSetAction = new QAction( tr( "Embed File…" ), mButton ); | ||
connect( mSetAction, &QAction::triggered, this, &QgsBinaryWidgetWrapper::setContent ); | ||
mClearAction = new QAction( tr( "Clear Contents…" ), mButton ); | ||
connect( mClearAction, &QAction::triggered, this, &QgsBinaryWidgetWrapper::clear ); | ||
mSaveAction = new QAction( tr( "Save Contents to File…" ), mButton ); | ||
connect( mSaveAction, &QAction::triggered, this, &QgsBinaryWidgetWrapper::saveContent ); | ||
QMenu *menu = new QMenu( mButton ); | ||
menu->addAction( mSetAction ); | ||
menu->addAction( mClearAction ); | ||
menu->addSeparator(); | ||
menu->addAction( mSaveAction ); | ||
mButton->setMenu( menu ); | ||
} | ||
} | ||
|
||
bool QgsBinaryWidgetWrapper::valid() const | ||
{ | ||
return mLabel && mButton; | ||
} | ||
|
||
void QgsBinaryWidgetWrapper::setValue( const QVariant &value ) | ||
{ | ||
mValue = value.toByteArray(); | ||
if ( mLabel ) | ||
{ | ||
if ( !mValue.isEmpty() ) | ||
{ | ||
mLabel->setText( tr( "Binary (%1)" ).arg( QgsFileUtils::representFileSize( mValue.size() ) ) ); | ||
} | ||
else | ||
{ | ||
mLabel->setText( QgsApplication::nullRepresentation() ); | ||
} | ||
} | ||
if ( mSaveAction ) | ||
mSaveAction->setEnabled( !mValue.isEmpty() ); | ||
if ( mClearAction ) | ||
mClearAction->setEnabled( !mValue.isEmpty() ); | ||
} | ||
|
||
void QgsBinaryWidgetWrapper::saveContent() | ||
{ | ||
QgsSettings s; | ||
QString file = QFileDialog::getSaveFileName( nullptr, | ||
tr( "Save Contents to File" ), | ||
defaultPath(), | ||
tr( "All files" ) + " (*.*)" ); | ||
if ( file.isEmpty() ) | ||
{ | ||
return; | ||
} | ||
|
||
QFileInfo fi( file ); | ||
s.setValue( QStringLiteral( "/UI/lastBinaryDir" ), fi.absolutePath() ); | ||
|
||
QFile fileOut( file ); | ||
fileOut.open( QIODevice::WriteOnly ); | ||
fileOut.write( mValue ); | ||
fileOut.close(); | ||
} | ||
|
||
void QgsBinaryWidgetWrapper::setContent() | ||
{ | ||
QgsSettings s; | ||
QString file = QFileDialog::getOpenFileName( nullptr, | ||
tr( "Embed File" ), | ||
defaultPath(), | ||
tr( "All files" ) + " (*.*)" ); | ||
QFileInfo fi( file ); | ||
if ( file.isEmpty() || !fi.exists() ) | ||
{ | ||
return; | ||
} | ||
|
||
s.setValue( QStringLiteral( "/UI/lastBinaryDir" ), fi.absolutePath() ); | ||
|
||
QFile fileSource( file ); | ||
if ( !fileSource.open( QIODevice::ReadOnly ) ) | ||
{ | ||
return; | ||
} | ||
|
||
setValue( fileSource.readAll() ); | ||
emitValueChanged(); | ||
} | ||
|
||
void QgsBinaryWidgetWrapper::clear() | ||
{ | ||
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 ) | ||
return; | ||
|
||
setValue( QByteArray() ); | ||
} | ||
|
||
QString QgsBinaryWidgetWrapper::defaultPath() | ||
{ | ||
return QgsSettings().value( QStringLiteral( "/UI/lastBinaryDir" ), QDir::homePath() ).toString(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/*************************************************************************** | ||
qgsbinarywidgetwrapper.h | ||
----------------------- | ||
Date : November 2018 | ||
Copyright : (C) 2018 Nyall Dawson | ||
Email : nyall dot dawson at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSBINARYWIDGETWRAPPER_H | ||
#define QGSBINARYWIDGETWRAPPER_H | ||
|
||
#include "qgseditorwidgetwrapper.h" | ||
#include "qgis_gui.h" | ||
|
||
class QLabel; | ||
class QToolButton; | ||
|
||
SIP_NO_FILE | ||
|
||
/** | ||
* \ingroup gui | ||
* \class QgsBinaryWidgetWrapper | ||
* Widget wrapper for binary (BLOB) fields. | ||
* \note not available in Python bindings | ||
* \since QGIS 3.6 | ||
*/ | ||
|
||
class GUI_EXPORT QgsBinaryWidgetWrapper : public QgsEditorWidgetWrapper | ||
{ | ||
Q_OBJECT | ||
public: | ||
explicit QgsBinaryWidgetWrapper( QgsVectorLayer *vl, int fieldIdx, QWidget *editor = nullptr, QWidget *parent = nullptr ); | ||
|
||
// QgsEditorWidgetWrapper interface | ||
public: | ||
QVariant value() const override; | ||
void showIndeterminateState() override; | ||
void setEnabled( bool enabled ) override; | ||
|
||
protected: | ||
QWidget *createWidget( QWidget *parent ) override; | ||
void initWidget( QWidget *editor ) override; | ||
bool valid() const override; | ||
|
||
public slots: | ||
void setValue( const QVariant &value ) override; | ||
|
||
private slots: | ||
|
||
void saveContent(); | ||
void setContent(); | ||
void clear(); | ||
|
||
private: | ||
QString defaultPath(); | ||
|
||
QByteArray mValue; | ||
|
||
QLabel *mLabel = nullptr; | ||
QToolButton *mButton = nullptr; | ||
QAction *mSetAction = nullptr; | ||
QAction *mClearAction = nullptr; | ||
QAction *mSaveAction = nullptr; | ||
}; | ||
|
||
#endif // QGSBINARYWIDGETWRAPPER_H |