[quick] [feature] Feature attribute panel
Allow to show feature attribute form and edit/save the modification of the attributes. Support most frequent QGIS edit widgets such as text edit, value map or external resource (photo capture)
@ -13,6 +13,9 @@ QGIS Quick consists of a Qt plugin that provides the QML components and of a sha
|
||||
|
||||
\subsection qgsquick_overview_widgets QML Classes
|
||||
\subsubsection qgsquick_overview_widgets_mapcanvas MapCanvas
|
||||
\subsubsection qgsquick_overview_widgets_featureform FeatureForm
|
||||
A form listing attributes of a given feature. It supports basic edit field widgets for types such as edit text, map value,
|
||||
check box, date/time picker or external resource (photo capture).
|
||||
\subsubsection qgsquick_overview_widgets_positionmarker PositionMarker
|
||||
The element refers to current position according gps location device connected to it. It holds information about longitude, latitude, altitude,
|
||||
direction of the movement and accuracy of the signal. See also QgsQuickPositionKit.
|
||||
|
@ -1,6 +1,11 @@
|
||||
############################################################
|
||||
# sources
|
||||
SET(QGIS_QUICK_GUI_MOC_HDRS
|
||||
attributes/qgsquickattributeformmodel.h
|
||||
attributes/qgsquickattributeformmodelbase.h
|
||||
attributes/qgsquickattributemodel.h
|
||||
attributes/qgsquicksubmodel.h
|
||||
|
||||
qgsquickfeaturelayerpair.h
|
||||
qgsquickcoordinatetransformer.h
|
||||
qgsquickfeaturehighlight.h
|
||||
@ -20,6 +25,11 @@ SET(QGIS_QUICK_GUI_HDRS
|
||||
)
|
||||
|
||||
SET(QGIS_QUICK_GUI_SRC
|
||||
attributes/qgsquickattributeformmodel.cpp
|
||||
attributes/qgsquickattributeformmodelbase.cpp
|
||||
attributes/qgsquickattributemodel.cpp
|
||||
attributes/qgsquicksubmodel.cpp
|
||||
|
||||
qgsquickfeaturelayerpair.cpp
|
||||
qgsquickcoordinatetransformer.cpp
|
||||
qgsquickfeaturehighlight.cpp
|
||||
@ -37,6 +47,7 @@ SET(QGIS_QUICK_GUI_SRC
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/attributes
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
|
||||
${CMAKE_SOURCE_DIR}/src/core
|
||||
|
72
src/quickgui/attributes/qgsquickattributeformmodel.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/***************************************************************************
|
||||
qgsquickattributeformmodel.cpp
|
||||
--------------------------------------
|
||||
Date : 22.9.2016
|
||||
Copyright : (C) 2016 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgsquickattributeformmodel.h"
|
||||
#include "qgsquickattributeformmodelbase.h"
|
||||
|
||||
QgsQuickAttributeFormModel::QgsQuickAttributeFormModel( QObject *parent )
|
||||
: QSortFilterProxyModel( parent )
|
||||
, mSourceModel( new QgsQuickAttributeFormModelBase( this ) )
|
||||
{
|
||||
setSourceModel( mSourceModel );
|
||||
connect( mSourceModel, &QgsQuickAttributeFormModelBase::hasTabsChanged, this, &QgsQuickAttributeFormModel::hasTabsChanged );
|
||||
connect( mSourceModel, &QgsQuickAttributeFormModelBase::attributeModelChanged, this, &QgsQuickAttributeFormModel::attributeModelChanged );
|
||||
connect( mSourceModel, &QgsQuickAttributeFormModelBase::constraintsValidChanged, this, &QgsQuickAttributeFormModel::constraintsValidChanged );
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeFormModel::hasTabs() const
|
||||
{
|
||||
return mSourceModel->hasTabs();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModel::setHasTabs( bool hasTabs )
|
||||
{
|
||||
mSourceModel->setHasTabs( hasTabs );
|
||||
}
|
||||
|
||||
QgsQuickAttributeModel *QgsQuickAttributeFormModel::attributeModel() const
|
||||
{
|
||||
return mSourceModel->attributeModel();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModel::setAttributeModel( QgsQuickAttributeModel *attributeModel )
|
||||
{
|
||||
mSourceModel->setAttributeModel( attributeModel );
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeFormModel::constraintsValid() const
|
||||
{
|
||||
return mSourceModel->constraintsValid();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModel::save()
|
||||
{
|
||||
mSourceModel->save();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModel::create()
|
||||
{
|
||||
mSourceModel->create();
|
||||
}
|
||||
|
||||
QVariant QgsQuickAttributeFormModel::attribute( const QString &name ) const
|
||||
{
|
||||
return mSourceModel->attribute( name );
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeFormModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
|
||||
{
|
||||
return mSourceModel->data( mSourceModel->index( source_row, 0, source_parent ), CurrentlyVisible ).toBool();
|
||||
}
|
122
src/quickgui/attributes/qgsquickattributeformmodel.h
Normal file
@ -0,0 +1,122 @@
|
||||
/***************************************************************************
|
||||
qgsquickattributeformmodel.h
|
||||
--------------------------------------
|
||||
Date : 22.9.2016
|
||||
Copyright : (C) 2016 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSQUICKATTRIBUTEFORMMODEL_H
|
||||
#define QGSQUICKATTRIBUTEFORMMODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "qgis_quick.h"
|
||||
|
||||
class QgsQuickAttributeFormModelBase;
|
||||
class QgsQuickAttributeModel;
|
||||
class QVariant;
|
||||
|
||||
/**
|
||||
* \ingroup quick
|
||||
* This is a model implementation for attribute form of a feature from a vector layer.
|
||||
*
|
||||
* The model is based on vector layer's edit form config (QgsEditFormConfig). It supports
|
||||
* auto-generated editor layouts and "tab" layout (layout defined with groups and tabs).
|
||||
* The form layout gets flattened into a list, each row has a bunch of roles with values
|
||||
* extracted from the edit form config.
|
||||
*
|
||||
* It also adds filtering of attribute (attributes may be visible or hidden based on expressions).
|
||||
*
|
||||
* \note QML Type: AttributeFormModel
|
||||
*
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
class QUICK_EXPORT QgsQuickAttributeFormModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
//! Feature model with attributes
|
||||
Q_PROPERTY( QgsQuickAttributeModel *attributeModel READ attributeModel WRITE setAttributeModel NOTIFY attributeModelChanged )
|
||||
|
||||
//! Whether use tabs layout
|
||||
Q_PROPERTY( bool hasTabs READ hasTabs WRITE setHasTabs NOTIFY hasTabsChanged )
|
||||
|
||||
//! Returns true if all constraints defined on fields are satisfied with the current attribute values
|
||||
Q_PROPERTY( bool constraintsValid READ constraintsValid NOTIFY constraintsValidChanged )
|
||||
|
||||
public:
|
||||
|
||||
//! Feature fields's roles
|
||||
enum FeatureRoles
|
||||
{
|
||||
ElementType = Qt::UserRole + 1, //!< User role used to identify either "field" or "container" type of item
|
||||
Name, //!< Field Name
|
||||
AttributeValue, //!< Field Value
|
||||
AttributeEditable, //!< Whether is field editable
|
||||
EditorWidget, //!< Widget type to represent the data (text field, value map, ...)
|
||||
EditorWidgetConfig, //!< Widget configuration
|
||||
RememberValue, //!< Remember value (default value for next feature)
|
||||
Field, //!< Field
|
||||
FieldIndex, //!< Index
|
||||
Group, //!< Group
|
||||
AttributeEditorElement, //!< Attribute editor element
|
||||
CurrentlyVisible, //!< Field visible
|
||||
ConstraintValid, //!< Contraint valid
|
||||
ConstraintDescription //!< Contraint description
|
||||
};
|
||||
|
||||
Q_ENUM( FeatureRoles )
|
||||
|
||||
//! Create new attribute form model
|
||||
QgsQuickAttributeFormModel( QObject *parent = nullptr );
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModel::hasTabs
|
||||
bool hasTabs() const;
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModel::hasTabs
|
||||
void setHasTabs( bool hasTabs );
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModel::attributeModel
|
||||
QgsQuickAttributeModel *attributeModel() const;
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModel::attributeModel
|
||||
void setAttributeModel( QgsQuickAttributeModel *attributeModel );
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModel::constraintsValid
|
||||
bool constraintsValid() const;
|
||||
|
||||
//! Updates QgsFeature based on changes
|
||||
Q_INVOKABLE void save();
|
||||
|
||||
//! Creates new QgsFeature
|
||||
Q_INVOKABLE void create();
|
||||
|
||||
//! Returns attribute value with name
|
||||
Q_INVOKABLE QVariant attribute( const QString &name ) const;
|
||||
|
||||
signals:
|
||||
//! \copydoc QgsQuickAttributeFormModel::attributeModel
|
||||
void attributeModelChanged();
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModel::hasTabs
|
||||
void hasTabsChanged();
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModel::constraintsValid
|
||||
void constraintsValidChanged();
|
||||
|
||||
protected:
|
||||
virtual bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const override;
|
||||
|
||||
private:
|
||||
QgsQuickAttributeFormModelBase *mSourceModel; //not owned
|
||||
};
|
||||
|
||||
#endif // QGSQUICKATTRIBUTEFORMMODEL_H
|
383
src/quickgui/attributes/qgsquickattributeformmodelbase.cpp
Normal file
@ -0,0 +1,383 @@
|
||||
/***************************************************************************
|
||||
qgsquickattributemodelbase.cpp
|
||||
--------------------------------------
|
||||
Date : 16.8.2016
|
||||
Copyright : (C) 2016 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgseditorwidgetsetup.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
#include "qgsquickattributeformmodelbase.h"
|
||||
#include "qgsquickattributeformmodel.h"
|
||||
|
||||
/// @cond PRIVATE
|
||||
|
||||
QgsQuickAttributeFormModelBase::QgsQuickAttributeFormModelBase( QObject *parent )
|
||||
: QStandardItemModel( 0, 1, parent )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QHash<int, QByteArray> QgsQuickAttributeFormModelBase::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
||||
|
||||
roles[QgsQuickAttributeFormModel::ElementType] = QByteArray( "Type" );
|
||||
roles[QgsQuickAttributeFormModel::Name] = QByteArray( "Name" );
|
||||
roles[QgsQuickAttributeFormModel::AttributeValue] = QByteArray( "AttributeValue" );
|
||||
roles[QgsQuickAttributeFormModel::AttributeEditable] = QByteArray( "AttributeEditable" );
|
||||
roles[QgsQuickAttributeFormModel::EditorWidget] = QByteArray( "EditorWidget" );
|
||||
roles[QgsQuickAttributeFormModel::EditorWidgetConfig] = QByteArray( "EditorWidgetConfig" );
|
||||
roles[QgsQuickAttributeFormModel::RememberValue] = QByteArray( "RememberValue" );
|
||||
roles[QgsQuickAttributeFormModel::Field] = QByteArray( "Field" );
|
||||
roles[QgsQuickAttributeFormModel::Group] = QByteArray( "Group" );
|
||||
roles[QgsQuickAttributeFormModel::ConstraintValid] = QByteArray( "ConstraintValid" );
|
||||
roles[QgsQuickAttributeFormModel::ConstraintDescription] = QByteArray( "ConstraintDescription" );
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeFormModelBase::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
if ( data( index, role ) != value )
|
||||
{
|
||||
switch ( role )
|
||||
{
|
||||
case QgsQuickAttributeFormModel::RememberValue:
|
||||
{
|
||||
QStandardItem *item = itemFromIndex( index );
|
||||
int fieldIndex = item->data( QgsQuickAttributeFormModel::FieldIndex ).toInt();
|
||||
mAttributeModel->setData( mAttributeModel->index( fieldIndex ), value, QgsQuickAttributeModel::RememberAttribute );
|
||||
item->setData( value, QgsQuickAttributeFormModel::RememberValue );
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsQuickAttributeFormModel::AttributeValue:
|
||||
{
|
||||
QStandardItem *item = itemFromIndex( index );
|
||||
int fieldIndex = item->data( QgsQuickAttributeFormModel::FieldIndex ).toInt();
|
||||
bool changed = mAttributeModel->setData( mAttributeModel->index( fieldIndex ), value, QgsQuickAttributeModel::AttributeValue );
|
||||
if ( changed )
|
||||
{
|
||||
item->setData( value, QgsQuickAttributeFormModel::AttributeValue );
|
||||
emit dataChanged( index, index, QVector<int>() << role );
|
||||
}
|
||||
updateVisibility( fieldIndex );
|
||||
return changed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QgsQuickAttributeModel *QgsQuickAttributeFormModelBase::attributeModel() const
|
||||
{
|
||||
return mAttributeModel;
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::setAttributeModel( QgsQuickAttributeModel *attributeModel )
|
||||
{
|
||||
if ( mAttributeModel == attributeModel )
|
||||
return;
|
||||
|
||||
if ( mAttributeModel )
|
||||
{
|
||||
disconnect( mAttributeModel, &QgsQuickAttributeModel::layerChanged, this, &QgsQuickAttributeFormModelBase::onLayerChanged );
|
||||
disconnect( mAttributeModel, &QgsQuickAttributeModel::featureChanged, this, &QgsQuickAttributeFormModelBase::onFeatureChanged );
|
||||
disconnect( mAttributeModel, &QgsQuickAttributeModel::modelReset, this, &QgsQuickAttributeFormModelBase::onFeatureChanged );
|
||||
}
|
||||
|
||||
mAttributeModel = attributeModel;
|
||||
|
||||
if ( mAttributeModel )
|
||||
{
|
||||
connect( mAttributeModel, &QgsQuickAttributeModel::layerChanged, this, &QgsQuickAttributeFormModelBase::onLayerChanged );
|
||||
connect( mAttributeModel, &QgsQuickAttributeModel::featureChanged, this, &QgsQuickAttributeFormModelBase::onFeatureChanged );
|
||||
connect( mAttributeModel, &QgsQuickAttributeModel::modelReset, this, &QgsQuickAttributeFormModelBase::onFeatureChanged );
|
||||
}
|
||||
|
||||
emit attributeModelChanged();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::onLayerChanged()
|
||||
{
|
||||
clear();
|
||||
|
||||
mLayer = mAttributeModel->featureLayerPair().layer();
|
||||
mVisibilityExpressions.clear();
|
||||
mConstraints.clear();
|
||||
|
||||
if ( mLayer )
|
||||
{
|
||||
QgsAttributeEditorContainer *root;
|
||||
mTemporaryContainer = nullptr;
|
||||
|
||||
if ( mLayer->editFormConfig().layout() == QgsEditFormConfig::TabLayout )
|
||||
{
|
||||
root = mLayer->editFormConfig().invisibleRootContainer();
|
||||
}
|
||||
else
|
||||
{
|
||||
root = generateRootContainer(); //#spellok
|
||||
mTemporaryContainer.reset( root );
|
||||
}
|
||||
|
||||
setHasTabs( !root->children().isEmpty() && QgsAttributeEditorElement::AeTypeContainer == root->children().first()->type() );
|
||||
|
||||
invisibleRootItem()->setColumnCount( 1 );
|
||||
if ( mHasTabs )
|
||||
{
|
||||
for ( QgsAttributeEditorElement *element : root->children() )
|
||||
{
|
||||
if ( element->type() == QgsAttributeEditorElement::AeTypeContainer )
|
||||
{
|
||||
QgsAttributeEditorContainer *container = static_cast<QgsAttributeEditorContainer *>( element );
|
||||
|
||||
QStandardItem *item = new QStandardItem();
|
||||
item->setData( element->name(), QgsQuickAttributeFormModel::Name );
|
||||
item->setData( QStringLiteral( "container" ), QgsQuickAttributeFormModel::ElementType );
|
||||
item->setData( true, QgsQuickAttributeFormModel::CurrentlyVisible );
|
||||
invisibleRootItem()->appendRow( item );
|
||||
|
||||
if ( container->visibilityExpression().enabled() )
|
||||
{
|
||||
mVisibilityExpressions.append( qMakePair( container->visibilityExpression().data(), QVector<QStandardItem *>() << item ) );
|
||||
}
|
||||
|
||||
QVector<QStandardItem *> dummy;
|
||||
flatten( container, item, QString(), dummy );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QVector<QStandardItem *> dummy;
|
||||
flatten( invisibleRootContainer(), invisibleRootItem(), QString(), dummy );
|
||||
}
|
||||
|
||||
mExpressionContext = mLayer->createExpressionContext();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::onFeatureChanged()
|
||||
{
|
||||
for ( int i = 0 ; i < invisibleRootItem()->rowCount(); ++i )
|
||||
{
|
||||
updateAttributeValue( invisibleRootItem()->child( i ) );
|
||||
}
|
||||
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
QgsAttributeEditorContainer *QgsQuickAttributeFormModelBase::generateRootContainer() const //#spellok
|
||||
{
|
||||
QgsAttributeEditorContainer *root = new QgsAttributeEditorContainer( QString(), nullptr );
|
||||
QgsFields fields = mLayer->fields();
|
||||
for ( int i = 0; i < fields.size(); ++i )
|
||||
{
|
||||
if ( fields.at( i ).editorWidgetSetup().type() != QStringLiteral( "Hidden" ) )
|
||||
{
|
||||
QgsAttributeEditorField *field = new QgsAttributeEditorField( fields.at( i ).name(), i, root );
|
||||
root->addChildElement( field );
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
QgsAttributeEditorContainer *QgsQuickAttributeFormModelBase::invisibleRootContainer() const
|
||||
{
|
||||
return mTemporaryContainer ? mTemporaryContainer.get() : mLayer->editFormConfig().invisibleRootContainer();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::updateAttributeValue( QStandardItem *item )
|
||||
{
|
||||
if ( item->data( QgsQuickAttributeFormModel::ElementType ) == QStringLiteral( "field" ) )
|
||||
{
|
||||
item->setData( mAttributeModel->featureLayerPair().feature().attribute( item->data( QgsQuickAttributeFormModel::FieldIndex ).toInt() ), QgsQuickAttributeFormModel::AttributeValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < item->rowCount(); ++i )
|
||||
{
|
||||
updateAttributeValue( item->child( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::flatten( QgsAttributeEditorContainer *container, QStandardItem *parent, const QString &parentVisibilityExpressions, QVector<QStandardItem *> &items )
|
||||
{
|
||||
for ( QgsAttributeEditorElement *element : container->children() )
|
||||
{
|
||||
switch ( element->type() )
|
||||
{
|
||||
case QgsAttributeEditorElement::AeTypeContainer:
|
||||
{
|
||||
QString visibilityExpression = parentVisibilityExpressions;
|
||||
QgsAttributeEditorContainer *container = static_cast<QgsAttributeEditorContainer *>( element );
|
||||
if ( container->visibilityExpression().enabled() )
|
||||
{
|
||||
if ( visibilityExpression.isNull() )
|
||||
visibilityExpression = container->visibilityExpression().data().expression();
|
||||
else
|
||||
visibilityExpression += " AND " + container->visibilityExpression().data().expression();
|
||||
}
|
||||
|
||||
QVector<QStandardItem *> newItems;
|
||||
flatten( container, parent, visibilityExpression, newItems );
|
||||
if ( !visibilityExpression.isEmpty() )
|
||||
mVisibilityExpressions.append( qMakePair( QgsExpression( visibilityExpression ), newItems ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAttributeEditorElement::AeTypeField:
|
||||
{
|
||||
QgsAttributeEditorField *editorField = static_cast<QgsAttributeEditorField *>( element );
|
||||
int fieldIndex = editorField->idx();
|
||||
if ( fieldIndex < 0 || fieldIndex >= mLayer->fields().size() )
|
||||
continue;
|
||||
|
||||
QgsField field = mLayer->fields().at( fieldIndex );
|
||||
|
||||
QStandardItem *item = new QStandardItem();
|
||||
item->setData( mLayer->attributeDisplayName( fieldIndex ), QgsQuickAttributeFormModel::Name );
|
||||
item->setData( mAttributeModel->featureLayerPair().feature().attribute( fieldIndex ), QgsQuickAttributeFormModel::AttributeValue );
|
||||
item->setData( !mLayer->editFormConfig().readOnly( fieldIndex ), QgsQuickAttributeFormModel::AttributeEditable );
|
||||
QgsEditorWidgetSetup setup = mLayer->editorWidgetSetup( fieldIndex );
|
||||
item->setData( setup.type(), QgsQuickAttributeFormModel::EditorWidget );
|
||||
item->setData( setup.config(), QgsQuickAttributeFormModel::EditorWidgetConfig );
|
||||
item->setData( mAttributeModel->rememberedAttributes().at( fieldIndex ) ? Qt::Checked : Qt::Unchecked, QgsQuickAttributeFormModel::RememberValue );
|
||||
item->setData( mLayer->fields().at( fieldIndex ), QgsQuickAttributeFormModel::Field );
|
||||
item->setData( QStringLiteral( "field" ), QgsQuickAttributeFormModel::ElementType );
|
||||
item->setData( fieldIndex, QgsQuickAttributeFormModel::FieldIndex );
|
||||
item->setData( container->isGroupBox() ? container->name() : QString(), QgsQuickAttributeFormModel::Group );
|
||||
item->setData( true, QgsQuickAttributeFormModel::CurrentlyVisible );
|
||||
item->setData( true, QgsQuickAttributeFormModel::ConstraintValid );
|
||||
item->setData( field.constraints().constraintDescription(), QgsQuickAttributeFormModel::ConstraintDescription );
|
||||
|
||||
if ( !field.constraints().constraintExpression().isEmpty() )
|
||||
{
|
||||
mConstraints.insert( item, field.constraints().constraintExpression() );
|
||||
}
|
||||
|
||||
items.append( item );
|
||||
|
||||
parent->appendRow( item );
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsAttributeEditorElement::AeTypeRelation:
|
||||
// todo
|
||||
break;
|
||||
|
||||
case QgsAttributeEditorElement::AeTypeInvalid:
|
||||
// todo
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::updateVisibility( int fieldIndex )
|
||||
{
|
||||
QgsFields fields = mAttributeModel->featureLayerPair().feature().fields();
|
||||
mExpressionContext.setFields( fields );
|
||||
mExpressionContext.setFeature( mAttributeModel->featureLayerPair().feature() );
|
||||
|
||||
for ( const VisibilityExpression &it : mVisibilityExpressions )
|
||||
{
|
||||
if ( fieldIndex == -1 || it.first.referencedAttributeIndexes( fields ).contains( fieldIndex ) )
|
||||
{
|
||||
QgsExpression exp = it.first;
|
||||
exp.prepare( &mExpressionContext );
|
||||
|
||||
bool visible = exp.evaluate( &mExpressionContext ).toInt();
|
||||
for ( QStandardItem *item : it.second )
|
||||
{
|
||||
if ( item->data( QgsQuickAttributeFormModel::CurrentlyVisible ).toBool() != visible )
|
||||
{
|
||||
item->setData( visible, QgsQuickAttributeFormModel::CurrentlyVisible );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool allConstraintsValid = true;
|
||||
QMap<QStandardItem *, QgsExpression>::ConstIterator constraintIterator( mConstraints.constBegin() );
|
||||
for ( ; constraintIterator != mConstraints.constEnd(); ++constraintIterator )
|
||||
{
|
||||
QStandardItem *item = constraintIterator.key();
|
||||
QgsExpression exp = constraintIterator.value();
|
||||
exp.prepare( &mExpressionContext );
|
||||
bool constraintSatisfied = exp.evaluate( &mExpressionContext ).toBool();
|
||||
|
||||
if ( constraintSatisfied != item->data( QgsQuickAttributeFormModel::ConstraintValid ).toBool() )
|
||||
{
|
||||
item->setData( constraintSatisfied, QgsQuickAttributeFormModel::ConstraintValid );
|
||||
}
|
||||
|
||||
if ( !item->data( QgsQuickAttributeFormModel::ConstraintValid ).toBool() )
|
||||
{
|
||||
allConstraintsValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
setConstraintsValid( allConstraintsValid );
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeFormModelBase::constraintsValid() const
|
||||
{
|
||||
return mConstraintsValid;
|
||||
}
|
||||
|
||||
QVariant QgsQuickAttributeFormModelBase::attribute( const QString &name ) const
|
||||
{
|
||||
if ( !mLayer )
|
||||
return QVariant();
|
||||
|
||||
int idx = mLayer->fields().indexOf( name );
|
||||
return mAttributeModel->featureLayerPair().feature().attribute( idx );
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::setConstraintsValid( bool constraintsValid )
|
||||
{
|
||||
if ( constraintsValid == mConstraintsValid )
|
||||
return;
|
||||
|
||||
mConstraintsValid = constraintsValid;
|
||||
emit constraintsValidChanged();
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeFormModelBase::hasTabs() const
|
||||
{
|
||||
return mHasTabs;
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::setHasTabs( bool hasTabs )
|
||||
{
|
||||
if ( hasTabs == mHasTabs )
|
||||
return;
|
||||
|
||||
mHasTabs = hasTabs;
|
||||
emit hasTabsChanged();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::save()
|
||||
{
|
||||
mAttributeModel->save();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeFormModelBase::create()
|
||||
{
|
||||
mAttributeModel->create();
|
||||
}
|
||||
|
||||
/// @endcond
|
132
src/quickgui/attributes/qgsquickattributeformmodelbase.h
Normal file
@ -0,0 +1,132 @@
|
||||
/***************************************************************************
|
||||
qgsquickattributemodelbase.h
|
||||
--------------------------------------
|
||||
Date : 16.8.2016
|
||||
Copyright : (C) 2016 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSQUICKATTRIBUTEFORMMODELBASE_H
|
||||
#define QGSQUICKATTRIBUTEFORMMODELBASE_H
|
||||
|
||||
/// @cond PRIVATE
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the QGIS API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QStack>
|
||||
|
||||
#include "qgseditformconfig.h"
|
||||
#include "qgsexpressioncontext.h"
|
||||
|
||||
#include "qgis_quick.h"
|
||||
#include "qgsquickattributemodel.h"
|
||||
|
||||
class QVariant;
|
||||
|
||||
/**
|
||||
* \ingroup quick
|
||||
* This is an internal (implementation) class used as the source model for QgsQuickAttributeFormModel.
|
||||
*
|
||||
* \sa QgsQuickAttributeFormModel
|
||||
*
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
class QgsQuickAttributeFormModelBase : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
//! Feature model with attributes
|
||||
Q_PROPERTY( QgsQuickAttributeModel *attributeModel READ attributeModel WRITE setAttributeModel NOTIFY attributeModelChanged )
|
||||
|
||||
//! Whether use tabs layout
|
||||
Q_PROPERTY( bool hasTabs READ hasTabs WRITE setHasTabs NOTIFY hasTabsChanged )
|
||||
|
||||
//! Returns true if all constraints defined on fields are satisfied with the current attribute values
|
||||
Q_PROPERTY( bool constraintsValid READ constraintsValid NOTIFY constraintsValidChanged )
|
||||
|
||||
public:
|
||||
//! Constructor
|
||||
explicit QgsQuickAttributeFormModelBase( QObject *parent = nullptr );
|
||||
//! Destructor
|
||||
~QgsQuickAttributeFormModelBase() = default;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModelBase::attributeModel
|
||||
QgsQuickAttributeModel *attributeModel() const;
|
||||
//! \copydoc QgsQuickAttributeFormModelBase::attributeModel
|
||||
void setAttributeModel( QgsQuickAttributeModel *attributeModel );
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModelBase::hasTabs
|
||||
bool hasTabs() const;
|
||||
//! \copydoc QgsQuickAttributeFormModelBase::hasTabs
|
||||
void setHasTabs( bool hasTabs );
|
||||
|
||||
//! Saves changes
|
||||
void save();
|
||||
|
||||
//! Creates a new feature
|
||||
void create();
|
||||
|
||||
//! \copydoc QgsQuickAttributeFormModelBase::constraintsValid
|
||||
bool constraintsValid() const;
|
||||
|
||||
/**
|
||||
* Gets the value of attribute of the feature in the model
|
||||
*
|
||||
* \param name QString name of the wanted attribute
|
||||
*/
|
||||
QVariant attribute( const QString &name ) const;
|
||||
|
||||
signals:
|
||||
//! \copydoc QgsQuickAttributeFormModelBase::attributeModel
|
||||
void attributeModelChanged();
|
||||
//! \copydoc QgsQuickAttributeFormModelBase::hasTabs
|
||||
void hasTabsChanged();
|
||||
//! \copydoc QgsQuickAttributeFormModelBase::constraintsValid
|
||||
void constraintsValidChanged();
|
||||
|
||||
private slots:
|
||||
void onFeatureChanged();
|
||||
void onLayerChanged();
|
||||
|
||||
private:
|
||||
|
||||
QgsAttributeEditorContainer *generateRootContainer() const; //#spellok
|
||||
QgsAttributeEditorContainer *invisibleRootContainer() const;
|
||||
void updateAttributeValue( QStandardItem *item );
|
||||
void flatten( QgsAttributeEditorContainer *container, QStandardItem *parent, const QString &parentVisibilityExpressions, QVector<QStandardItem *> &items );
|
||||
void updateVisibility( int fieldIndex = -1 );
|
||||
void setConstraintsValid( bool constraintsValid );
|
||||
|
||||
QgsQuickAttributeModel *mAttributeModel = nullptr; // not owned
|
||||
QgsVectorLayer *mLayer = nullptr; // not owned
|
||||
std::unique_ptr<QgsAttributeEditorContainer> mTemporaryContainer;
|
||||
bool mHasTabs = false;
|
||||
|
||||
typedef QPair<QgsExpression, QVector<QStandardItem *> > VisibilityExpression;
|
||||
QList<VisibilityExpression> mVisibilityExpressions;
|
||||
QMap<QStandardItem *, QgsExpression> mConstraints;
|
||||
|
||||
QgsExpressionContext mExpressionContext;
|
||||
bool mConstraintsValid = false;
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
#endif // QGSQUICKATTRIBUTEFORMMODELBASE_H
|
327
src/quickgui/attributes/qgsquickattributemodel.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
/***************************************************************************
|
||||
qgsquickattributemodel.cpp
|
||||
--------------------------------------
|
||||
Date : 10.12.2014
|
||||
Copyright : (C) 2014 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgis.h"
|
||||
#include "qgsmessagelog.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
#include "qgsquickattributemodel.h"
|
||||
|
||||
QgsQuickAttributeModel::QgsQuickAttributeModel( QObject *parent )
|
||||
: QAbstractListModel( parent )
|
||||
{
|
||||
connect( this, &QgsQuickAttributeModel::modelReset, this, &QgsQuickAttributeModel::featureLayerPairChanged );
|
||||
connect( this, &QgsQuickAttributeModel::featureChanged, this, &QgsQuickAttributeModel::featureLayerPairChanged );
|
||||
connect( this, &QgsQuickAttributeModel::layerChanged, this, &QgsQuickAttributeModel::featureLayerPairChanged );
|
||||
}
|
||||
|
||||
QgsQuickFeatureLayerPair QgsQuickAttributeModel::featureLayerPair() const
|
||||
{
|
||||
return mFeatureLayerPair;
|
||||
}
|
||||
|
||||
void QgsQuickAttributeModel::setFeatureLayerPair( const QgsQuickFeatureLayerPair &pair )
|
||||
{
|
||||
setVectorLayer( pair.layer() );
|
||||
setFeature( pair.feature() );
|
||||
}
|
||||
|
||||
|
||||
void QgsQuickAttributeModel::setVectorLayer( QgsVectorLayer *layer )
|
||||
{
|
||||
if ( mFeatureLayerPair.layer() == layer )
|
||||
return;
|
||||
|
||||
beginResetModel();
|
||||
mFeatureLayerPair = QgsQuickFeatureLayerPair( mFeatureLayerPair.feature(), layer );
|
||||
|
||||
|
||||
if ( mFeatureLayerPair.layer() )
|
||||
{
|
||||
mRememberedAttributes.resize( mFeatureLayerPair.layer()->fields().size() );
|
||||
mRememberedAttributes.fill( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
mRememberedAttributes.clear();
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
emit layerChanged();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeModel::setFeature( const QgsFeature &feature )
|
||||
{
|
||||
if ( mFeatureLayerPair.feature() == feature )
|
||||
return;
|
||||
|
||||
beginResetModel();
|
||||
mFeatureLayerPair = QgsQuickFeatureLayerPair( feature, mFeatureLayerPair.layer() );
|
||||
endResetModel();
|
||||
|
||||
emit featureChanged();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> QgsQuickAttributeModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
|
||||
roles[AttributeName] = QByteArrayLiteral( "AttributeName" );
|
||||
roles[AttributeValue] = QByteArrayLiteral( "AttributeValue" );
|
||||
roles[Field] = QByteArrayLiteral( "Field" );
|
||||
roles[RememberAttribute] = QByteArrayLiteral( "RememberAttribute" );
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
|
||||
int QgsQuickAttributeModel::rowCount( const QModelIndex &parent ) const
|
||||
{
|
||||
if ( parent.isValid() )
|
||||
return 0;
|
||||
else
|
||||
return mFeatureLayerPair.feature().attributes().count();
|
||||
}
|
||||
|
||||
QVariant QgsQuickAttributeModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
switch ( role )
|
||||
{
|
||||
case AttributeName:
|
||||
return mFeatureLayerPair.layer()->attributeDisplayName( index.row() );
|
||||
break;
|
||||
|
||||
case AttributeValue:
|
||||
return mFeatureLayerPair.feature().attribute( index.row() );
|
||||
break;
|
||||
|
||||
case Field:
|
||||
return mFeatureLayerPair.layer()->fields().at( index.row() );
|
||||
break;
|
||||
|
||||
case RememberAttribute:
|
||||
return mRememberedAttributes.at( index.row() );
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
if ( data( index, role ) == value )
|
||||
return true;
|
||||
|
||||
switch ( role )
|
||||
{
|
||||
case AttributeValue:
|
||||
{
|
||||
QVariant val( value );
|
||||
QgsField fld = mFeatureLayerPair.feature().fields().at( index.row() );
|
||||
|
||||
if ( !fld.convertCompatible( val ) )
|
||||
{
|
||||
QgsMessageLog::logMessage( tr( "Value \"%1\" %4 could not be converted to a compatible value for field %2(%3)." ).arg( value.toString(), fld.name(), fld.typeName(), value.isNull() ? "NULL" : "NOT NULL" ) );
|
||||
return false;
|
||||
}
|
||||
bool success = mFeatureLayerPair.featureRef().setAttribute( index.row(), val );
|
||||
if ( success )
|
||||
emit dataChanged( index, index, QVector<int>() << role );
|
||||
return success;
|
||||
break;
|
||||
}
|
||||
|
||||
case RememberAttribute:
|
||||
{
|
||||
mRememberedAttributes[ index.row() ] = value.toBool();
|
||||
emit dataChanged( index, index, QVector<int>() << role );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeModel::save()
|
||||
{
|
||||
if ( !mFeatureLayerPair.layer() )
|
||||
return false;
|
||||
|
||||
bool rv = true;
|
||||
|
||||
if ( !startEditing() )
|
||||
{
|
||||
rv = false;
|
||||
}
|
||||
|
||||
QgsFeature feat = mFeatureLayerPair.feature();
|
||||
if ( !mFeatureLayerPair.layer()->updateFeature( feat ) )
|
||||
QgsMessageLog::logMessage( tr( "Cannot update feature" ),
|
||||
QStringLiteral( "QgsQuick" ),
|
||||
Qgis::Warning );
|
||||
rv = commit();
|
||||
|
||||
if ( rv )
|
||||
{
|
||||
QgsFeature feat;
|
||||
if ( mFeatureLayerPair.layer()->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureLayerPair.feature().id() ) ).nextFeature( feat ) )
|
||||
setFeature( feat );
|
||||
else
|
||||
QgsMessageLog::logMessage( tr( "Feature %1 could not be fetched after commit" ).arg( mFeatureLayerPair.feature().id() ),
|
||||
QStringLiteral( "QgsQuick" ),
|
||||
Qgis::Warning );
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeModel::deleteFeature()
|
||||
{
|
||||
if ( !mFeatureLayerPair.layer() )
|
||||
return false;
|
||||
|
||||
bool rv = true;
|
||||
|
||||
if ( !startEditing() )
|
||||
{
|
||||
rv = false;
|
||||
}
|
||||
|
||||
if ( !mFeatureLayerPair.layer()->deleteFeature( mFeatureLayerPair.feature().id() ) )
|
||||
QgsMessageLog::logMessage( tr( "Cannot delete feature" ),
|
||||
QStringLiteral( "QgsQuick" ),
|
||||
Qgis::Warning );
|
||||
rv = commit();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void QgsQuickAttributeModel::reset()
|
||||
{
|
||||
if ( !mFeatureLayerPair.layer() )
|
||||
return;
|
||||
|
||||
mFeatureLayerPair.layer()->rollBack();
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeModel::suppressFeatureForm() const
|
||||
{
|
||||
if ( !mFeatureLayerPair.layer() )
|
||||
return false;
|
||||
|
||||
return mFeatureLayerPair.layer()->editFormConfig().suppress();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeModel::resetAttributes()
|
||||
{
|
||||
if ( !mFeatureLayerPair.layer() )
|
||||
return;
|
||||
|
||||
QgsExpressionContext expressionContext = mFeatureLayerPair.layer()->createExpressionContext();
|
||||
expressionContext.setFeature( mFeatureLayerPair.feature() );
|
||||
|
||||
QgsFields fields = mFeatureLayerPair.layer()->fields();
|
||||
|
||||
beginResetModel();
|
||||
for ( int i = 0; i < fields.count(); ++i )
|
||||
{
|
||||
if ( !mRememberedAttributes.at( i ) )
|
||||
{
|
||||
if ( !fields.at( i ).defaultValueDefinition().expression().isEmpty() )
|
||||
{
|
||||
QgsExpression exp( fields.at( i ).defaultValueDefinition().expression() );
|
||||
exp.prepare( &expressionContext );
|
||||
if ( exp.hasParserError() )
|
||||
QgsMessageLog::logMessage( tr( "Default value expression for %1:%2 has parser error: %3" ).arg(
|
||||
mFeatureLayerPair.layer()->name(),
|
||||
fields.at( i ).name(),
|
||||
exp.parserErrorString() ),
|
||||
QStringLiteral( "QgsQuick" ),
|
||||
Qgis::Warning );
|
||||
|
||||
QVariant value = exp.evaluate( &expressionContext );
|
||||
|
||||
if ( exp.hasEvalError() )
|
||||
QgsMessageLog::logMessage( tr( "Default value expression for %1:%2 has evaluation error: %3" ).arg(
|
||||
mFeatureLayerPair.layer()->name(),
|
||||
fields.at( i ).name(),
|
||||
exp.evalErrorString() ),
|
||||
QStringLiteral( "QgsQuick" ),
|
||||
Qgis::Warning );
|
||||
|
||||
mFeatureLayerPair.feature().setAttribute( i, value );
|
||||
}
|
||||
else
|
||||
{
|
||||
mFeatureLayerPair.feature().setAttribute( i, QVariant() );
|
||||
}
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void QgsQuickAttributeModel::create()
|
||||
{
|
||||
if ( !mFeatureLayerPair.layer() )
|
||||
return;
|
||||
|
||||
startEditing();
|
||||
QgsFeature feat = mFeatureLayerPair.feature();
|
||||
if ( !mFeatureLayerPair.layer()->addFeature( feat ) )
|
||||
{
|
||||
QgsMessageLog::logMessage( tr( "Feature could not be added" ),
|
||||
QStringLiteral( "QgsQuick" ),
|
||||
Qgis::Critical );
|
||||
}
|
||||
commit();
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeModel::commit()
|
||||
{
|
||||
if ( !mFeatureLayerPair.layer()->commitChanges() )
|
||||
{
|
||||
QgsMessageLog::logMessage( tr( "Could not save changes. Rolling back." ),
|
||||
QStringLiteral( "QgsQuick" ),
|
||||
Qgis::Critical );
|
||||
mFeatureLayerPair.layer()->rollBack();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsQuickAttributeModel::startEditing()
|
||||
{
|
||||
// Already an edit session active
|
||||
if ( mFeatureLayerPair.layer()->editBuffer() )
|
||||
return true;
|
||||
|
||||
if ( !mFeatureLayerPair.layer()->startEditing() )
|
||||
{
|
||||
QgsMessageLog::logMessage( tr( "Cannot start editing" ),
|
||||
QStringLiteral( "QgsQuick" ),
|
||||
Qgis::Warning );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<bool> QgsQuickAttributeModel::rememberedAttributes() const
|
||||
{
|
||||
return mRememberedAttributes;
|
||||
}
|
153
src/quickgui/attributes/qgsquickattributemodel.h
Normal file
@ -0,0 +1,153 @@
|
||||
/***************************************************************************
|
||||
QgsQuickAttributeModel.h
|
||||
--------------------------------------
|
||||
Date : 10.12.2014
|
||||
Copyright : (C) 2014 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSQUICKATTRIBUTEMODEL_H
|
||||
#define QGSQUICKATTRIBUTEMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QVector>
|
||||
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
#include "qgis_quick.h"
|
||||
#include "qgsquickfeaturelayerpair.h"
|
||||
|
||||
/**
|
||||
* \ingroup quick
|
||||
*
|
||||
* Basic item model for attributes of QgsFeature associated
|
||||
* from feature layer pair. Each attribute of the feature
|
||||
* gets a row in the model. Also supports CRUD operations
|
||||
* related to layer and feature pair.
|
||||
*
|
||||
* On top of the QgsFeature attibutes, support for "remember"
|
||||
* attribute is added. Remember attribute is used for
|
||||
* quick addition of the multiple features to the same layer.
|
||||
* A new feature can use "remembered" attribute values from
|
||||
* the last feature added.
|
||||
*
|
||||
*
|
||||
* \note QML Type: AttributeModel
|
||||
*
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
class QUICK_EXPORT QgsQuickAttributeModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* QgsQuickFeatureLayerPair for the model. Input for attributes model.
|
||||
*/
|
||||
Q_PROPERTY( QgsQuickFeatureLayerPair featureLayerPair READ featureLayerPair WRITE setFeatureLayerPair NOTIFY featureLayerPairChanged )
|
||||
|
||||
/**
|
||||
* Feature roles enum.
|
||||
*/
|
||||
Q_ENUMS( FeatureRoles )
|
||||
|
||||
public:
|
||||
//! Feature roles
|
||||
enum FeatureRoles
|
||||
{
|
||||
AttributeName = Qt::UserRole + 1, //!< Attribute's display name (the original field name or a custom alias)
|
||||
AttributeValue, //!< Value of the feature's attribute
|
||||
Field, //!< Field definition (QgsField)
|
||||
RememberAttribute //!< Remember attribute value for next feature
|
||||
};
|
||||
|
||||
//! Creates a new feature attribute model
|
||||
explicit QgsQuickAttributeModel( QObject *parent = nullptr );
|
||||
|
||||
/**
|
||||
* Creates a new feature attribute model
|
||||
* \param feat Feature set to model
|
||||
* \param parent Parent object.
|
||||
*/
|
||||
explicit QgsQuickAttributeModel( const QgsFeature &feat, QObject *parent = nullptr );
|
||||
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
int rowCount( const QModelIndex &parent ) const override;
|
||||
QVariant data( const QModelIndex &index, int role ) const override;
|
||||
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||
|
||||
/**
|
||||
* Commits the edit buffer of this layer.
|
||||
* May change in the future to only commit the changes buffered in this model.
|
||||
*
|
||||
* @return Success of the operation.
|
||||
*/
|
||||
Q_INVOKABLE bool save();
|
||||
|
||||
/**
|
||||
* Deletes the current feature from the layer and commit the changes.
|
||||
* @return Success of the operation.
|
||||
*/
|
||||
Q_INVOKABLE bool deleteFeature();
|
||||
|
||||
/**
|
||||
* Resets the feature to the original values and dismiss any buffered edits.
|
||||
*/
|
||||
Q_INVOKABLE void reset();
|
||||
|
||||
//! Adds feature from featureLayerPair to the layer
|
||||
Q_INVOKABLE void create();
|
||||
|
||||
/**
|
||||
* Suppress layer's QgsEditFormConfig
|
||||
*
|
||||
* \sa QgsEditFormConfig::suppress
|
||||
*/
|
||||
Q_INVOKABLE bool suppressFeatureForm() const;
|
||||
|
||||
//! Resets remembered attributes
|
||||
Q_INVOKABLE virtual void resetAttributes();
|
||||
|
||||
//! Gets remembered attributes
|
||||
QVector<bool> rememberedAttributes() const;
|
||||
|
||||
//!\copydoc QgsQuickAttributeModel::featureLayerPair
|
||||
QgsQuickFeatureLayerPair featureLayerPair() const;
|
||||
|
||||
//!\copydoc QgsQuickAttributeModel::featureLayerPair
|
||||
void setFeatureLayerPair( const QgsQuickFeatureLayerPair &pair );
|
||||
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
//! Feature or layer changed in feature layer pair
|
||||
void featureLayerPairChanged();
|
||||
|
||||
//! Feature updated, layer is the same
|
||||
void featureChanged();
|
||||
|
||||
//! Layer changed, feature is the same
|
||||
void layerChanged();
|
||||
|
||||
protected:
|
||||
//! Commits model changes
|
||||
bool commit();
|
||||
//! Starts editing model
|
||||
bool startEditing();
|
||||
|
||||
QgsQuickFeatureLayerPair mFeatureLayerPair;
|
||||
QVector<bool> mRememberedAttributes;
|
||||
private:
|
||||
void setFeature( const QgsFeature &feature );
|
||||
void setVectorLayer( QgsVectorLayer *layer );
|
||||
};
|
||||
|
||||
#endif // QGSQUICKATTRIBUTEMODEL_H
|
183
src/quickgui/attributes/qgsquicksubmodel.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/***************************************************************************
|
||||
qgsquicksubmodel.cpp
|
||||
--------------------------------------
|
||||
Date : 16.9.2016
|
||||
Copyright : (C) 2016 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgsquicksubmodel.h"
|
||||
|
||||
QgsQuickSubModel::QgsQuickSubModel( QObject *parent )
|
||||
: QAbstractItemModel( parent )
|
||||
{
|
||||
}
|
||||
|
||||
QModelIndex QgsQuickSubModel::index( int row, int column, const QModelIndex &parent ) const
|
||||
{
|
||||
if ( !mModel )
|
||||
return mRootIndex;
|
||||
|
||||
QModelIndex sourceIndex = mModel->index( row, column, parent.isValid() ? mapToSource( parent ) : static_cast<QModelIndex>( mRootIndex ) );
|
||||
return mapFromSource( sourceIndex );
|
||||
}
|
||||
|
||||
QModelIndex QgsQuickSubModel::parent( const QModelIndex &child ) const
|
||||
{
|
||||
if ( !mModel )
|
||||
return mRootIndex;
|
||||
|
||||
QModelIndex idx = mModel->parent( child );
|
||||
if ( idx == mRootIndex )
|
||||
return QModelIndex();
|
||||
else
|
||||
return mapFromSource( idx );
|
||||
}
|
||||
|
||||
int QgsQuickSubModel::rowCount( const QModelIndex &parent ) const
|
||||
{
|
||||
if ( !mModel )
|
||||
return 0;
|
||||
|
||||
return mModel->rowCount( parent.isValid() ? mapToSource( parent ) : static_cast<QModelIndex>( mRootIndex ) );
|
||||
}
|
||||
|
||||
int QgsQuickSubModel::columnCount( const QModelIndex &parent ) const
|
||||
{
|
||||
if ( !mModel )
|
||||
return 0;
|
||||
|
||||
return mModel->columnCount( parent.isValid() ? mapToSource( parent ) : static_cast<QModelIndex>( mRootIndex ) );
|
||||
}
|
||||
|
||||
QVariant QgsQuickSubModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
if ( !mModel )
|
||||
return QVariant();
|
||||
|
||||
return mModel->data( mapToSource( index ), role );
|
||||
}
|
||||
|
||||
bool QgsQuickSubModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
if ( !mModel )
|
||||
return false;
|
||||
|
||||
return mModel->setData( mapToSource( index ), value, role );
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> QgsQuickSubModel::roleNames() const
|
||||
{
|
||||
if ( !mModel )
|
||||
return QHash<int, QByteArray>();
|
||||
|
||||
return mModel->roleNames();
|
||||
}
|
||||
|
||||
QModelIndex QgsQuickSubModel::rootIndex() const
|
||||
{
|
||||
return mRootIndex;
|
||||
}
|
||||
|
||||
void QgsQuickSubModel::setRootIndex( const QModelIndex &rootIndex )
|
||||
{
|
||||
if ( rootIndex == mRootIndex )
|
||||
return;
|
||||
|
||||
beginResetModel();
|
||||
mRootIndex = rootIndex;
|
||||
endResetModel();
|
||||
emit rootIndexChanged();
|
||||
}
|
||||
|
||||
QAbstractItemModel *QgsQuickSubModel::model() const
|
||||
{
|
||||
return mModel;
|
||||
}
|
||||
|
||||
void QgsQuickSubModel::setModel( QAbstractItemModel *model )
|
||||
{
|
||||
if ( model == mModel )
|
||||
return;
|
||||
|
||||
if ( model )
|
||||
{
|
||||
connect( model, &QAbstractItemModel::rowsAboutToBeInserted, this, &QgsQuickSubModel::onRowsAboutToBeInserted );
|
||||
connect( model, &QAbstractItemModel::rowsInserted, this, &QgsQuickSubModel::onRowsInserted );
|
||||
connect( model, &QAbstractItemModel::rowsAboutToBeRemoved, this, &QgsQuickSubModel::onRowsAboutToBeRemoved );
|
||||
connect( model, &QAbstractItemModel::rowsRemoved, this, &QgsQuickSubModel::onRowsRemoved );
|
||||
connect( model, &QAbstractItemModel::modelAboutToBeReset, this, &QgsQuickSubModel::onModelAboutToBeReset );
|
||||
connect( model, &QAbstractItemModel::modelReset, this, &QAbstractItemModel::modelReset );
|
||||
connect( model, &QAbstractItemModel::dataChanged, this, &QgsQuickSubModel::onDataChanged );
|
||||
}
|
||||
|
||||
mModel = model;
|
||||
emit modelChanged();
|
||||
}
|
||||
|
||||
void QgsQuickSubModel::onRowsAboutToBeInserted( const QModelIndex &parent, int first, int last )
|
||||
{
|
||||
emit beginInsertRows( mapFromSource( parent ), first, last );
|
||||
}
|
||||
|
||||
void QgsQuickSubModel::onRowsInserted( const QModelIndex &parent, int first, int last )
|
||||
{
|
||||
Q_UNUSED( parent )
|
||||
Q_UNUSED( first )
|
||||
Q_UNUSED( last )
|
||||
emit endInsertRows();
|
||||
}
|
||||
|
||||
void QgsQuickSubModel::onRowsAboutToBeRemoved( const QModelIndex &parent, int first, int last )
|
||||
{
|
||||
emit beginRemoveRows( mapFromSource( parent ), first, last );
|
||||
}
|
||||
|
||||
void QgsQuickSubModel::onRowsRemoved( const QModelIndex &parent, int first, int last )
|
||||
{
|
||||
Q_UNUSED( parent )
|
||||
Q_UNUSED( first )
|
||||
Q_UNUSED( last )
|
||||
emit endRemoveRows();
|
||||
}
|
||||
|
||||
void QgsQuickSubModel::onModelAboutToBeReset()
|
||||
{
|
||||
mMappings.clear();
|
||||
}
|
||||
|
||||
void QgsQuickSubModel::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
|
||||
{
|
||||
emit dataChanged( mapFromSource( topLeft ), mapFromSource( bottomRight ), roles );
|
||||
}
|
||||
|
||||
QModelIndex QgsQuickSubModel::mapFromSource( const QModelIndex &sourceIndex ) const
|
||||
{
|
||||
if ( sourceIndex == mRootIndex || !sourceIndex.isValid() )
|
||||
return QModelIndex();
|
||||
|
||||
if ( !mMappings.contains( sourceIndex.internalId() ) )
|
||||
{
|
||||
mMappings.insert( sourceIndex.internalId(), sourceIndex.parent() );
|
||||
}
|
||||
|
||||
return createIndex( sourceIndex.row(), sourceIndex.column(), sourceIndex.internalId() );
|
||||
}
|
||||
|
||||
QModelIndex QgsQuickSubModel::mapToSource( const QModelIndex &index ) const
|
||||
{
|
||||
if ( !index.isValid() )
|
||||
return mRootIndex;
|
||||
|
||||
if ( !mModel )
|
||||
return mRootIndex;
|
||||
|
||||
return mModel->index( index.row(), index.column(), mMappings.find( index.internalId() ).value() );
|
||||
}
|
93
src/quickgui/attributes/qgsquicksubmodel.h
Normal file
@ -0,0 +1,93 @@
|
||||
/***************************************************************************
|
||||
qgsquicksubmodel.h
|
||||
--------------------------------------
|
||||
Date : 16.9.2016
|
||||
Copyright : (C) 2016 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSQUICKSUBMODEL_H
|
||||
#define QGSQUICKSUBMODEL_H
|
||||
|
||||
#include "qgis_quick.h"
|
||||
#include "qgsquickattributeformmodel.h"
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
/**
|
||||
* \ingroup quick
|
||||
*
|
||||
* Helper class for submodels (e.g. tabs within feature model).
|
||||
*
|
||||
* It uses internal mapping from internal indexes to indexes in the parent model.
|
||||
*
|
||||
* \note QML Type: SubModel
|
||||
*
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
class QUICK_EXPORT QgsQuickSubModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
//! Parent model (e.g QgsQuickAttributeFormModel)
|
||||
Q_PROPERTY( QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged )
|
||||
|
||||
//! Root index of parent model
|
||||
Q_PROPERTY( QModelIndex rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged )
|
||||
|
||||
public:
|
||||
//! Creates new sub model
|
||||
QgsQuickSubModel( QObject *parent = nullptr );
|
||||
|
||||
QModelIndex index( int row, int column, const QModelIndex &parent ) const override;
|
||||
QModelIndex parent( const QModelIndex &child ) const override;
|
||||
int rowCount( const QModelIndex &parent ) const override;
|
||||
int columnCount( const QModelIndex &parent ) const override;
|
||||
QVariant data( const QModelIndex &index, int role ) const override;
|
||||
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
//! \copydoc QgsQuickSubModel::model
|
||||
QAbstractItemModel *model() const;
|
||||
|
||||
//! \copydoc QgsQuickSubModel::model
|
||||
void setModel( QAbstractItemModel *model );
|
||||
|
||||
//! \copydoc QgsQuickSubModel::rootIndex
|
||||
QModelIndex rootIndex() const;
|
||||
|
||||
//! \copydoc QgsQuickSubModel::rootIndex
|
||||
void setRootIndex( const QModelIndex &rootIndex );
|
||||
|
||||
signals:
|
||||
//! \copydoc QgsQuickSubModel::model
|
||||
void modelChanged();
|
||||
|
||||
//! \copydoc QgsQuickSubModel::rootIndex
|
||||
void rootIndexChanged();
|
||||
|
||||
private slots:
|
||||
void onRowsAboutToBeInserted( const QModelIndex &parent, int first, int last );
|
||||
void onRowsInserted( const QModelIndex &parent, int first, int last );
|
||||
void onRowsAboutToBeRemoved( const QModelIndex &parent, int first, int last );
|
||||
void onRowsRemoved( const QModelIndex &parent, int first, int last );
|
||||
void onModelAboutToBeReset();
|
||||
void onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>() );
|
||||
|
||||
private:
|
||||
QModelIndex mapFromSource( const QModelIndex &sourceIndex ) const;
|
||||
QModelIndex mapToSource( const QModelIndex &index ) const;
|
||||
|
||||
QAbstractItemModel *mModel = nullptr; // not owned
|
||||
QPersistentModelIndex mRootIndex;
|
||||
|
||||
// Map internal id to parent index
|
||||
mutable QHash<qintptr, QModelIndex> mMappings;
|
||||
};
|
||||
|
||||
#endif // QGSQUICKSUBMODEL_H
|
5
src/quickgui/images/ic_broken_image_black.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0h24v24H0zm0 0h24v24H0zm21 19c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2" fill="none"/>
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M21 5v6.59l-3-3.01-4 4.01-4-4-4 4-3-3.01V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2zm-3 6.42l3 3.01V19c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2v-6.58l3 2.99 4-4 4 4 4-3.99z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 447 B |
71
src/quickgui/images/ic_camera_alt_border.svg
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="ic_camera_alt_border_24dp.svg">
|
||||
<metadata
|
||||
id="metadata14">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
id="namedview10"
|
||||
showgrid="true"
|
||||
showguides="false"
|
||||
inkscape:zoom="19.666667"
|
||||
inkscape:cx="11.698998"
|
||||
inkscape:cy="13.796445"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 8.4,0 -2.196,2.4444444 -3.804,0 c -1.32,0 -2.4,1.1 -2.4,2.4444444 L 0,19.555556 C 0,20.9 1.08,22 2.4,22 l 19.2,0 C 22.92,22 24,20.9 24,19.555556 L 24,4.8888888 C 24,3.5444444 22.92,2.4444444 21.6,2.4444444 l -3.804,0 L 15.6,0 Z"
|
||||
id="path6-7"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
sodipodi:nodetypes="ccssssssssccc" />
|
||||
<circle
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="3.2"
|
||||
id="circle4" />
|
||||
<path
|
||||
d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"
|
||||
id="path6"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter-blend-mode:normal;filter-gaussianBlur-deviation:0;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<path
|
||||
d="M0 0h24v24H0z"
|
||||
fill="none"
|
||||
id="path8" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
4
src/quickgui/images/ic_check_black.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 213 B |
4
src/quickgui/images/ic_clear_black.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
</svg>
|
After Width: | Height: | Size: 265 B |
4
src/quickgui/images/ic_clear_white.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
</svg>
|
After Width: | Height: | Size: 265 B |
5
src/quickgui/images/ic_delete_forever_white.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0h24v24H0V0z" fill="none"/>
|
||||
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/>
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
</svg>
|
After Width: | Height: | Size: 411 B |
66
src/quickgui/images/ic_photo_notavailable_white.svg
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 48 48"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="ic_photo_notavailable_white_48dp.svg">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1321"
|
||||
inkscape:window-height="729"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.7383042"
|
||||
inkscape:cx="34.371391"
|
||||
inkscape:cy="-23.586747"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
d="M0 0h48v48H0z"
|
||||
fill="none"
|
||||
id="path4" />
|
||||
<path
|
||||
d="M 36.449219 42 L 30.449219 36 L 10 36 L 17 27 L 22 33.009766 L 24.386719 29.9375 L 6 11.550781 L 6 38 C 6 40.21 7.79 42 10 42 L 36.449219 42 z "
|
||||
id="path4149" />
|
||||
<path
|
||||
d="M 42 37.449219 L 42 10 C 42 7.79 40.21 6 38 6 L 10.550781 6 L 28.802734 24.251953 L 29 24 L 30.347656 25.796875 L 42 37.449219 z "
|
||||
id="path4184" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 5,10.55 37.450002,43 l 2.55,-2.55 L 7.55,8.0000004 Z"
|
||||
id="path6-3"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
4
src/quickgui/images/ic_save_white.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg fill="#FFFFFF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 306 B |
@ -1,5 +1,13 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>ic_broken_image_black.svg</file>
|
||||
<file>ic_camera_alt_border.svg</file>
|
||||
<file>ic_check_black.svg</file>
|
||||
<file>ic_clear_black.svg</file>
|
||||
<file>ic_clear_white.svg</file>
|
||||
<file>ic_delete_forever_white.svg</file>
|
||||
<file>ic_navigation_black.svg</file>
|
||||
<file>ic_photo_notavailable_white.svg</file>
|
||||
<file>ic_save_white.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -10,8 +10,16 @@ SET(QGIS_QUICK_PLUGIN_SRC
|
||||
)
|
||||
|
||||
SET(QGIS_QUICK_PLUGIN_RESOURCES
|
||||
editor/qgsquickcheckbox.qml
|
||||
editor/qgsquickdatetime.qml
|
||||
editor/qgsquickexternalresource.qml
|
||||
editor/qgsquicktextedit.qml
|
||||
editor/qgsquickvaluemap.qml
|
||||
qgsquickfeatureform.qml
|
||||
qgsquickfeatureformstyling.qml
|
||||
qgsquickmapcanvas.qml
|
||||
qgsquickmessagelog.qml
|
||||
qgsquickphotopanel.qml
|
||||
qgsquickpositionmarker.qml
|
||||
qgsquickscalebar.qml
|
||||
qmldir
|
||||
|
49
src/quickgui/plugin/editor/qgsquickcheckbox.qml
Normal file
@ -0,0 +1,49 @@
|
||||
/***************************************************************************
|
||||
qgsquickcheckbox.qml
|
||||
--------------------------------------
|
||||
Date : 2017
|
||||
Copyright : (C) 2017 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QgisQuick 0.1 as QgsQuick
|
||||
|
||||
/**
|
||||
* Checkbox for QGIS Attribute Form
|
||||
* Requires various global properties set to function, see qgsquickfeatureform Loader section
|
||||
* Do not use directly from Application QML
|
||||
*/
|
||||
Item {
|
||||
signal valueChanged( var value, bool isNull )
|
||||
|
||||
height: childrenRect.height
|
||||
anchors {
|
||||
right: parent.right
|
||||
left: parent.left
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
property var currentValue: value
|
||||
|
||||
checked: value == config['CheckedState']
|
||||
|
||||
onCheckedChanged: {
|
||||
valueChanged( checked ? config['CheckedState'] : config['UncheckedState'], false )
|
||||
forceActiveFocus()
|
||||
}
|
||||
|
||||
// Workaround to get a signal when the value has changed
|
||||
onCurrentValueChanged: {
|
||||
checked = currentValue == config['CheckedState']
|
||||
}
|
||||
}
|
||||
}
|
125
src/quickgui/plugin/editor/qgsquickdatetime.qml
Normal file
@ -0,0 +1,125 @@
|
||||
/***************************************************************************
|
||||
qgsquickdatetime.qml
|
||||
--------------------------------------
|
||||
Date : 2017
|
||||
Copyright : (C) 2017 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 1.4 as Controls1
|
||||
import QgsQuick 0.1 as QgsQuick
|
||||
|
||||
/**
|
||||
* Calendar for QGIS Attribute Form
|
||||
* Requires various global properties set to function, see qgsquickfeatureform Loader section
|
||||
* Do not use directly from Application QML
|
||||
*/
|
||||
Item {
|
||||
signal valueChanged(var value, bool isNull)
|
||||
|
||||
height: childrenRect.height
|
||||
anchors { right: parent.right; left: parent.left }
|
||||
|
||||
ColumnLayout {
|
||||
id: main
|
||||
property var currentValue: value
|
||||
|
||||
anchors { right: parent.right; left: parent.left }
|
||||
|
||||
Item {
|
||||
anchors { right: parent.right; left: parent.left }
|
||||
Layout.minimumHeight: 48 * QgsQuick.Utils.dp
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
id: backgroundRect
|
||||
border.color: "#17a81a"
|
||||
border.width: 2
|
||||
color: "#dddddd"
|
||||
radius: 2
|
||||
}
|
||||
|
||||
Label {
|
||||
id: label
|
||||
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
popup.open()
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
source: QgsQuick.Utils.getThemeIcon("ic_clear_black")
|
||||
anchors.left: parent.right
|
||||
visible: main.currentValue !== undefined && config['allow_null']
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
main.currentValue = undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Popup {
|
||||
id: popup
|
||||
modal: true
|
||||
focus: true
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
parent: ApplicationWindow.overlay
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
Controls1.Calendar {
|
||||
id: calendar
|
||||
selectedDate: main.currentValue
|
||||
weekNumbersVisible: true
|
||||
focus: false
|
||||
|
||||
onSelectedDateChanged: {
|
||||
main.currentValue = selectedDate
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Button {
|
||||
text: qsTr( "Ok" )
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: popup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentValueChanged: {
|
||||
valueChanged(currentValue, main.currentValue === undefined)
|
||||
if (main.currentValue === undefined)
|
||||
{
|
||||
label.text = qsTr('(no date)')
|
||||
label.color = 'gray'
|
||||
}
|
||||
else
|
||||
{
|
||||
label.color = 'black'
|
||||
label.text = new Date(value).toLocaleString(Qt.locale(), config['display_format'] )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
85
src/quickgui/plugin/editor/qgsquickexternalresource.qml
Normal file
@ -0,0 +1,85 @@
|
||||
/***************************************************************************
|
||||
qgsquickexternalresource.qml
|
||||
--------------------------------------
|
||||
Date : 2017
|
||||
Copyright : (C) 2017 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 2.0
|
||||
import QgsQuick 0.1 as QgsQuick
|
||||
|
||||
/**
|
||||
* External Resource (Photo capture) for QGIS Attribute Form
|
||||
* Requires various global properties set to function, see qgsquickfeatureform Loader section
|
||||
* Do not use directly from Application QML
|
||||
*/
|
||||
Item {
|
||||
signal valueChanged(var value, bool isNull)
|
||||
|
||||
property var image: image
|
||||
|
||||
id: fieldItem
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
height: Math.max(image.height, button.height)
|
||||
|
||||
QgsQuick.PhotoCapture {
|
||||
id: photoCapturePanel
|
||||
visible: false
|
||||
height: window.height
|
||||
width: window.width
|
||||
edge: Qt.RightEdge
|
||||
}
|
||||
|
||||
Image {
|
||||
property var currentValue: value
|
||||
|
||||
id: image
|
||||
width: 200 * QgsQuick.Utils.dp
|
||||
autoTransform: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
Component.onCompleted: image.source = getSource()
|
||||
|
||||
function getSource() {
|
||||
if (image.status === Image.Error)
|
||||
return QgsQuick.Utils.getThemeIcon("ic_broken_image_black")
|
||||
else if (image.currentValue && QgsQuick.Utils.fileExists(homePath + "/" + image.currentValue))
|
||||
return homePath + "/" + image.currentValue
|
||||
else
|
||||
return QgsQuick.Utils.getThemeIcon("ic_photo_notavailable_white")
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button
|
||||
visible: fieldItem.enabled
|
||||
width: 45 * QgsQuick.Utils.dp
|
||||
height: 45 * QgsQuick.Utils.dp
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
onClicked: {
|
||||
photoCapturePanel.visible = true
|
||||
photoCapturePanel.targetDir = homePath
|
||||
photoCapturePanel.fieldItem = fieldItem
|
||||
}
|
||||
|
||||
background: Image {
|
||||
source: QgsQuick.Utils.getThemeIcon("ic_camera_alt_border")
|
||||
width: button.width
|
||||
height: button.height
|
||||
}
|
||||
}
|
||||
}
|
88
src/quickgui/plugin/editor/qgsquicktextedit.qml
Normal file
@ -0,0 +1,88 @@
|
||||
/***************************************************************************
|
||||
qgsquicktextedit.qml
|
||||
--------------------------------------
|
||||
Date : 2017
|
||||
Copyright : (C) 2017 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick 2.5
|
||||
import QgsQuick 0.1 as QgsQuick
|
||||
|
||||
/**
|
||||
* Text Edit for QGIS Attribute Form
|
||||
* Requires various global properties set to function, see qgsquickfeatureform Loader section
|
||||
* Do not use directly from Application QML
|
||||
*/
|
||||
Item {
|
||||
signal valueChanged(var value, bool isNull)
|
||||
|
||||
height: childrenRect.height
|
||||
|
||||
TextField {
|
||||
id: textField
|
||||
height: textArea.height == 0 ? fontMetrics.height + 20 * QgsQuick.Utils.dp : 0
|
||||
topPadding: 10 * QgsQuick.Utils.dp
|
||||
bottomPadding: 10 * QgsQuick.Utils.dp
|
||||
visible: height !== 0
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
font.pointSize: 14 * QgsQuick.Utils.dp
|
||||
|
||||
text: value || ''
|
||||
|
||||
inputMethodHints: field.isNumeric || widget == 'Range' ? field.precision === 0 ? Qt.ImhDigitsOnly : Qt.ImhFormattedNumbersOnly : Qt.ImhNone
|
||||
|
||||
// Make sure we do not input more characters than allowed for strings
|
||||
states: [
|
||||
State {
|
||||
name: "limitedTextLengthState"
|
||||
when: (!field.isNumeric) && (field.length > 0)
|
||||
PropertyChanges {
|
||||
target: textField
|
||||
maximumLength: field.length
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
background: Rectangle {
|
||||
y: textField.height - height - textField.bottomPadding / 2
|
||||
implicitWidth: 120 * QgsQuick.Utils.dp
|
||||
height: textField.activeFocus ? 2 * QgsQuick.Utils.dp : 1 * QgsQuick.Utils.dp
|
||||
color: textField.activeFocus ? "#4CAF50" : "#C8E6C9"
|
||||
}
|
||||
|
||||
onTextChanged: {
|
||||
valueChanged( text, text == '' )
|
||||
}
|
||||
}
|
||||
|
||||
TextArea {
|
||||
id: textArea
|
||||
height: config['IsMultiline'] === true ? undefined : 0
|
||||
visible: height !== 0
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
text: value || ''
|
||||
textFormat: config['UseHtml'] ? TextEdit.RichText : TextEdit.PlainText
|
||||
|
||||
onEditingFinished: {
|
||||
valueChanged( text, text == '' )
|
||||
}
|
||||
}
|
||||
|
||||
FontMetrics {
|
||||
id: fontMetrics
|
||||
font: textField.font
|
||||
}
|
||||
}
|
109
src/quickgui/plugin/editor/qgsquickvaluemap.qml
Normal file
@ -0,0 +1,109 @@
|
||||
/***************************************************************************
|
||||
qgsquickvaluemap.qml
|
||||
--------------------------------------
|
||||
Date : 2017
|
||||
Copyright : (C) 2017 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QtGraphicalEffects 1.0
|
||||
import QgsQuick 0.1 as QgsQuick
|
||||
|
||||
/**
|
||||
* Value Map for QGIS Attribute Form
|
||||
* Requires various global properties set to function, see qgsquickfeatureform Loader section
|
||||
* Do not use directly from Application QML
|
||||
*/
|
||||
Item {
|
||||
signal valueChanged(var value, bool isNull)
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
rightMargin: 10 * QgsQuick.Utils.dp
|
||||
}
|
||||
|
||||
height: childrenRect.height + 10 * QgsQuick.Utils.dp
|
||||
|
||||
ComboBox {
|
||||
id: comboBox
|
||||
|
||||
property var reverseConfig: ({})
|
||||
property var currentValue: value
|
||||
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
|
||||
currentIndex: find(reverseConfig[value])
|
||||
|
||||
Component.onCompleted: {
|
||||
model = Object.keys(config['map']);
|
||||
for(var key in config['map']) {
|
||||
reverseConfig[config['map'][key]] = key;
|
||||
}
|
||||
currentIndex = find(reverseConfig[value])
|
||||
}
|
||||
|
||||
onCurrentTextChanged: {
|
||||
valueChanged(config['map'][currentText], false)
|
||||
}
|
||||
|
||||
// Workaround to get a signal when the value has changed
|
||||
onCurrentValueChanged: {
|
||||
currentIndex = find(reverseConfig[value])
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
propagateComposedEvents: true
|
||||
|
||||
onClicked: mouse.accepted = false
|
||||
onPressed: { forceActiveFocus(); mouse.accepted = false; }
|
||||
onReleased: mouse.accepted = false;
|
||||
onDoubleClicked: mouse.accepted = false;
|
||||
onPositionChanged: mouse.accepted = false;
|
||||
onPressAndHold: mouse.accepted = false;
|
||||
}
|
||||
|
||||
// [hidpi fixes]
|
||||
delegate: ItemDelegate {
|
||||
width: comboBox.width
|
||||
height: 36 * QgsQuick.Utils.dp
|
||||
text: modelData
|
||||
font.weight: comboBox.currentIndex === index ? Font.DemiBold : Font.Normal
|
||||
font.pointSize: 12 * QgsQuick.Utils.dp
|
||||
highlighted: comboBox.highlightedIndex == index
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
height: 36 * QgsQuick.Utils.dp
|
||||
text: comboBox.displayText
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
background: Item {
|
||||
implicitWidth: 120 * QgsQuick.Utils.dp
|
||||
implicitHeight: 36 * QgsQuick.Utils.dp
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
id: backgroundRect
|
||||
border.color: comboBox.pressed ? "#17a81a" : "#21be2b"
|
||||
border.width: comboBox.visualFocus ? 2 : 1
|
||||
color: "#dddddd"
|
||||
radius: 2
|
||||
}
|
||||
}
|
||||
// [/hidpi fixes]
|
||||
}
|
||||
}
|
487
src/quickgui/plugin/qgsquickfeatureform.qml
Normal file
@ -0,0 +1,487 @@
|
||||
/***************************************************************************
|
||||
qgsquickfeatureform.qml
|
||||
--------------------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 by Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Controls 2.0
|
||||
import QtQuick.Dialogs 1.2
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQml.Models 2.2
|
||||
import QtQml 2.2
|
||||
|
||||
// We use calendar in datetime widget that is not yet implemented in Controls 2.2
|
||||
import QtQuick.Controls 1.4 as Controls1
|
||||
|
||||
import QgsQuick 0.1 as QgsQuick
|
||||
|
||||
Item {
|
||||
/**
|
||||
* When feature in the form is saved.
|
||||
*/
|
||||
signal saved
|
||||
/**
|
||||
* When the form is about to be closed by closeButton or deleting a feature.
|
||||
*/
|
||||
signal canceled
|
||||
|
||||
/**
|
||||
* AttributeFormModel binded on a feature supporting auto-generated editor layouts and "tab" layout.
|
||||
*/
|
||||
property QgsQuick.AttributeFormModel model
|
||||
|
||||
/**
|
||||
* Visibility of toolbar.
|
||||
*/
|
||||
property alias toolbarVisible: toolbar.visible
|
||||
|
||||
/**
|
||||
* When adding a new feature, add checkbox to be able to save the same value for the next feature as default.
|
||||
*/
|
||||
property bool allowRememberAttribute: false
|
||||
|
||||
/**
|
||||
* Active project.
|
||||
*/
|
||||
property QgsQuick.Project project
|
||||
|
||||
/**
|
||||
* The function used for a component loader to find qml edit widget componets used in form.
|
||||
*/
|
||||
property var loadWidgetFn: QgsQuick.Utils.getEditorComponentSource
|
||||
|
||||
/**
|
||||
* Icon path for save button.
|
||||
*/
|
||||
property string saveButtonIcon: QgsQuick.Utils.getThemeIcon( "ic_save_white" )
|
||||
/**
|
||||
* Icon path for delete button.
|
||||
*/
|
||||
property string deleteButtonIcon: QgsQuick.Utils.getThemeIcon( "ic_delete_forever_white" )
|
||||
/**
|
||||
* Icon path for close button
|
||||
*/
|
||||
property string closeButtonIcon: QgsQuick.Utils.getThemeIcon( "ic_clear_white" )
|
||||
|
||||
/**
|
||||
* Predefined form styling
|
||||
*/
|
||||
property FeatureFormStyling style: FeatureFormStyling {}
|
||||
|
||||
id: form
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "ReadOnly"
|
||||
},
|
||||
State {
|
||||
name: "Edit"
|
||||
},
|
||||
State {
|
||||
name: "Add"
|
||||
}
|
||||
]
|
||||
|
||||
function reset() {
|
||||
master.reset()
|
||||
}
|
||||
|
||||
function save() {
|
||||
parent.focus = true
|
||||
if ( form.state === "Add" ) {
|
||||
model.create()
|
||||
state = "Edit"
|
||||
}
|
||||
else
|
||||
{
|
||||
model.save()
|
||||
}
|
||||
|
||||
saved()
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a relay to forward private signals to internal components.
|
||||
*/
|
||||
QtObject {
|
||||
id: master
|
||||
|
||||
/**
|
||||
* This signal is emitted whenever the state of Flickables and TabBars should
|
||||
* be restored.
|
||||
*/
|
||||
signal reset
|
||||
}
|
||||
|
||||
Item {
|
||||
id: container
|
||||
|
||||
clip: true
|
||||
|
||||
anchors {
|
||||
top: toolbar.bottom
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flickable
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
height: tabRow.height
|
||||
|
||||
flickableDirection: Flickable.HorizontalFlick
|
||||
contentWidth: tabRow.width
|
||||
|
||||
// Tabs
|
||||
TabBar {
|
||||
id: tabRow
|
||||
visible: model.hasTabs
|
||||
height: form.style.tabs.height
|
||||
|
||||
Connections {
|
||||
target: master
|
||||
onReset: tabRow.currentIndex = 0
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: swipeView
|
||||
onCurrentIndexChanged: tabRow.currentIndex = swipeView.currentIndex
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: form.model
|
||||
|
||||
TabButton {
|
||||
id: tabButton
|
||||
text: Name
|
||||
leftPadding: 8 * QgsQuick.Utils.dp
|
||||
rightPadding: 8 * QgsQuick.Utils.dp
|
||||
|
||||
width: contentItem.width + leftPadding + rightPadding
|
||||
height: form.style.tabs.height
|
||||
|
||||
contentItem: Text {
|
||||
// Make sure the width is derived from the text so we can get wider
|
||||
// than the parent item and the Flickable is useful
|
||||
width: paintedWidth
|
||||
text: tabButton.text
|
||||
color: !tabButton.enabled ? form.style.tabs.disabledColor : tabButton.down ||
|
||||
tabButton.checked ? form.style.tabs.activeColor : form.style.tabs.normalColor
|
||||
font.weight: tabButton.checked ? Font.DemiBold : Font.Normal
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SwipeView {
|
||||
id: swipeView
|
||||
currentIndex: tabRow.currentIndex
|
||||
anchors {
|
||||
top: flickable.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
Repeater {
|
||||
/**
|
||||
* One page per tab in tabbed forms, 1 page in auto forms
|
||||
*/
|
||||
model: form.model.hasTabs ? form.model : 1
|
||||
|
||||
Item {
|
||||
id: formPage
|
||||
property int currentIndex: index
|
||||
|
||||
/**
|
||||
* The main form content area
|
||||
*/
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: form.style.backgroundColor
|
||||
opacity: form.style.backgroundOpacity
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: content
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
section.property: "Group"
|
||||
section.labelPositioning: ViewSection.CurrentLabelAtStart | ViewSection.InlineLabels
|
||||
section.delegate: Component {
|
||||
// section header: group box name
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: section === "" ? 0 : form.style.group.height
|
||||
color: form.style.group.backgroundColor
|
||||
|
||||
Text {
|
||||
anchors { horizontalCenter: parent.horizontalCenter; verticalCenter: parent.verticalCenter }
|
||||
font.bold: true
|
||||
text: section
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: master
|
||||
onReset: content.contentY = 0
|
||||
}
|
||||
|
||||
model: QgsQuick.SubModel {
|
||||
id: contentModel
|
||||
model: form.model
|
||||
rootIndex: form.model.hasTabs ? form.model.index(currentIndex, 0) : undefined
|
||||
}
|
||||
|
||||
delegate: fieldItem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A field editor
|
||||
*/
|
||||
Component {
|
||||
id: fieldItem
|
||||
|
||||
Item {
|
||||
id: fieldContainer
|
||||
visible: Type === 'field'
|
||||
height: childrenRect.height
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
leftMargin: 12 * QgsQuick.Utils.dp
|
||||
}
|
||||
|
||||
Label {
|
||||
id: fieldLabel
|
||||
|
||||
text: qsTr(Name) || ''
|
||||
font.bold: true
|
||||
color: ConstraintValid ? form.style.constraint.validColor : form.style.constraint.invalidColor
|
||||
}
|
||||
|
||||
Label {
|
||||
id: constraintDescriptionLabel
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: fieldLabel.bottom
|
||||
}
|
||||
|
||||
text: qsTr(ConstraintDescription)
|
||||
height: ConstraintValid ? 0 : undefined
|
||||
visible: !ConstraintValid
|
||||
|
||||
color: form.style.constraint.descriptionColor
|
||||
}
|
||||
|
||||
Item {
|
||||
id: placeholder
|
||||
height: childrenRect.height
|
||||
anchors { left: parent.left; right: rememberCheckbox.left; top: constraintDescriptionLabel.bottom }
|
||||
|
||||
Loader {
|
||||
id: attributeEditorLoader
|
||||
|
||||
height: childrenRect.height
|
||||
anchors { left: parent.left; right: parent.right }
|
||||
|
||||
enabled: form.state !== "ReadOnly" && !!AttributeEditable
|
||||
|
||||
property var value: AttributeValue
|
||||
property var config: EditorWidgetConfig
|
||||
property var widget: EditorWidget
|
||||
property var field: Field
|
||||
property var constraintValid: ConstraintValid
|
||||
property var homePath: form.project ? form.project.homePath : ""
|
||||
|
||||
active: widget !== 'Hidden'
|
||||
|
||||
source: form.loadWidgetFn(widget.toLowerCase())
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: attributeEditorLoader.item
|
||||
onValueChanged: {
|
||||
AttributeValue = isNull ? undefined : value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: rememberCheckbox
|
||||
checked: RememberValue ? true : false
|
||||
|
||||
visible: form.allowRememberAttribute && form.state === "Add" && EditorWidget !== "Hidden"
|
||||
width: visible ? undefined : 0
|
||||
|
||||
anchors { right: parent.right; top: fieldLabel.bottom }
|
||||
|
||||
onCheckedChanged: {
|
||||
RememberValue = checked
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Qt.inputMethod
|
||||
onVisibleChanged: {
|
||||
Qt.inputMethod.commit()
|
||||
}
|
||||
}
|
||||
|
||||
/** The form toolbar **/
|
||||
Item {
|
||||
id: toolbar
|
||||
height: visible ? 48 * QgsQuick.Utils.dp : 0
|
||||
visible: form.state === 'Add'
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
Layout.margins: 0
|
||||
|
||||
ToolButton {
|
||||
id: saveButton
|
||||
Layout.preferredWidth: form.style.toolbutton.size
|
||||
Layout.preferredHeight: form.style.toolbutton.size
|
||||
|
||||
visible: form.state !== "ReadOnly"
|
||||
|
||||
contentItem: Image {
|
||||
source: form.saveButtonIcon
|
||||
sourceSize: Qt.size(width, height)
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: model.constraintsValid ? form.style.toolbutton.backgroundColor : form.style.toolbutton.backgroundColorInvalid
|
||||
}
|
||||
|
||||
enabled: model.constraintsValid
|
||||
|
||||
onClicked: {
|
||||
form.save()
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: deleteButton
|
||||
|
||||
Layout.preferredWidth: form.style.toolbutton.size
|
||||
Layout.preferredHeight: form.style.toolbutton.size
|
||||
|
||||
visible: form.state === "Edit"
|
||||
|
||||
contentItem: Image {
|
||||
source: form.deleteButtonIcon
|
||||
sourceSize: Qt.size(width, height)
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: form.style.toolbutton.backgroundColor
|
||||
}
|
||||
|
||||
onClicked: deleteDialog.visible = true
|
||||
}
|
||||
|
||||
Label {
|
||||
id: titleLabel
|
||||
|
||||
text:
|
||||
{
|
||||
var currentLayer = model.attributeModel.featureLayerPair.layer
|
||||
var layerName = 'N/A'
|
||||
if (!!currentLayer)
|
||||
layerName = currentLayer.name
|
||||
|
||||
if ( form.state === 'Add' )
|
||||
qsTr( 'Add feature on <i>%1</i>' ).arg(layerName )
|
||||
else if ( form.state === 'Edit' )
|
||||
qsTr( 'Edit feature on <i>%1</i>' ).arg(layerName)
|
||||
else
|
||||
qsTr( 'View feature on <i>%1</i>' ).arg(layerName)
|
||||
}
|
||||
font.bold: true
|
||||
font.pointSize: 16
|
||||
elide: Label.ElideRight
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
color: "white"
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: closeButton
|
||||
anchors.right: parent.right
|
||||
|
||||
Layout.preferredWidth: form.style.toolbutton.size
|
||||
Layout.preferredHeight: form.style.toolbutton.size
|
||||
|
||||
contentItem: Image {
|
||||
source: form.closeButtonIcon
|
||||
sourceSize: Qt.size(width, height)
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: form.style.toolbutton.backgroundColor
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
Qt.inputMethod.hide()
|
||||
form.canceled()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
id: deleteDialog
|
||||
|
||||
visible: false
|
||||
|
||||
title: qsTr( "Delete feature" )
|
||||
text: qsTr( "Really delete this feature?" )
|
||||
icon: StandardIcon.Warning
|
||||
standardButtons: StandardButton.Ok | StandardButton.Cancel
|
||||
onAccepted: {
|
||||
model.attributeModel.deleteFeature()
|
||||
visible = false
|
||||
|
||||
form.canceled()
|
||||
}
|
||||
onRejected: {
|
||||
visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
47
src/quickgui/plugin/qgsquickfeatureformstyling.qml
Normal file
@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
qgsquickfeatureformstyling.qml
|
||||
--------------------------------------
|
||||
Date : January 2018
|
||||
Copyright : (C) 2018 by Martin Dobias
|
||||
Email : wonder dot sk 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
|
||||
import QgsQuick 0.1 as QgsQuick
|
||||
|
||||
QtObject {
|
||||
property color backgroundColor: "white"
|
||||
property real backgroundOpacity: 1
|
||||
|
||||
property QtObject group: QtObject {
|
||||
property color backgroundColor: "lightGray"
|
||||
property real height: 30 * QgsQuick.Utils.dp
|
||||
}
|
||||
|
||||
property QtObject tabs: QtObject {
|
||||
property color normalColor: "#4CAF50"
|
||||
property color activeColor: "#1B5E20"
|
||||
property color disabledColor: "#999999"
|
||||
property real height: 48 * QgsQuick.Utils.dp
|
||||
}
|
||||
|
||||
property QtObject constraint: QtObject {
|
||||
property color validColor: "black"
|
||||
property color invalidColor: "#c0392b"
|
||||
property color descriptionColor: "#e67e22"
|
||||
}
|
||||
|
||||
property QtObject toolbutton: QtObject {
|
||||
property color backgroundColor: "transparent"
|
||||
property color backgroundColorInvalid: "#bdc3c7"
|
||||
property real size: 80 * QgsQuick.Utils.dp
|
||||
}
|
||||
}
|
222
src/quickgui/plugin/qgsquickphotopanel.qml
Normal file
@ -0,0 +1,222 @@
|
||||
/***************************************************************************
|
||||
qgsquickphotopanel.qml
|
||||
--------------------------------------
|
||||
Date : Dec 2017
|
||||
Copyright : (C) 2017 by Viktor Sklencar
|
||||
Email : vsklencar 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.3
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQml 2.2
|
||||
import QtMultimedia 5.8
|
||||
import QtGraphicalEffects 1.0
|
||||
import QgsQuick 0.1 as QgsQuick
|
||||
|
||||
Drawer {
|
||||
property var targetDir
|
||||
property var lastPhotoName
|
||||
property int iconSize: photoPanel.width/20
|
||||
property var fieldItem
|
||||
|
||||
property color bgColor: "white"
|
||||
property real bgOpacity: 0.8
|
||||
property color borderColor: "black"
|
||||
|
||||
// icons:
|
||||
property var captureButtonIcon: QgsQuick.Utils.getThemeIcon("ic_camera_alt_border")
|
||||
property var okButtonIcon: QgsQuick.Utils.getThemeIcon("ic_check_black")
|
||||
property var cancelButtonIcon: QgsQuick.Utils.getThemeIcon("ic_clear_black")
|
||||
|
||||
|
||||
id: photoPanel
|
||||
visible: false
|
||||
modal: true
|
||||
interactive: true
|
||||
dragMargin: 0 // prevents opening the drawer by dragging.
|
||||
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: photoPanel.bgColor
|
||||
opacity: photoPanel.bgOpacity
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
camera.setCameraState(Camera.ActiveState)
|
||||
camera.start()
|
||||
} else {
|
||||
camera.stop()
|
||||
photoPreview.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
// PhotoCapture item
|
||||
Item {
|
||||
|
||||
property bool saveImage: false
|
||||
|
||||
id: captureItem
|
||||
width: window.width
|
||||
height: window.height
|
||||
|
||||
Component.onDestruction: {
|
||||
if (!captureItem && camera.imageCapture.capturedImagePath != ""){
|
||||
captureItem.saveImage = false
|
||||
QgsQuick.Utils.remove(camera.imageCapture.capturedImagePath)
|
||||
}
|
||||
captureItem.saveImage = false
|
||||
}
|
||||
|
||||
Camera {
|
||||
id: camera
|
||||
cameraState: Camera.UnloadedState
|
||||
|
||||
imageCapture {
|
||||
onImageCaptured: {
|
||||
// Show the preview in an Image
|
||||
photoPreview.source = preview
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flipped VideoOutput on android - known ButtonGroup
|
||||
// https://bugreports.qt.io/browse/QTBUG-64764
|
||||
VideoOutput {
|
||||
id: videoOutput
|
||||
source: camera
|
||||
focus : visible // to receive focus and capture key events when visible
|
||||
anchors.fill: parent
|
||||
autoOrientation: true
|
||||
|
||||
Rectangle {
|
||||
id: captureButton
|
||||
property int borderWidth: 10 * QgsQuick.Utils.dp
|
||||
width: parent.width/20
|
||||
height: parent.width/20
|
||||
color: photoPanel.bgColor
|
||||
border.color: photoPanel.borderColor
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
border.width: borderWidth
|
||||
radius: width*0.5
|
||||
antialiasing: true
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (targetDir !== "") {
|
||||
camera.imageCapture.captureToLocation(photoPanel.targetDir);
|
||||
} else {
|
||||
// saved to default location - TODO handle this case
|
||||
camera.imageCapture.capture();
|
||||
}
|
||||
photoPreview.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: captureButtonImage
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.centerIn: parent
|
||||
sourceSize.height: captureButton.height/2
|
||||
height: captureButton.height/2
|
||||
source: photoPanel.captureButtonIcon
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Image {
|
||||
id: photoPreview
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
// Cancel button
|
||||
Rectangle {
|
||||
id: cancelButton
|
||||
visible: camera.imageCapture.capturedImagePath != ""
|
||||
|
||||
property int borderWidth: 10 * QgsQuick.Utils.dp
|
||||
width: parent.width/20
|
||||
height: parent.width/20
|
||||
color: photoPanel.bgColor
|
||||
border.color: photoPanel.borderColor
|
||||
anchors.right: parent.right
|
||||
anchors.top: confirmButton.bottom
|
||||
border.width: borderWidth
|
||||
radius: width*0.5
|
||||
antialiasing: true
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
captureItem.saveImage = false
|
||||
photoPreview.visible = false
|
||||
if (camera.imageCapture.capturedImagePath != "") {
|
||||
QgsQuick.Utils.remove(camera.imageCapture.capturedImagePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.centerIn: parent
|
||||
sourceSize.height: captureButton.height/2
|
||||
height: captureButton.height/2
|
||||
source: photoPanel.cancelButtonIcon
|
||||
}
|
||||
}
|
||||
|
||||
// OK button
|
||||
Rectangle {
|
||||
id: confirmButton
|
||||
visible: camera.imageCapture.capturedImagePath != ""
|
||||
|
||||
property int borderWidth: 10 * QgsQuick.Utils.dp
|
||||
width: parent.width/20
|
||||
height: parent.width/20
|
||||
color: photoPanel.bgColor
|
||||
border.color: photoPanel.borderColor
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
border.width: borderWidth
|
||||
radius: width*0.5
|
||||
antialiasing: true
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
captureItem.saveImage = true
|
||||
photoPanel.visible = false
|
||||
photoPanel.lastPhotoName = QgsQuick.Utils.getFileName(camera.imageCapture.capturedImagePath)
|
||||
if (photoPanel.lastPhotoName !== "") {
|
||||
fieldItem.image.source = photoPanel.targetDir + "/" + photoPanel.lastPhotoName
|
||||
fieldItem.valueChanged(photoPanel.lastPhotoName, photoPanel.lastPhotoName === "" || photoPanel.lastPhotoName === null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.centerIn: parent
|
||||
sourceSize.height: captureButton.height/2
|
||||
height: captureButton.height/2
|
||||
source: photoPanel.okButtonIcon
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsunittypes.h"
|
||||
|
||||
#include "qgsquickattributeformmodel.h"
|
||||
#include "qgsquickattributeformmodelbase.h"
|
||||
#include "qgsquickattributemodel.h"
|
||||
#include "qgsquickfeaturehighlight.h"
|
||||
#include "qgsquickcoordinatetransformer.h"
|
||||
#include "qgsquickidentifykit.h"
|
||||
@ -41,6 +44,7 @@
|
||||
#include "qgsquickplugin.h"
|
||||
#include "qgsquickpositionkit.h"
|
||||
#include "qgsquickscalebarkit.h"
|
||||
#include "qgsquicksubmodel.h"
|
||||
#include "qgsquickutils.h"
|
||||
|
||||
static QObject *_utilsProvider( QQmlEngine *engine, QJSEngine *scriptEngine )
|
||||
@ -69,6 +73,8 @@ void QgsQuickPlugin::registerTypes( const char *uri )
|
||||
qmlRegisterUncreatableType< QgsUnitTypes >( uri, 0, 1, "QgsUnitTypes", "Only enums from QgsUnitTypes can be used" );
|
||||
|
||||
qmlRegisterType< QgsProject >( uri, 0, 1, "Project" );
|
||||
qmlRegisterType< QgsQuickAttributeFormModel >( uri, 0, 1, "AttributeFormModel" );
|
||||
qmlRegisterType< QgsQuickAttributeModel >( uri, 0, 1, "AttributeModel" );
|
||||
qmlRegisterType< QgsQuickFeatureHighlight >( uri, 0, 1, "FeatureHighlight" );
|
||||
qmlRegisterType< QgsQuickCoordinateTransformer >( uri, 0, 1, "CoordinateTransformer" );
|
||||
qmlRegisterType< QgsQuickIdentifyKit >( uri, 0, 1, "IdentifyKit" );
|
||||
@ -78,6 +84,7 @@ void QgsQuickPlugin::registerTypes( const char *uri )
|
||||
qmlRegisterType< QgsQuickMessageLogModel >( uri, 0, 1, "MessageLogModel" );
|
||||
qmlRegisterType< QgsQuickPositionKit >( uri, 0, 1, "PositionKit" );
|
||||
qmlRegisterType< QgsQuickScaleBarKit >( uri, 0, 1, "ScaleBarKit" );
|
||||
qmlRegisterType< QgsQuickSubModel >( uri, 0, 1, "SubModel" );
|
||||
qmlRegisterType< QgsVectorLayer >( uri, 0, 1, "VectorLayer" );
|
||||
|
||||
qmlRegisterSingletonType< QgsQuickUtils >( uri, 0, 1, "Utils", _utilsProvider );
|
||||
|
@ -14,8 +14,11 @@ module QgsQuick
|
||||
plugin qgis_quick_plugin
|
||||
|
||||
MapCanvas 0.1 qgsquickmapcanvas.qml
|
||||
FeatureForm 0.1 qgsquickfeatureform.qml
|
||||
FeatureFormStyling 0.1 qgsquickfeatureformstyling.qml
|
||||
PositionMarker 0.1 qgsquickpositionmarker.qml
|
||||
ScaleBar 0.1 qgsquickscalebar.qml
|
||||
PhotoCapture 0.1 qgsquickphotopanel.qml
|
||||
MessageLog 0.1 qgsquickmessagelog.qml
|
||||
|
||||
typeinfo qgsquick.qmltypes
|
||||
|
@ -30,7 +30,7 @@
|
||||
* Helper class for transform of coordinates (QgsPoint) to a different coordinate reference system.
|
||||
*
|
||||
* It requires connection of transformation context from mapSettings, source position and source CRS to
|
||||
* calculate projected position in desired destination CRS
|
||||
* calculate projected position in desired destination CRS.
|
||||
*
|
||||
* \note QML Type: CoordinateTransformer
|
||||
*
|
||||
|
@ -27,7 +27,7 @@ class QgsQuickMapSettings;
|
||||
/**
|
||||
* \ingroup quick
|
||||
*
|
||||
* Creates map highlights for a geometry provided by a FeatureModel.
|
||||
* Creates map highlights for a geometry provided by a AttributeModel.
|
||||
*
|
||||
* The highlights are compatible with the QtQuick scene graph and
|
||||
* can be direcly shown on map canvas
|
||||
|
@ -36,6 +36,11 @@ QgsFeature QgsQuickFeatureLayerPair::feature() const
|
||||
return mFeature;
|
||||
}
|
||||
|
||||
QgsFeature &QgsQuickFeatureLayerPair::featureRef()
|
||||
{
|
||||
return mFeature;
|
||||
}
|
||||
|
||||
bool QgsQuickFeatureLayerPair::isValid() const
|
||||
{
|
||||
return ( mLayer && mFeature.isValid() && hasValidGeometry() );
|
||||
|
@ -82,6 +82,9 @@ class QUICK_EXPORT QgsQuickFeatureLayerPair
|
||||
//! \copydoc QgsQuickFeatureLayerPair::feature
|
||||
QgsFeature feature() const;
|
||||
|
||||
//! \copydoc QgsQuickFeatureLayerPair::feature
|
||||
QgsFeature &featureRef();
|
||||
|
||||
//! \copydoc QgsQuickFeatureLayerPair::valid
|
||||
bool isValid() const;
|
||||
|
||||
|
@ -44,12 +44,12 @@ class QUICK_EXPORT QgsQuickMapTransform : public QQuickTransform
|
||||
Q_PROPERTY( QgsQuickMapSettings *mapSettings READ mapSettings WRITE setMapSettings NOTIFY mapSettingsChanged )
|
||||
|
||||
public:
|
||||
//! create new map transform
|
||||
//! Creates a new map transform
|
||||
QgsQuickMapTransform() = default;
|
||||
~QgsQuickMapTransform() = default;
|
||||
|
||||
/**
|
||||
* Apply transformation based on current map settings to a matrix.
|
||||
* Applies transformation based on current map settings to a matrix.
|
||||
*
|
||||
* Also optimize resulting matrix after transformation
|
||||
* \param matrix Matrix to be transformed
|
||||
@ -70,7 +70,7 @@ class QUICK_EXPORT QgsQuickMapTransform : public QQuickTransform
|
||||
void updateMatrix();
|
||||
|
||||
private:
|
||||
QgsQuickMapSettings *mMapSettings = nullptr;
|
||||
QgsQuickMapSettings *mMapSettings = nullptr; // not owned
|
||||
QMatrix4x4 mMatrix;
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qgsdistancearea.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsfeature.h"
|
||||
|
||||
#include "qgsquickfeaturelayerpair.h"
|
||||
#include "qgsquickmapsettings.h"
|
||||
@ -84,6 +85,20 @@ double QgsQuickUtils::screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int
|
||||
return mDistanceArea.measureLine( p1, p2 );
|
||||
}
|
||||
|
||||
bool QgsQuickUtils::fileExists( QString path )
|
||||
{
|
||||
QFileInfo check_file( path );
|
||||
// check if file exists and if yes: Is it really a file and no directory?
|
||||
return ( check_file.exists() && check_file.isFile() );
|
||||
}
|
||||
|
||||
QString QgsQuickUtils::getFileName( QString path )
|
||||
{
|
||||
QFileInfo fileInfo( path );
|
||||
QString filename( fileInfo.fileName() );
|
||||
return filename;
|
||||
}
|
||||
|
||||
void QgsQuickUtils::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
|
||||
{
|
||||
QgsMessageLog::logMessage( message, tag, level );
|
||||
@ -101,6 +116,25 @@ const QUrl QgsQuickUtils::getThemeIcon( const QString &name ) const
|
||||
return QUrl( path );
|
||||
}
|
||||
|
||||
const QUrl QgsQuickUtils::getEditorComponentSource( const QString &widgetName )
|
||||
{
|
||||
QString path( "qgsquick%1.qml" );
|
||||
QStringList supportedWidgets = { "textedit",
|
||||
"valuemap",
|
||||
"checkbox",
|
||||
"externalresource",
|
||||
"datetime"
|
||||
};
|
||||
if ( supportedWidgets.contains( widgetName ) )
|
||||
{
|
||||
return QUrl( path.arg( widgetName ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QUrl( path.arg( "textedit" ) );
|
||||
}
|
||||
}
|
||||
|
||||
QString QgsQuickUtils::formatPoint(
|
||||
const QgsPoint &point,
|
||||
QgsCoordinateFormatter::Format format,
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QtPositioning/QGeoCoordinate>
|
||||
|
||||
#include <limits>
|
||||
@ -31,9 +32,10 @@
|
||||
#include "qgsquickmapsettings.h"
|
||||
#include "qgsquickfeaturelayerpair.h"
|
||||
#include "qgis_quick.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgscoordinateformatter.h"
|
||||
|
||||
|
||||
class QgsFeature;
|
||||
class QgsVectorLayer;
|
||||
class QgsCoordinateReferenceSystem;
|
||||
|
||||
@ -115,7 +117,21 @@ class QUICK_EXPORT QgsQuickUtils: public QObject
|
||||
*/
|
||||
Q_INVOKABLE static double screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels );
|
||||
|
||||
//! Log message in QgsMessageLog
|
||||
/**
|
||||
* Returns whether file on path exists
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
Q_INVOKABLE bool fileExists( QString path );
|
||||
|
||||
/**
|
||||
* Extracts filename from path
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
Q_INVOKABLE QString getFileName( QString path );
|
||||
|
||||
/**
|
||||
* Log message in QgsMessageLog
|
||||
*/
|
||||
Q_INVOKABLE void logMessage( const QString &message,
|
||||
const QString &tag = QString( "QgsQuick" ),
|
||||
Qgis::MessageLevel level = Qgis::Warning );
|
||||
@ -136,6 +152,15 @@ class QUICK_EXPORT QgsQuickUtils: public QObject
|
||||
*/
|
||||
Q_INVOKABLE const QUrl getThemeIcon( const QString &name ) const;
|
||||
|
||||
/**
|
||||
* Returns url to field editor component for a feature form.
|
||||
* If the widgetName does not match any supported widget, text edit is returned.
|
||||
* \param widgetName name of the attribute field widget
|
||||
*
|
||||
* \since QGIS 3.4
|
||||
*/
|
||||
Q_INVOKABLE const QUrl getEditorComponentSource( const QString &widgetName );
|
||||
|
||||
/**
|
||||
* \copydoc QgsCoordinateFormatter::format()
|
||||
*
|
||||
|
@ -7,6 +7,7 @@ SET(QGIS_QUICK_APP_SRCS
|
||||
|
||||
SET(QGIS_QUICK_APP_QMLS
|
||||
main.qml
|
||||
FeaturePanel.qml
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
|
73
tests/src/quickgui/app/FeaturePanel.qml
Normal file
@ -0,0 +1,73 @@
|
||||
/***************************************************************************
|
||||
FeaturePanel.qml
|
||||
----------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 by Peter Petrik
|
||||
Email : zilolv 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2
|
||||
import QgsQuick 0.1 as QgsQuick
|
||||
|
||||
Drawer {
|
||||
|
||||
property var mapSettings
|
||||
property var project
|
||||
|
||||
property alias state: featureForm.state
|
||||
property alias feature: attributeModel.featureLayerPair
|
||||
property alias currentAttributeModel: attributeModel
|
||||
|
||||
id: featurePanel
|
||||
visible: false
|
||||
modal: true
|
||||
interactive: true
|
||||
dragMargin: 0 // prevents opening the drawer by dragging.
|
||||
|
||||
background: Rectangle {
|
||||
color: "white"
|
||||
opacity: 0.5
|
||||
}
|
||||
|
||||
function show_panel(feature, state) {
|
||||
featurePanel.feature = feature
|
||||
featurePanel.state = state
|
||||
featurePanel.visible = true
|
||||
}
|
||||
|
||||
QgsQuick.FeatureForm {
|
||||
id: featureForm
|
||||
|
||||
// using anchors here is not working well as
|
||||
width: featurePanel.width
|
||||
height: featurePanel.height
|
||||
|
||||
model: QgsQuick.AttributeFormModel {
|
||||
attributeModel: QgsQuick.AttributeModel {
|
||||
id: attributeModel
|
||||
}
|
||||
}
|
||||
|
||||
project: featurePanel.project
|
||||
|
||||
toolbarVisible: true
|
||||
|
||||
onSaved: {
|
||||
featurePanel.visible = false
|
||||
}
|
||||
onCanceled:
|
||||
{
|
||||
featurePanel.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/***************************************************************************
|
||||
main.qml
|
||||
--------------------------------------
|
||||
--------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 by Peter Petrik
|
||||
Email : zilolv at gmail dot com
|
||||
@ -21,7 +21,15 @@ ApplicationWindow {
|
||||
id: window
|
||||
visible: true
|
||||
visibility: "Maximized"
|
||||
title: qsTr("QGIS Quick Test App")
|
||||
title: "QGIS Quick Test App"
|
||||
|
||||
// Some info
|
||||
Button {
|
||||
id: logbutton
|
||||
text: "Log"
|
||||
onClicked: logPanel.visible = true
|
||||
z: 1
|
||||
}
|
||||
|
||||
QgsQuick.MapCanvas {
|
||||
id: mapCanvas
|
||||
@ -38,9 +46,12 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
var screenPoint = Qt.point(mouse.x, mouse.y)
|
||||
var screenPoint = Qt.point( mouse.x, mouse.y );
|
||||
|
||||
var res = identifyKit.identifyOne(screenPoint);
|
||||
highlight.featureLayerPair = res
|
||||
if (res.valid)
|
||||
featurePanel.show_panel(res, "Edit" )
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,11 +66,11 @@ ApplicationWindow {
|
||||
/** Message Log */
|
||||
Drawer {
|
||||
id: logPanel
|
||||
visible: true
|
||||
visible: false
|
||||
modal: true
|
||||
interactive: true
|
||||
height: window.height
|
||||
width: QgsQuick.Utils.dp * 700
|
||||
width: 700 * QgsQuick.Utils.dp
|
||||
edge: Qt.RightEdge
|
||||
z: 2 // make sure items from here are on top of the Z-order
|
||||
|
||||
@ -72,7 +83,6 @@ ApplicationWindow {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
model: QgsQuick.MessageLogModel {}
|
||||
visible: true
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,6 +118,7 @@ ApplicationWindow {
|
||||
QgsQuick.PositionMarker {
|
||||
id: positionMarker
|
||||
positionKit: positionKit
|
||||
z: 2
|
||||
}
|
||||
|
||||
Label {
|
||||
@ -151,4 +162,14 @@ ApplicationWindow {
|
||||
color: "steelblue"
|
||||
z: 1
|
||||
}
|
||||
|
||||
FeaturePanel {
|
||||
id: featurePanel
|
||||
height: window.height
|
||||
width: 700 * QgsQuick.Utils.dp
|
||||
edge: Qt.RightEdge
|
||||
mapSettings: mapCanvas.mapSettings
|
||||
project: __project
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>main.qml</file>
|
||||
<file>FeaturePanel.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
testqgsquickidentifykit.cpp.cpp
|
||||
testqgsquickidentifykit.cpp
|
||||
--------------------------------------
|
||||
Date : May 2018
|
||||
Copyright : (C) 2018 by Viktor Sklencar
|
||||
|
@ -40,6 +40,9 @@ class TestQgsQuickUtils: public QObject
|
||||
void transformedPoint();
|
||||
void formatPoint();
|
||||
void formatDistance();
|
||||
void loadIcon();
|
||||
void fileExists();
|
||||
void loadQmlComponent();
|
||||
|
||||
private:
|
||||
QgsQuickUtils utils;
|
||||
@ -136,5 +139,30 @@ void TestQgsQuickUtils::formatDistance()
|
||||
QVERIFY( dist2str == "1.2 NM" );
|
||||
}
|
||||
|
||||
void TestQgsQuickUtils::loadIcon()
|
||||
{
|
||||
QUrl url = utils.getThemeIcon( "ic_save_white" );
|
||||
Q_ASSERT( url.toString() == QStringLiteral( "qrc:/ic_save_white.svg" ) );
|
||||
|
||||
QString fileName = utils.getFileName( url.toString() );
|
||||
Q_ASSERT( fileName == QStringLiteral( "ic_save_white.svg" ) );
|
||||
}
|
||||
|
||||
void TestQgsQuickUtils::fileExists()
|
||||
{
|
||||
QString path = QStringLiteral( TEST_DATA_DIR ) + "/quickapp_project.qgs";
|
||||
Q_ASSERT( utils.fileExists( path ) );
|
||||
}
|
||||
|
||||
|
||||
void TestQgsQuickUtils::loadQmlComponent()
|
||||
{
|
||||
QUrl dummy = utils.getEditorComponentSource( "dummy" );
|
||||
Q_ASSERT( dummy.path() == QString( "qgsquicktextedit.qml" ) );
|
||||
|
||||
QUrl valuemap = utils.getEditorComponentSource( "valuemap" );
|
||||
Q_ASSERT( valuemap.path() == QString( "qgsquickvaluemap.qml" ) );
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsQuickUtils )
|
||||
#include "testqgsquickutils.moc"
|
||||
|
BIN
tests/testdata/lines.dbf
vendored
BIN
tests/testdata/points.dbf
vendored
BIN
tests/testdata/polys.dbf
vendored
538
tests/testdata/quickapp_project.qgs
vendored
@ -1,5 +1,6 @@
|
||||
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
||||
<qgis projectname="" version="3.1.0-Master">
|
||||
<homePath path=""/>
|
||||
<title></title>
|
||||
<autotransaction active="0"/>
|
||||
<evaluateDefaultValues active="0"/>
|
||||
@ -18,13 +19,13 @@
|
||||
</projectCrs>
|
||||
<layer-tree-group>
|
||||
<customproperties/>
|
||||
<layer-tree-layer name="Planes" id="points20151123133104693" expanded="1" checked="Qt::Checked" source="./points.shp" providerKey="ogr">
|
||||
<layer-tree-layer expanded="1" name="Planes" id="points20151123133104693" providerKey="ogr" checked="Qt::Checked" source="./points.shp">
|
||||
<customproperties/>
|
||||
</layer-tree-layer>
|
||||
<layer-tree-layer name="Land" id="polys20151123133114244" expanded="1" checked="Qt::Checked" source="./polys.shp" providerKey="ogr">
|
||||
<layer-tree-layer expanded="1" name="Land" id="polys20151123133114244" providerKey="ogr" checked="Qt::Checked" source="./polys.shp">
|
||||
<customproperties/>
|
||||
</layer-tree-layer>
|
||||
<layer-tree-layer name="Roads" id="lines20151123133101198" expanded="1" checked="Qt::Checked" source="./lines.shp" providerKey="ogr">
|
||||
<layer-tree-layer expanded="1" name="Roads" id="lines20151123133101198" providerKey="ogr" checked="Qt::Checked" source="./lines.shp">
|
||||
<customproperties/>
|
||||
</layer-tree-layer>
|
||||
<custom-order enabled="0">
|
||||
@ -33,11 +34,11 @@
|
||||
<item>lines20151123133101198</item>
|
||||
</custom-order>
|
||||
</layer-tree-group>
|
||||
<snapping-settings tolerance="20" mode="1" type="2" enabled="1" unit="1" intersection-snapping="0">
|
||||
<snapping-settings mode="1" intersection-snapping="0" enabled="1" tolerance="20" type="2" unit="1">
|
||||
<individual-layer-settings>
|
||||
<layer-setting tolerance="20" units="1" id="lines20151123133101198" type="2" enabled="1"/>
|
||||
<layer-setting tolerance="20" units="1" id="polys20151123133114244" type="2" enabled="1"/>
|
||||
<layer-setting tolerance="20" units="1" id="points20151123133104693" type="2" enabled="1"/>
|
||||
<layer-setting units="1" enabled="1" id="lines20151123133101198" tolerance="20" type="2"/>
|
||||
<layer-setting units="1" enabled="1" id="points20151123133104693" tolerance="20" type="2"/>
|
||||
<layer-setting units="1" enabled="1" id="polys20151123133114244" tolerance="20" type="2"/>
|
||||
</individual-layer-settings>
|
||||
</snapping-settings>
|
||||
<relations/>
|
||||
@ -65,26 +66,25 @@
|
||||
<rendermaptile>0</rendermaptile>
|
||||
</mapcanvas>
|
||||
<legend updateDrawingOrder="true">
|
||||
<legendlayer name="Planes" drawingOrder="-1" open="true" checked="Qt::Checked" showFeatureCount="0">
|
||||
<filegroup open="true" hidden="false">
|
||||
<legendlayerfile layerid="points20151123133104693" isInOverview="0" visible="1"/>
|
||||
<legendlayer name="Planes" showFeatureCount="0" open="true" checked="Qt::Checked" drawingOrder="-1">
|
||||
<filegroup hidden="false" open="true">
|
||||
<legendlayerfile layerid="points20151123133104693" visible="1" isInOverview="0"/>
|
||||
</filegroup>
|
||||
</legendlayer>
|
||||
<legendlayer name="Land" drawingOrder="-1" open="true" checked="Qt::Checked" showFeatureCount="0">
|
||||
<filegroup open="true" hidden="false">
|
||||
<legendlayerfile layerid="polys20151123133114244" isInOverview="0" visible="1"/>
|
||||
<legendlayer name="Land" showFeatureCount="0" open="true" checked="Qt::Checked" drawingOrder="-1">
|
||||
<filegroup hidden="false" open="true">
|
||||
<legendlayerfile layerid="polys20151123133114244" visible="1" isInOverview="0"/>
|
||||
</filegroup>
|
||||
</legendlayer>
|
||||
<legendlayer name="Roads" drawingOrder="-1" open="true" checked="Qt::Checked" showFeatureCount="0">
|
||||
<filegroup open="true" hidden="false">
|
||||
<legendlayerfile layerid="lines20151123133101198" isInOverview="0" visible="1"/>
|
||||
<legendlayer name="Roads" showFeatureCount="0" open="true" checked="Qt::Checked" drawingOrder="-1">
|
||||
<filegroup hidden="false" open="true">
|
||||
<legendlayerfile layerid="lines20151123133101198" visible="1" isInOverview="0"/>
|
||||
</filegroup>
|
||||
</legendlayer>
|
||||
</legend>
|
||||
<mapViewDocks/>
|
||||
<mapViewDocks3D/>
|
||||
<projectlayers>
|
||||
<maplayer simplifyLocal="1" autoRefreshEnabled="0" simplifyDrawingTol="1" refreshOnNotifyEnabled="0" type="vector" simplifyMaxScale="1" maxScale="1" readOnly="0" simplifyDrawingHints="1" hasScaleBasedVisibilityFlag="0" autoRefreshTime="0" refreshOnNotifyMessage="" minScale="1e+8" simplifyAlgorithm="0" geometry="Line" labelsEnabled="1">
|
||||
<maplayer refreshOnNotifyMessage="" simplifyDrawingHints="1" simplifyMaxScale="1" refreshOnNotifyEnabled="0" simplifyDrawingTol="1" autoRefreshTime="0" autoRefreshEnabled="0" geometry="Line" simplifyAlgorithm="0" simplifyLocal="1" maxScale="1" type="vector" minScale="1e+8" labelsEnabled="1" readOnly="0" hasScaleBasedVisibilityFlag="0">
|
||||
<extent>
|
||||
<xmin>-117.62319839219053108</xmin>
|
||||
<ymin>23.20820580488508966</ymin>
|
||||
@ -116,6 +116,7 @@
|
||||
<type></type>
|
||||
<title></title>
|
||||
<abstract></abstract>
|
||||
<links/>
|
||||
<fees></fees>
|
||||
<encoding></encoding>
|
||||
<crs>
|
||||
@ -127,29 +128,29 @@
|
||||
<description></description>
|
||||
<projectionacronym></projectionacronym>
|
||||
<ellipsoidacronym></ellipsoidacronym>
|
||||
<geographicflag>true</geographicflag>
|
||||
<geographicflag>false</geographicflag>
|
||||
</spatialrefsys>
|
||||
</crs>
|
||||
<extent/>
|
||||
<links/>
|
||||
</resourceMetadata>
|
||||
<provider encoding="UTF-8">ogr</provider>
|
||||
<vectorjoins/>
|
||||
<layerDependencies/>
|
||||
<dataDependencies/>
|
||||
<legend type="default-vector"/>
|
||||
<expressionfields/>
|
||||
<map-layer-style-manager current="default">
|
||||
<map-layer-style name="default"/>
|
||||
</map-layer-style-manager>
|
||||
<auxiliaryLayer/>
|
||||
<renderer-v2 type="categorizedSymbol" enableorderby="0" attr="Name" symbollevels="0" forceraster="0">
|
||||
<renderer-v2 forceraster="0" enableorderby="0" type="categorizedSymbol" attr="Name" symbollevels="0">
|
||||
<categories>
|
||||
<category symbol="0" label="Arterial" value="Arterial" render="true"/>
|
||||
<category symbol="1" label="Highway" value="Highway" render="true"/>
|
||||
<category label="Arterial" render="true" symbol="0" value="Arterial"/>
|
||||
<category label="Highway" render="true" symbol="1" value="Highway"/>
|
||||
</categories>
|
||||
<symbols>
|
||||
<symbol name="0" clip_to_extent="1" type="line" alpha="1">
|
||||
<layer pass="0" locked="0" enabled="1" class="SimpleLine">
|
||||
<layer class="SimpleLine" enabled="1" locked="0" pass="0">
|
||||
<prop k="capstyle" v="square"/>
|
||||
<prop k="customdash" v="5;2"/>
|
||||
<prop k="customdash_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
@ -175,7 +176,7 @@
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="1" clip_to_extent="1" type="line" alpha="1">
|
||||
<layer pass="0" locked="0" enabled="1" class="SimpleLine">
|
||||
<layer class="SimpleLine" enabled="1" locked="0" pass="0">
|
||||
<prop k="capstyle" v="square"/>
|
||||
<prop k="customdash" v="5;2"/>
|
||||
<prop k="customdash_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
@ -205,7 +206,7 @@
|
||||
<sizescale/>
|
||||
</renderer-v2>
|
||||
<customproperties>
|
||||
<property value="0" key="embeddedWidgets/count"/>
|
||||
<property key="embeddedWidgets/count" value="0"/>
|
||||
<property key="variableNames"/>
|
||||
<property key="variableValues"/>
|
||||
</customproperties>
|
||||
@ -213,12 +214,12 @@
|
||||
<featureBlendMode>0</featureBlendMode>
|
||||
<layerOpacity>1</layerOpacity>
|
||||
<SingleCategoryDiagramRenderer diagramType="Pie" attributeLegend="1">
|
||||
<DiagramCategory maxScaleDenominator="1e+8" scaleDependency="Area" opacity="1" sizeType="MM" backgroundColor="#ffffff" labelPlacementMethod="XHeight" penColor="#000000" barWidth="5" minimumSize="0" enabled="0" rotationOffset="270" minScaleDenominator="1" penAlpha="255" lineSizeType="MM" diagramOrientation="Up" height="15" scaleBasedVisibility="0" width="15" sizeScale="3x:0,0,0,0,0,0" lineSizeScale="3x:0,0,0,0,0,0" backgroundAlpha="255" penWidth="0">
|
||||
<fontProperties description="Ubuntu,13,-1,5,50,0,0,0,0,0" style=""/>
|
||||
<attribute color="#000000" field="" label=""/>
|
||||
<DiagramCategory scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="3x:0,0,0,0,0,0" barWidth="5" maxScaleDenominator="1e+8" penAlpha="255" scaleDependency="Area" labelPlacementMethod="XHeight" penWidth="0" penColor="#000000" sizeType="MM" backgroundAlpha="255" minimumSize="0" opacity="1" diagramOrientation="Up" width="15" rotationOffset="270" minScaleDenominator="1" backgroundColor="#ffffff" sizeScale="3x:0,0,0,0,0,0" lineSizeType="MM">
|
||||
<fontProperties style="" description="Ubuntu,13,-1,5,50,0,0,0,0,0"/>
|
||||
<attribute label="" field="" color="#000000"/>
|
||||
</DiagramCategory>
|
||||
</SingleCategoryDiagramRenderer>
|
||||
<DiagramLayerSettings placement="2" priority="0" showAll="1" linePlacementFlags="10" zIndex="0" obstacle="0" dist="0">
|
||||
<DiagramLayerSettings priority="0" dist="0" placement="2" obstacle="0" showAll="1" zIndex="0" linePlacementFlags="10">
|
||||
<properties>
|
||||
<Option type="Map">
|
||||
<Option name="name" type="QString" value=""/>
|
||||
@ -256,32 +257,32 @@
|
||||
</field>
|
||||
</fieldConfiguration>
|
||||
<aliases>
|
||||
<alias name="" field="Name" index="0"/>
|
||||
<alias name="" field="Value" index="1"/>
|
||||
<alias index="0" field="Name" name=""/>
|
||||
<alias index="1" field="Value" name=""/>
|
||||
</aliases>
|
||||
<excludeAttributesWMS/>
|
||||
<excludeAttributesWFS/>
|
||||
<defaults>
|
||||
<default field="Name" applyOnUpdate="0" expression=""/>
|
||||
<default field="Value" applyOnUpdate="0" expression=""/>
|
||||
<default applyOnUpdate="0" expression="" field="Name"/>
|
||||
<default applyOnUpdate="0" expression="" field="Value"/>
|
||||
</defaults>
|
||||
<constraints>
|
||||
<constraint field="Name" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint field="Value" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Name" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Value" constraints="0" unique_strength="0"/>
|
||||
</constraints>
|
||||
<constraintExpressions>
|
||||
<constraint exp="" desc="" field="Name"/>
|
||||
<constraint exp="" desc="" field="Value"/>
|
||||
<constraint field="Name" desc="" exp=""/>
|
||||
<constraint field="Value" desc="" exp=""/>
|
||||
</constraintExpressions>
|
||||
<attributeactions/>
|
||||
<attributetableconfig actionWidgetStyle="dropDown" sortOrder="0" sortExpression="">
|
||||
<attributetableconfig sortExpression="" sortOrder="0" actionWidgetStyle="dropDown">
|
||||
<columns>
|
||||
<column name="Name" type="field" hidden="0" width="-1"/>
|
||||
<column name="Value" type="field" hidden="0" width="-1"/>
|
||||
<column type="actions" hidden="1" width="-1"/>
|
||||
<column name="Blocked" type="field" hidden="0" width="-1"/>
|
||||
<column name="Situation" type="field" hidden="0" width="-1"/>
|
||||
<column name="BlockStart" type="field" hidden="0" width="-1"/>
|
||||
<column hidden="0" width="-1" name="Name" type="field"/>
|
||||
<column hidden="0" width="-1" name="Value" type="field"/>
|
||||
<column hidden="1" width="-1" type="actions"/>
|
||||
<column hidden="0" width="-1" name="Blocked" type="field"/>
|
||||
<column hidden="0" width="-1" name="Situation" type="field"/>
|
||||
<column hidden="0" width="-1" name="BlockStart" type="field"/>
|
||||
</columns>
|
||||
</attributetableconfig>
|
||||
<editform>../src/quickgui/app/qgis-data</editform>
|
||||
@ -318,7 +319,7 @@ def my_form_open(dialog, layer, feature):
|
||||
<previewExpression>COALESCE( "Name", '<NULL>' )</previewExpression>
|
||||
<mapTip></mapTip>
|
||||
</maplayer>
|
||||
<maplayer simplifyLocal="1" autoRefreshEnabled="0" simplifyDrawingTol="1" refreshOnNotifyEnabled="0" type="vector" simplifyMaxScale="1" maxScale="1" readOnly="0" simplifyDrawingHints="0" hasScaleBasedVisibilityFlag="0" autoRefreshTime="0" refreshOnNotifyMessage="" minScale="1e+8" simplifyAlgorithm="0" geometry="Point" labelsEnabled="1">
|
||||
<maplayer refreshOnNotifyMessage="" simplifyDrawingHints="0" simplifyMaxScale="1" refreshOnNotifyEnabled="0" simplifyDrawingTol="1" autoRefreshTime="0" autoRefreshEnabled="0" geometry="Point" simplifyAlgorithm="0" simplifyLocal="1" maxScale="1" type="vector" minScale="1e+8" labelsEnabled="0" readOnly="0" hasScaleBasedVisibilityFlag="0">
|
||||
<extent>
|
||||
<xmin>-118.88888888888877204</xmin>
|
||||
<ymin>22.80020703933767834</ymin>
|
||||
@ -350,6 +351,16 @@ def my_form_open(dialog, layer, feature):
|
||||
<type></type>
|
||||
<title></title>
|
||||
<abstract></abstract>
|
||||
<contact>
|
||||
<name></name>
|
||||
<organization></organization>
|
||||
<position></position>
|
||||
<voice></voice>
|
||||
<fax></fax>
|
||||
<email></email>
|
||||
<role></role>
|
||||
</contact>
|
||||
<links/>
|
||||
<fees></fees>
|
||||
<encoding></encoding>
|
||||
<crs>
|
||||
@ -364,27 +375,35 @@ def my_form_open(dialog, layer, feature):
|
||||
<geographicflag>false</geographicflag>
|
||||
</spatialrefsys>
|
||||
</crs>
|
||||
<extent/>
|
||||
<links/>
|
||||
<extent>
|
||||
<spatial miny="0" crs="" minz="0" maxy="0" maxx="0" minx="0" maxz="0" dimensions="2"/>
|
||||
<temporal>
|
||||
<period>
|
||||
<start></start>
|
||||
<end></end>
|
||||
</period>
|
||||
</temporal>
|
||||
</extent>
|
||||
</resourceMetadata>
|
||||
<provider encoding="UTF-8">ogr</provider>
|
||||
<vectorjoins/>
|
||||
<layerDependencies/>
|
||||
<dataDependencies/>
|
||||
<legend type="default-vector"/>
|
||||
<expressionfields/>
|
||||
<map-layer-style-manager current="default">
|
||||
<map-layer-style name="default"/>
|
||||
</map-layer-style-manager>
|
||||
<auxiliaryLayer/>
|
||||
<renderer-v2 type="categorizedSymbol" enableorderby="0" attr="Class" symbollevels="0" forceraster="0">
|
||||
<renderer-v2 forceraster="0" enableorderby="0" type="categorizedSymbol" attr="Class" symbollevels="0">
|
||||
<categories>
|
||||
<category symbol="0" label="B52" value="B52" render="true"/>
|
||||
<category symbol="1" label="Biplane" value="Biplane" render="true"/>
|
||||
<category symbol="2" label="Jet" value="Jet" render="true"/>
|
||||
<category label="B52" render="true" symbol="0" value="B52"/>
|
||||
<category label="Biplane" render="true" symbol="1" value="Biplane"/>
|
||||
<category label="Jet" render="true" symbol="2" value="Jet"/>
|
||||
</categories>
|
||||
<symbols>
|
||||
<symbol name="0" clip_to_extent="1" type="marker" alpha="1">
|
||||
<layer pass="0" locked="0" enabled="1" class="SvgMarker">
|
||||
<layer class="SvgMarker" enabled="1" locked="0" pass="0">
|
||||
<prop k="angle" v="0"/>
|
||||
<prop k="color" v="189,189,189,255"/>
|
||||
<prop k="fixedAspectRatio" v="0"/>
|
||||
@ -418,7 +437,7 @@ def my_form_open(dialog, layer, feature):
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="1" clip_to_extent="1" type="marker" alpha="1">
|
||||
<layer pass="0" locked="0" enabled="1" class="SvgMarker">
|
||||
<layer class="SvgMarker" enabled="1" locked="0" pass="0">
|
||||
<prop k="angle" v="0"/>
|
||||
<prop k="color" v="124,124,124,255"/>
|
||||
<prop k="fixedAspectRatio" v="0"/>
|
||||
@ -452,7 +471,7 @@ def my_form_open(dialog, layer, feature):
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="2" clip_to_extent="1" type="marker" alpha="1">
|
||||
<layer pass="0" locked="0" enabled="1" class="SvgMarker">
|
||||
<layer class="SvgMarker" enabled="1" locked="0" pass="0">
|
||||
<prop k="angle" v="0"/>
|
||||
<prop k="color" v="178,223,138,255"/>
|
||||
<prop k="fixedAspectRatio" v="0"/>
|
||||
@ -490,7 +509,7 @@ def my_form_open(dialog, layer, feature):
|
||||
<sizescale/>
|
||||
</renderer-v2>
|
||||
<customproperties>
|
||||
<property value="0" key="embeddedWidgets/count"/>
|
||||
<property key="embeddedWidgets/count" value="0"/>
|
||||
<property key="variableNames"/>
|
||||
<property key="variableValues"/>
|
||||
</customproperties>
|
||||
@ -498,12 +517,12 @@ def my_form_open(dialog, layer, feature):
|
||||
<featureBlendMode>0</featureBlendMode>
|
||||
<layerOpacity>1</layerOpacity>
|
||||
<SingleCategoryDiagramRenderer diagramType="Pie" attributeLegend="1">
|
||||
<DiagramCategory maxScaleDenominator="1e+8" scaleDependency="Area" opacity="1" sizeType="MM" backgroundColor="#ffffff" labelPlacementMethod="XHeight" penColor="#000000" barWidth="5" minimumSize="0" enabled="0" rotationOffset="270" minScaleDenominator="1" penAlpha="255" lineSizeType="MM" diagramOrientation="Up" height="15" scaleBasedVisibility="0" width="15" sizeScale="3x:0,0,0,0,0,0" lineSizeScale="3x:0,0,0,0,0,0" backgroundAlpha="255" penWidth="0">
|
||||
<fontProperties description="Ubuntu,13,-1,5,50,0,0,0,0,0" style=""/>
|
||||
<attribute color="#000000" field="" label=""/>
|
||||
<DiagramCategory scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="3x:0,0,0,0,0,0" barWidth="5" maxScaleDenominator="1e+8" penAlpha="255" scaleDependency="Area" labelPlacementMethod="XHeight" penWidth="0" penColor="#000000" sizeType="MM" backgroundAlpha="255" minimumSize="0" opacity="1" diagramOrientation="Up" width="15" rotationOffset="270" minScaleDenominator="1" backgroundColor="#ffffff" sizeScale="3x:0,0,0,0,0,0" lineSizeType="MM">
|
||||
<fontProperties style="" description="Ubuntu,13,-1,5,50,0,0,0,0,0"/>
|
||||
<attribute label="" field="" color="#000000"/>
|
||||
</DiagramCategory>
|
||||
</SingleCategoryDiagramRenderer>
|
||||
<DiagramLayerSettings placement="0" priority="0" showAll="1" linePlacementFlags="10" zIndex="0" obstacle="0" dist="0">
|
||||
<DiagramLayerSettings priority="0" dist="0" placement="0" obstacle="0" showAll="1" zIndex="0" linePlacementFlags="2">
|
||||
<properties>
|
||||
<Option type="Map">
|
||||
<Option name="name" type="QString" value=""/>
|
||||
@ -523,12 +542,18 @@ def my_form_open(dialog, layer, feature):
|
||||
<editWidget type="ValueMap">
|
||||
<config>
|
||||
<Option type="Map">
|
||||
<Option name="map" type="Map">
|
||||
<Option name="map" type="List">
|
||||
<Option type="Map">
|
||||
<Option name="B52" type="QString" value="B52"/>
|
||||
</Option>
|
||||
<Option type="Map">
|
||||
<Option name="Biplane" type="QString" value="Biplane"/>
|
||||
</Option>
|
||||
<Option type="Map">
|
||||
<Option name="Jet" type="QString" value="Jet"/>
|
||||
</Option>
|
||||
</Option>
|
||||
</Option>
|
||||
</config>
|
||||
</editWidget>
|
||||
</field>
|
||||
@ -536,8 +561,8 @@ def my_form_open(dialog, layer, feature):
|
||||
<editWidget type="TextEdit">
|
||||
<config>
|
||||
<Option type="Map">
|
||||
<Option name="IsMultiline" type="QString" value="0"/>
|
||||
<Option name="UseHtml" type="QString" value="0"/>
|
||||
<Option name="IsMultiline" type="bool" value="false"/>
|
||||
<Option name="UseHtml" type="bool" value="false"/>
|
||||
</Option>
|
||||
</config>
|
||||
</editWidget>
|
||||
@ -556,8 +581,8 @@ def my_form_open(dialog, layer, feature):
|
||||
<editWidget type="TextEdit">
|
||||
<config>
|
||||
<Option type="Map">
|
||||
<Option name="IsMultiline" type="QString" value="0"/>
|
||||
<Option name="UseHtml" type="QString" value="0"/>
|
||||
<Option name="IsMultiline" type="bool" value="false"/>
|
||||
<Option name="UseHtml" type="bool" value="false"/>
|
||||
</Option>
|
||||
</config>
|
||||
</editWidget>
|
||||
@ -576,57 +601,103 @@ def my_form_open(dialog, layer, feature):
|
||||
<editWidget type="TextEdit">
|
||||
<config>
|
||||
<Option type="Map">
|
||||
<Option name="IsMultiline" type="QString" value="0"/>
|
||||
<Option name="UseHtml" type="QString" value="0"/>
|
||||
<Option name="IsMultiline" type="bool" value="false"/>
|
||||
<Option name="UseHtml" type="bool" value="false"/>
|
||||
</Option>
|
||||
</config>
|
||||
</editWidget>
|
||||
</field>
|
||||
<field name="Construct">
|
||||
<editWidget type="DateTime">
|
||||
<config>
|
||||
<Option type="Map">
|
||||
<Option name="allow_null" type="bool" value="true"/>
|
||||
<Option name="calendar_popup" type="bool" value="true"/>
|
||||
<Option name="display_format" type="QString" value="yyyy-MM-dd"/>
|
||||
<Option name="field_format" type="QString" value="yyyy-MM-dd"/>
|
||||
<Option name="field_iso_format" type="bool" value="false"/>
|
||||
</Option>
|
||||
</config>
|
||||
</editWidget>
|
||||
</field>
|
||||
<field name="Photo">
|
||||
<editWidget type="ExternalResource">
|
||||
<config>
|
||||
<Option type="Map">
|
||||
<Option name="DocumentViewer" type="int" value="0"/>
|
||||
<Option name="DocumentViewerHeight" type="int" value="0"/>
|
||||
<Option name="DocumentViewerWidth" type="int" value="0"/>
|
||||
<Option name="FileWidget" type="bool" value="true"/>
|
||||
<Option name="FileWidgetButton" type="bool" value="true"/>
|
||||
<Option name="FileWidgetFilter" type="QString" value=""/>
|
||||
<Option name="PropertyCollection" type="Map">
|
||||
<Option name="name" type="QString" value=""/>
|
||||
<Option name="properties"/>
|
||||
<Option name="type" type="QString" value="collection"/>
|
||||
</Option>
|
||||
<Option name="RelativeStorage" type="int" value="0"/>
|
||||
<Option name="StorageMode" type="int" value="0"/>
|
||||
</Option>
|
||||
</config>
|
||||
</editWidget>
|
||||
</field>
|
||||
</fieldConfiguration>
|
||||
<aliases>
|
||||
<alias name="" field="Class" index="0"/>
|
||||
<alias name="" field="Heading" index="1"/>
|
||||
<alias name="" field="Importance" index="2"/>
|
||||
<alias name="" field="Pilots" index="3"/>
|
||||
<alias name="" field="Cabin Crew" index="4"/>
|
||||
<alias name="" field="Staff" index="5"/>
|
||||
<alias index="0" field="Class" name=""/>
|
||||
<alias index="1" field="Heading" name=""/>
|
||||
<alias index="2" field="Importance" name=""/>
|
||||
<alias index="3" field="Pilots" name=""/>
|
||||
<alias index="4" field="Cabin Crew" name=""/>
|
||||
<alias index="5" field="Staff" name=""/>
|
||||
<alias index="6" field="Construct" name=""/>
|
||||
<alias index="7" field="Photo" name=""/>
|
||||
</aliases>
|
||||
<excludeAttributesWMS/>
|
||||
<excludeAttributesWFS/>
|
||||
<defaults>
|
||||
<default field="Class" applyOnUpdate="0" expression=""/>
|
||||
<default field="Heading" applyOnUpdate="0" expression=""/>
|
||||
<default field="Importance" applyOnUpdate="0" expression=""/>
|
||||
<default field="Pilots" applyOnUpdate="0" expression=""/>
|
||||
<default field="Cabin Crew" applyOnUpdate="0" expression=""/>
|
||||
<default field="Staff" applyOnUpdate="0" expression=""/>
|
||||
<default applyOnUpdate="0" expression="" field="Class"/>
|
||||
<default applyOnUpdate="0" expression="" field="Heading"/>
|
||||
<default applyOnUpdate="0" expression="" field="Importance"/>
|
||||
<default applyOnUpdate="0" expression="" field="Pilots"/>
|
||||
<default applyOnUpdate="0" expression="" field="Cabin Crew"/>
|
||||
<default applyOnUpdate="0" expression="" field="Staff"/>
|
||||
<default applyOnUpdate="0" expression="" field="Construct"/>
|
||||
<default applyOnUpdate="0" expression="" field="Photo"/>
|
||||
</defaults>
|
||||
<constraints>
|
||||
<constraint field="Class" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint field="Heading" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint field="Importance" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint field="Pilots" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint field="Cabin Crew" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint field="Staff" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Class" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Heading" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Importance" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Pilots" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Cabin Crew" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Staff" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Construct" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Photo" constraints="0" unique_strength="0"/>
|
||||
</constraints>
|
||||
<constraintExpressions>
|
||||
<constraint exp="" desc="" field="Class"/>
|
||||
<constraint exp="" desc="" field="Heading"/>
|
||||
<constraint exp="" desc="" field="Importance"/>
|
||||
<constraint exp="" desc="" field="Pilots"/>
|
||||
<constraint exp="" desc="" field="Cabin Crew"/>
|
||||
<constraint exp="" desc="" field="Staff"/>
|
||||
<constraint field="Class" desc="" exp=""/>
|
||||
<constraint field="Heading" desc="" exp=""/>
|
||||
<constraint field="Importance" desc="" exp=""/>
|
||||
<constraint field="Pilots" desc="" exp=""/>
|
||||
<constraint field="Cabin Crew" desc="" exp=""/>
|
||||
<constraint field="Staff" desc="" exp=""/>
|
||||
<constraint field="Construct" desc="" exp=""/>
|
||||
<constraint field="Photo" desc="" exp=""/>
|
||||
</constraintExpressions>
|
||||
<attributeactions/>
|
||||
<attributetableconfig actionWidgetStyle="dropDown" sortOrder="0" sortExpression="">
|
||||
<attributeactions>
|
||||
<defaultAction key="Canvas" value="{00000000-0000-0000-0000-000000000000}"/>
|
||||
</attributeactions>
|
||||
<attributetableconfig sortExpression="" sortOrder="0" actionWidgetStyle="dropDown">
|
||||
<columns>
|
||||
<column name="Class" type="field" hidden="0" width="-1"/>
|
||||
<column name="Heading" type="field" hidden="0" width="-1"/>
|
||||
<column name="Importance" type="field" hidden="0" width="-1"/>
|
||||
<column name="Pilots" type="field" hidden="0" width="-1"/>
|
||||
<column name="Cabin Crew" type="field" hidden="0" width="-1"/>
|
||||
<column name="Staff" type="field" hidden="0" width="-1"/>
|
||||
<column type="actions" hidden="1" width="-1"/>
|
||||
<column hidden="0" width="-1" name="Class" type="field"/>
|
||||
<column hidden="0" width="-1" name="Heading" type="field"/>
|
||||
<column hidden="0" width="-1" name="Importance" type="field"/>
|
||||
<column hidden="0" width="-1" name="Pilots" type="field"/>
|
||||
<column hidden="0" width="-1" name="Cabin Crew" type="field"/>
|
||||
<column hidden="0" width="-1" name="Staff" type="field"/>
|
||||
<column hidden="1" width="-1" type="actions"/>
|
||||
<column hidden="0" width="-1" name="Construct" type="field"/>
|
||||
<column hidden="0" width="-1" name="Photo" type="field"/>
|
||||
</columns>
|
||||
</attributetableconfig>
|
||||
<editform>../src/quickgui/app/qgis-data</editform>
|
||||
@ -652,8 +723,26 @@ def my_form_open(dialog, layer, feature):
|
||||
]]></editforminitcode>
|
||||
<featformsuppress>0</featformsuppress>
|
||||
<editorlayout>generatedlayout</editorlayout>
|
||||
<editable/>
|
||||
<labelOnTop/>
|
||||
<editable>
|
||||
<field name="Cabin Crew" editable="1"/>
|
||||
<field name="Class" editable="1"/>
|
||||
<field name="Construct" editable="1"/>
|
||||
<field name="Heading" editable="1"/>
|
||||
<field name="Importance" editable="1"/>
|
||||
<field name="Photo" editable="1"/>
|
||||
<field name="Pilots" editable="1"/>
|
||||
<field name="Staff" editable="1"/>
|
||||
</editable>
|
||||
<labelOnTop>
|
||||
<field name="Cabin Crew" labelOnTop="0"/>
|
||||
<field name="Class" labelOnTop="0"/>
|
||||
<field name="Construct" labelOnTop="0"/>
|
||||
<field name="Heading" labelOnTop="0"/>
|
||||
<field name="Importance" labelOnTop="0"/>
|
||||
<field name="Photo" labelOnTop="0"/>
|
||||
<field name="Pilots" labelOnTop="0"/>
|
||||
<field name="Staff" labelOnTop="0"/>
|
||||
</labelOnTop>
|
||||
<widgets/>
|
||||
<conditionalstyles>
|
||||
<rowstyles/>
|
||||
@ -663,7 +752,7 @@ def my_form_open(dialog, layer, feature):
|
||||
<previewExpression>COALESCE( "Class", '<NULL>' )</previewExpression>
|
||||
<mapTip></mapTip>
|
||||
</maplayer>
|
||||
<maplayer simplifyLocal="1" autoRefreshEnabled="0" simplifyDrawingTol="1" refreshOnNotifyEnabled="0" type="vector" simplifyMaxScale="1" maxScale="1" readOnly="0" simplifyDrawingHints="1" hasScaleBasedVisibilityFlag="0" autoRefreshTime="0" refreshOnNotifyMessage="" minScale="1e+8" simplifyAlgorithm="0" geometry="Polygon" labelsEnabled="1">
|
||||
<maplayer refreshOnNotifyMessage="" simplifyDrawingHints="1" simplifyMaxScale="1" refreshOnNotifyEnabled="0" simplifyDrawingTol="1" autoRefreshTime="0" autoRefreshEnabled="0" geometry="Polygon" simplifyAlgorithm="0" simplifyLocal="1" maxScale="1" type="vector" minScale="1e+8" labelsEnabled="1" readOnly="0" hasScaleBasedVisibilityFlag="0">
|
||||
<extent>
|
||||
<xmin>-118.92286230599032137</xmin>
|
||||
<ymin>24.50786971868489061</ymin>
|
||||
@ -695,6 +784,7 @@ def my_form_open(dialog, layer, feature):
|
||||
<type></type>
|
||||
<title></title>
|
||||
<abstract></abstract>
|
||||
<links/>
|
||||
<fees></fees>
|
||||
<encoding></encoding>
|
||||
<crs>
|
||||
@ -710,25 +800,25 @@ def my_form_open(dialog, layer, feature):
|
||||
</spatialrefsys>
|
||||
</crs>
|
||||
<extent/>
|
||||
<links/>
|
||||
</resourceMetadata>
|
||||
<provider encoding="UTF-8">ogr</provider>
|
||||
<vectorjoins/>
|
||||
<layerDependencies/>
|
||||
<dataDependencies/>
|
||||
<legend type="default-vector"/>
|
||||
<expressionfields/>
|
||||
<map-layer-style-manager current="default">
|
||||
<map-layer-style name="default"/>
|
||||
</map-layer-style-manager>
|
||||
<auxiliaryLayer/>
|
||||
<renderer-v2 type="categorizedSymbol" enableorderby="0" attr="Name" symbollevels="0" forceraster="0">
|
||||
<renderer-v2 forceraster="0" enableorderby="0" type="categorizedSymbol" attr="Name" symbollevels="0">
|
||||
<categories>
|
||||
<category symbol="0" label="Dam" value="Dam" render="true"/>
|
||||
<category symbol="1" label="Lake" value="Lake" render="true"/>
|
||||
<category label="Dam" render="true" symbol="0" value="Dam"/>
|
||||
<category label="Lake" render="true" symbol="1" value="Lake"/>
|
||||
</categories>
|
||||
<symbols>
|
||||
<symbol name="0" clip_to_extent="1" type="fill" alpha="1">
|
||||
<layer pass="0" locked="0" enabled="1" class="SimpleFill">
|
||||
<layer class="SimpleFill" enabled="1" locked="0" pass="0">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="118,191,227,132"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
@ -750,7 +840,7 @@ def my_form_open(dialog, layer, feature):
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="1" clip_to_extent="1" type="fill" alpha="1">
|
||||
<layer pass="0" locked="0" enabled="1" class="SimpleFill">
|
||||
<layer class="SimpleFill" enabled="1" locked="0" pass="0">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="110,194,217,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
@ -776,7 +866,7 @@ def my_form_open(dialog, layer, feature):
|
||||
<sizescale/>
|
||||
</renderer-v2>
|
||||
<customproperties>
|
||||
<property value="0" key="embeddedWidgets/count"/>
|
||||
<property key="embeddedWidgets/count" value="0"/>
|
||||
<property key="variableNames"/>
|
||||
<property key="variableValues"/>
|
||||
</customproperties>
|
||||
@ -784,12 +874,12 @@ def my_form_open(dialog, layer, feature):
|
||||
<featureBlendMode>0</featureBlendMode>
|
||||
<layerOpacity>1</layerOpacity>
|
||||
<SingleCategoryDiagramRenderer diagramType="Pie" attributeLegend="1">
|
||||
<DiagramCategory maxScaleDenominator="1e+8" scaleDependency="Area" opacity="1" sizeType="MM" backgroundColor="#ffffff" labelPlacementMethod="XHeight" penColor="#000000" barWidth="5" minimumSize="0" enabled="0" rotationOffset="270" minScaleDenominator="1" penAlpha="255" lineSizeType="MM" diagramOrientation="Up" height="15" scaleBasedVisibility="0" width="15" sizeScale="3x:0,0,0,0,0,0" lineSizeScale="3x:0,0,0,0,0,0" backgroundAlpha="255" penWidth="0">
|
||||
<fontProperties description="Ubuntu,13,-1,5,50,0,0,0,0,0" style=""/>
|
||||
<attribute color="#000000" field="" label=""/>
|
||||
<DiagramCategory scaleBasedVisibility="0" enabled="0" height="15" lineSizeScale="3x:0,0,0,0,0,0" barWidth="5" maxScaleDenominator="1e+8" penAlpha="255" scaleDependency="Area" labelPlacementMethod="XHeight" penWidth="0" penColor="#000000" sizeType="MM" backgroundAlpha="255" minimumSize="0" opacity="1" diagramOrientation="Up" width="15" rotationOffset="270" minScaleDenominator="1" backgroundColor="#ffffff" sizeScale="3x:0,0,0,0,0,0" lineSizeType="MM">
|
||||
<fontProperties style="" description="Ubuntu,13,-1,5,50,0,0,0,0,0"/>
|
||||
<attribute label="" field="" color="#000000"/>
|
||||
</DiagramCategory>
|
||||
</SingleCategoryDiagramRenderer>
|
||||
<DiagramLayerSettings placement="0" priority="0" showAll="1" linePlacementFlags="10" zIndex="0" obstacle="0" dist="0">
|
||||
<DiagramLayerSettings priority="0" dist="0" placement="0" obstacle="0" showAll="1" zIndex="0" linePlacementFlags="10">
|
||||
<properties>
|
||||
<Option type="Map">
|
||||
<Option name="name" type="QString" value=""/>
|
||||
@ -829,29 +919,29 @@ def my_form_open(dialog, layer, feature):
|
||||
</field>
|
||||
</fieldConfiguration>
|
||||
<aliases>
|
||||
<alias name="" field="Name" index="0"/>
|
||||
<alias name="" field="Value" index="1"/>
|
||||
<alias index="0" field="Name" name=""/>
|
||||
<alias index="1" field="Value" name=""/>
|
||||
</aliases>
|
||||
<excludeAttributesWMS/>
|
||||
<excludeAttributesWFS/>
|
||||
<defaults>
|
||||
<default field="Name" applyOnUpdate="0" expression=""/>
|
||||
<default field="Value" applyOnUpdate="0" expression=""/>
|
||||
<default applyOnUpdate="0" expression="" field="Name"/>
|
||||
<default applyOnUpdate="0" expression="" field="Value"/>
|
||||
</defaults>
|
||||
<constraints>
|
||||
<constraint field="Name" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint field="Value" unique_strength="0" exp_strength="0" constraints="0" notnull_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Name" constraints="0" unique_strength="0"/>
|
||||
<constraint notnull_strength="0" exp_strength="0" field="Value" constraints="0" unique_strength="0"/>
|
||||
</constraints>
|
||||
<constraintExpressions>
|
||||
<constraint exp="" desc="" field="Name"/>
|
||||
<constraint exp="" desc="" field="Value"/>
|
||||
<constraint field="Name" desc="" exp=""/>
|
||||
<constraint field="Value" desc="" exp=""/>
|
||||
</constraintExpressions>
|
||||
<attributeactions/>
|
||||
<attributetableconfig actionWidgetStyle="dropDown" sortOrder="0" sortExpression="">
|
||||
<attributetableconfig sortExpression="" sortOrder="0" actionWidgetStyle="dropDown">
|
||||
<columns>
|
||||
<column name="Name" type="field" hidden="0" width="-1"/>
|
||||
<column name="Value" type="field" hidden="0" width="-1"/>
|
||||
<column type="actions" hidden="1" width="-1"/>
|
||||
<column hidden="0" width="-1" name="Name" type="field"/>
|
||||
<column hidden="0" width="-1" name="Value" type="field"/>
|
||||
<column hidden="1" width="-1" type="actions"/>
|
||||
</columns>
|
||||
</attributetableconfig>
|
||||
<editform>../src/quickgui/app/qgis-data</editform>
|
||||
@ -895,124 +985,146 @@ def my_form_open(dialog, layer, feature):
|
||||
<layer id="lines20151123133101198"/>
|
||||
</layerorder>
|
||||
<properties>
|
||||
<WMSPrecision type="QString">8</WMSPrecision>
|
||||
<WMSContactMail type="QString"></WMSContactMail>
|
||||
<WMSFees type="QString">conditions unknown</WMSFees>
|
||||
<WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
|
||||
<Paths>
|
||||
<Absolute type="bool">false</Absolute>
|
||||
</Paths>
|
||||
<WMSUrl type="QString"></WMSUrl>
|
||||
<Legend>
|
||||
<filterByMap type="bool">false</filterByMap>
|
||||
</Legend>
|
||||
<WMSContactPosition type="QString"></WMSContactPosition>
|
||||
<ddt2>
|
||||
<designs type="QString"></designs>
|
||||
</ddt2>
|
||||
<WMSAccessConstraints type="QString">None</WMSAccessConstraints>
|
||||
<WMSContactPerson type="QString"></WMSContactPerson>
|
||||
<WMSOnlineResource type="QString"></WMSOnlineResource>
|
||||
<WFSTLayers>
|
||||
<Insert type="QStringList"/>
|
||||
<Update type="QStringList"/>
|
||||
<Delete type="QStringList"/>
|
||||
</WFSTLayers>
|
||||
<Variables>
|
||||
<variableValues type="QStringList"/>
|
||||
<variableNames type="QStringList"/>
|
||||
</Variables>
|
||||
<PositionPrecision>
|
||||
<DegreeFormat type="QString">MU</DegreeFormat>
|
||||
<DecimalPlaces type="int">2</DecimalPlaces>
|
||||
<Automatic type="bool">true</Automatic>
|
||||
</PositionPrecision>
|
||||
<WMSSegmentizeFeatureInfoGeometry type="bool">false</WMSSegmentizeFeatureInfoGeometry>
|
||||
<Macros>
|
||||
<pythonCode type="QString"></pythonCode>
|
||||
</Macros>
|
||||
<WMSContactOrganization type="QString"></WMSContactOrganization>
|
||||
<Identify>
|
||||
<disabledLayers type="QStringList"/>
|
||||
</Identify>
|
||||
<DefaultStyles>
|
||||
<ColorRamp type="QString"></ColorRamp>
|
||||
<AlphaInt type="int">255</AlphaInt>
|
||||
<Fill type="QString"></Fill>
|
||||
<ColorRamp type="QString"></ColorRamp>
|
||||
<Marker type="QString"></Marker>
|
||||
<Line type="QString"></Line>
|
||||
<Fill type="QString"></Fill>
|
||||
<RandomColors type="bool">true</RandomColors>
|
||||
</DefaultStyles>
|
||||
<WMSServiceCapabilities type="bool">false</WMSServiceCapabilities>
|
||||
<WMSServiceTitle type="QString"></WMSServiceTitle>
|
||||
<WCSLayers type="QStringList"/>
|
||||
<WMSServiceAbstract type="QString"></WMSServiceAbstract>
|
||||
<SpatialRefSys>
|
||||
<ProjectCrs type="QString">EPSG:4326</ProjectCrs>
|
||||
<ProjectionsEnabled type="int">1</ProjectionsEnabled>
|
||||
<ProjectCRSID type="int">3452</ProjectCRSID>
|
||||
<ProjectCRSProj4String type="QString">+proj=longlat +datum=WGS84 +no_defs</ProjectCRSProj4String>
|
||||
</SpatialRefSys>
|
||||
<Measure>
|
||||
<Ellipsoid type="QString">NONE</Ellipsoid>
|
||||
</Measure>
|
||||
<WMSKeywordList type="QStringList">
|
||||
<value></value>
|
||||
</WMSKeywordList>
|
||||
<WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
|
||||
<WMSContactPhone type="QString"></WMSContactPhone>
|
||||
<WFSLayers type="QStringList"/>
|
||||
<Measurement>
|
||||
<AreaUnits type="QString">m2</AreaUnits>
|
||||
<DistanceUnits type="QString">meters</DistanceUnits>
|
||||
</Measurement>
|
||||
<Variables>
|
||||
<variableNames type="QStringList"/>
|
||||
<variableValues type="QStringList"/>
|
||||
</Variables>
|
||||
<WMSAccessConstraints type="QString">None</WMSAccessConstraints>
|
||||
<WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
|
||||
<WMSFees type="QString">conditions unknown</WMSFees>
|
||||
<SpatialRefSys>
|
||||
<ProjectionsEnabled type="int">1</ProjectionsEnabled>
|
||||
<ProjectCRSID type="int">3452</ProjectCRSID>
|
||||
<ProjectCRSProj4String type="QString">+proj=longlat +datum=WGS84 +no_defs</ProjectCRSProj4String>
|
||||
<ProjectCrs type="QString">EPSG:4326</ProjectCrs>
|
||||
</SpatialRefSys>
|
||||
<PAL>
|
||||
<ShowingPartialsLabels type="bool">true</ShowingPartialsLabels>
|
||||
<SearchMethod type="int">0</SearchMethod>
|
||||
<ShowingAllLabels type="bool">false</ShowingAllLabels>
|
||||
<DrawOutlineLabels type="bool">true</DrawOutlineLabels>
|
||||
<CandidatesPolygon type="int">30</CandidatesPolygon>
|
||||
<CandidatesPoint type="int">16</CandidatesPoint>
|
||||
<CandidatesLine type="int">50</CandidatesLine>
|
||||
<DrawRectOnly type="bool">false</DrawRectOnly>
|
||||
<ShowingCandidates type="bool">false</ShowingCandidates>
|
||||
</PAL>
|
||||
<WMSContactPerson type="QString"></WMSContactPerson>
|
||||
<WCSLayers type="QStringList"/>
|
||||
<WFSTLayers>
|
||||
<Insert type="QStringList"/>
|
||||
<Delete type="QStringList"/>
|
||||
<Update type="QStringList"/>
|
||||
</WFSTLayers>
|
||||
<Legend>
|
||||
<filterByMap type="bool">false</filterByMap>
|
||||
</Legend>
|
||||
<WMSServiceTitle type="QString"></WMSServiceTitle>
|
||||
<PositionPrecision>
|
||||
<Automatic type="bool">true</Automatic>
|
||||
<DecimalPlaces type="int">2</DecimalPlaces>
|
||||
<DegreeFormat type="QString">MU</DegreeFormat>
|
||||
</PositionPrecision>
|
||||
<WMSContactMail type="QString"></WMSContactMail>
|
||||
<WMSPrecision type="QString">8</WMSPrecision>
|
||||
<WMSContactPhone type="QString"></WMSContactPhone>
|
||||
<WMSServiceAbstract type="QString"></WMSServiceAbstract>
|
||||
<ddt2>
|
||||
<designs type="QString"></designs>
|
||||
</ddt2>
|
||||
<WMSSegmentizeFeatureInfoGeometry type="bool">false</WMSSegmentizeFeatureInfoGeometry>
|
||||
<WMSServiceCapabilities type="bool">false</WMSServiceCapabilities>
|
||||
<WMSContactOrganization type="QString"></WMSContactOrganization>
|
||||
<WMSImageQuality type="int">90</WMSImageQuality>
|
||||
<Gui>
|
||||
<SelectionColorRedPart type="int">255</SelectionColorRedPart>
|
||||
<CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
|
||||
<CanvasColorRedPart type="int">255</CanvasColorRedPart>
|
||||
<CanvasColorBluePart type="int">255</CanvasColorBluePart>
|
||||
<SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
|
||||
<SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
|
||||
<SelectionColorBluePart type="int">0</SelectionColorBluePart>
|
||||
</Gui>
|
||||
<WCSUrl type="QString"></WCSUrl>
|
||||
<Digitizing>
|
||||
<DefaultSnapType type="QString">to vertex and segment</DefaultSnapType>
|
||||
<DefaultSnapToleranceUnit type="int">1</DefaultSnapToleranceUnit>
|
||||
<LayerSnappingList type="QStringList">
|
||||
<value>lines20151123133101198</value>
|
||||
<value>points20151123133104693</value>
|
||||
<value>polys20151123133114244</value>
|
||||
</LayerSnappingList>
|
||||
<DefaultSnapTolerance type="double">20</DefaultSnapTolerance>
|
||||
<LayerSnappingToleranceList type="QStringList">
|
||||
<value>20.000000</value>
|
||||
<value>20.000000</value>
|
||||
<value>20.000000</value>
|
||||
</LayerSnappingToleranceList>
|
||||
<LayerSnapToList type="QStringList">
|
||||
<value>to_vertex_and_segment</value>
|
||||
<value>to_vertex_and_segment</value>
|
||||
<value>to_vertex_and_segment</value>
|
||||
</LayerSnapToList>
|
||||
<SnappingMode type="QString">current_layer</SnappingMode>
|
||||
<AvoidIntersectionsList type="QStringList"/>
|
||||
<LayerSnappingToleranceUnitList type="QStringList">
|
||||
<value>1</value>
|
||||
<value>1</value>
|
||||
<value>1</value>
|
||||
</LayerSnappingToleranceUnitList>
|
||||
<LayerSnappingList type="QStringList">
|
||||
<value>lines20151123133101198</value>
|
||||
<value>points20151123133104693</value>
|
||||
<value>polys20151123133114244</value>
|
||||
</LayerSnappingList>
|
||||
<SnappingMode type="QString">current_layer</SnappingMode>
|
||||
<DefaultSnapTolerance type="double">20</DefaultSnapTolerance>
|
||||
<LayerSnappingEnabledList type="QStringList">
|
||||
<value>enabled</value>
|
||||
<value>enabled</value>
|
||||
<value>enabled</value>
|
||||
</LayerSnappingEnabledList>
|
||||
<LayerSnapToList type="QStringList">
|
||||
<value>to_vertex_and_segment</value>
|
||||
<value>to_vertex_and_segment</value>
|
||||
<value>to_vertex_and_segment</value>
|
||||
</LayerSnapToList>
|
||||
<DefaultSnapToleranceUnit type="int">1</DefaultSnapToleranceUnit>
|
||||
<AvoidIntersectionsList type="QStringList"/>
|
||||
<DefaultSnapType type="QString">to vertex and segment</DefaultSnapType>
|
||||
</Digitizing>
|
||||
<Measurement>
|
||||
<DistanceUnits type="QString">meters</DistanceUnits>
|
||||
<AreaUnits type="QString">m2</AreaUnits>
|
||||
</Measurement>
|
||||
<WMSOnlineResource type="QString"></WMSOnlineResource>
|
||||
<Macros>
|
||||
<pythonCode type="QString"></pythonCode>
|
||||
</Macros>
|
||||
<WFSUrl type="QString"></WFSUrl>
|
||||
<WMSImageQuality type="int">90</WMSImageQuality>
|
||||
<Gui>
|
||||
<SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
|
||||
<SelectionColorRedPart type="int">255</SelectionColorRedPart>
|
||||
<CanvasColorRedPart type="int">255</CanvasColorRedPart>
|
||||
<SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
|
||||
<CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
|
||||
<SelectionColorBluePart type="int">0</SelectionColorBluePart>
|
||||
<CanvasColorBluePart type="int">255</CanvasColorBluePart>
|
||||
</Gui>
|
||||
<WCSUrl type="QString"></WCSUrl>
|
||||
<WMSUrl type="QString"></WMSUrl>
|
||||
<Identify>
|
||||
<disabledLayers type="QStringList"/>
|
||||
</Identify>
|
||||
<WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
|
||||
<WMSContactPosition type="QString"></WMSContactPosition>
|
||||
<WMSKeywordList type="QStringList">
|
||||
<value></value>
|
||||
</WMSKeywordList>
|
||||
<Paths>
|
||||
<Absolute type="bool">false</Absolute>
|
||||
</Paths>
|
||||
</properties>
|
||||
<visibility-presets/>
|
||||
<transformContext/>
|
||||
<projectMetadata>
|
||||
<identifier></identifier>
|
||||
<parentidentifier></parentidentifier>
|
||||
<language></language>
|
||||
<type></type>
|
||||
<title></title>
|
||||
<abstract></abstract>
|
||||
<links/>
|
||||
<author></author>
|
||||
<creation></creation>
|
||||
</projectMetadata>
|
||||
<Annotations/>
|
||||
<Layouts/>
|
||||
</qgis>
|
||||
|