Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Gui cleanups for attribute capture when digitising. Create a dynamica…
…lly generated dialog rather than using a table widget.

git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@8556 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
timlinux committed May 30, 2008
1 parent bb91d14 commit 820d87d
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 194 deletions.
230 changes: 112 additions & 118 deletions src/app/qgsattributedialog.cpp
Expand Up @@ -22,148 +22,142 @@
#include <QTableWidgetItem> #include <QTableWidgetItem>
#include <QSettings> #include <QSettings>
#include <QLineEdit> #include <QLineEdit>

#include <QSpinBox>
QgsAttributeDialog::QgsAttributeDialog(const QgsFieldMap& fields, const QgsAttributeMap& attributes) #include <QLabel>
#include <QDoubleSpinBox>
#include <QFrame>
#include <QScrollArea>

QgsAttributeDialog::QgsAttributeDialog(
QgsFieldMap theFieldMap, QgsFeature * thepFeature)
: QDialog(), : QDialog(),
_settingsPath("/Windows/AttributeDialog/"), mSettingsPath("/Windows/AttributeDialog/"),
mRowIsDirty(attributes.size(), FALSE) mFieldMap(theFieldMap),
mpFeature(thepFeature)
{ {
restorePositionAndColumnWidth();

setupUi(this);
mTable->setRowCount(attributes.size());


int index=0; setupUi(this);
for (QgsAttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); ++it) if (mpFeature==NULL) return;
if (mFieldMap.isEmpty()) return;
QgsAttributeMap myAttributes = mpFeature->attributeMap();
//
//Set up dynamic inside a scroll box
//
QVBoxLayout * mypOuterLayout = new QVBoxLayout();
mypOuterLayout->setContentsMargins(0,0,0,0);
//transfers layout ownership so no need to call delete
mFrame->setLayout(mypOuterLayout);
QScrollArea * mypScrollArea = new QScrollArea();
//transfers scroll area ownership so no need to call delete
mypOuterLayout->addWidget(mypScrollArea);
QFrame * mypInnerFrame = new QFrame();
mypInnerFrame->setFrameShape(QFrame::NoFrame);
mypInnerFrame->setFrameShadow(QFrame::Plain);
//transfers frame ownership so no need to call delete
mypScrollArea->setWidget(mypInnerFrame);
mypScrollArea->setWidgetResizable( true );
QGridLayout * mypInnerLayout = new QGridLayout(mypInnerFrame);

int index=0;
for (QgsAttributeMap::const_iterator it = myAttributes.begin();
it != myAttributes.end();
++it)
{
QString myFieldName = mFieldMap[it.key()].name();
QLabel * mypLabel = new QLabel();
mypInnerLayout->addWidget(mypLabel,index,0);
QVariant myFieldValue = it.value();
QLineEdit * mypLineEdit = new QLineEdit();
//the provider may have provided a default value so use it
mypLineEdit->setText(myFieldValue.toString());
if( mFieldMap[it.key()].type()==QVariant::Int )
{ {
// set attribute name mypLineEdit->setValidator( new QIntValidator(mypLineEdit) );

mypLabel->setText(myFieldName + tr(" (int)"));
QString fieldName = fields[it.key()].name();

QTableWidgetItem * myFieldItem = new QTableWidgetItem(fieldName);
myFieldItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
mTable->setItem(index, 0, myFieldItem);

#if QT_VERSION >= 0x040400
// set attribute value
QTableWidgetItem * myValueItem = new QTableWidgetItem((*it).toString());
mTable->setItem(index, 1, myValueItem);
#endif

QLineEdit *le = new QLineEdit();

le->setFrame(false);

if( fields[it.key()].type()==QVariant::Int )
{
le->setValidator( new QIntValidator(le) );
}
else if( fields[it.key()].type()==QVariant::Double )
{
le->setValidator( new QDoubleValidator(le) );
}

#if QT_VERSION < 0x040400
le->setText((*it).toString());
#endif

mTable->setCellWidget(index, 1, le);

++index;
} }

else if( mFieldMap[it.key()].type()==QVariant::Double )
// setup the mechanism to track edited attribute values {
// if we do it this way, only edited attributes will mypLineEdit->setValidator( new QDoubleValidator(mypLineEdit) );
// be attempted to be saved when the editing session stops. mypLabel->setText(myFieldName + tr(" (dbl)"));
connect(mTable, SIGNAL(cellChanged(int, int)), }
this, SLOT (setAttributeValueChanged(int, int))); else //string

{
mTable->resizeColumnsToContents(); //any special behaviour for string goes here
} mypLabel->setText(myFieldName + tr(" (txt)"));

}
QgsAttributeDialog::~QgsAttributeDialog() mypInnerLayout->addWidget(mypLineEdit,index,1);
{ mpWidgets << mypLineEdit;

++index;
}
restoreGeometry();
} }


QString QgsAttributeDialog::value(int row)
{
return static_cast<QLineEdit*>(mTable->cellWidget(row,1))->text();
}


bool QgsAttributeDialog::isDirty(int row) QgsAttributeDialog::~QgsAttributeDialog()
{ {
return mRowIsDirty.at(row); saveGeometry();
} }

bool QgsAttributeDialog::queryAttributes(const QgsFieldMap& fields, QgsFeature& f) void QgsAttributeDialog::accept()
{ {
QgsAttributeMap featureAttributes = f.attributeMap(); //write the new values back to the feature
QgsAttributeDialog attdialog(fields, featureAttributes); QgsAttributeMap myAttributes = mpFeature->attributeMap();

int myIndex=0;
if (attdialog.exec() == QDialog::Accepted) for (QgsAttributeMap::const_iterator it = myAttributes.begin();
it != myAttributes.end();
++it)
{ {
int i=0; //Q_ASSERT(myIndex <= mpWidgets.size());
for (QgsAttributeMap::const_iterator it = featureAttributes.begin(); it != featureAttributes.end(); ++it, i++) QString myFieldName = mFieldMap[it.key()].name();
bool myFlag=false;
QString myFieldValue =
dynamic_cast<QLineEdit *>(mpWidgets.value(myIndex))->text();
switch( mFieldMap[it.key()].type() )
{ {
QString value = attdialog.value(i); case QVariant::Int:

if( attdialog.isDirty(i) )
{
switch( fields[it.key()].type() )
{ {
case QVariant::Int: int myIntValue = myFieldValue.toInt(&myFlag);
f.changeAttribute(it.key(), value=="" ? QVariant( QString::null ) : QVariant( value.toInt() ) ); if (myFlag && ! myFieldValue.isEmpty())
break; {

mpFeature->changeAttribute( it.key(), QVariant(myIntValue) );
case QVariant::Double: }
f.changeAttribute(it.key(), value=="" ? QVariant( QString::null ) : QVariant( value.toDouble() ) ); else
break; {

mpFeature->changeAttribute( it.key(), QVariant(QString::null) );
default: }
f.changeAttribute(it.key(), value=="NULL" ? QVariant(QString::null) : QVariant(value) ); }
break; break;
case QVariant::Double:
{
double myDblValue = myFieldValue.toDouble(&myFlag);
if (myFlag && ! myFieldValue.isEmpty())
{
mpFeature->changeAttribute( it.key(), QVariant(myDblValue) );
}
else
{
mpFeature->changeAttribute( it.key(), QVariant(QString::null) );
}
} }
} else { break;
f.changeAttribute(it.key(), QVariant(value) ); default: //string
} mpFeature->changeAttribute(it.key(),QVariant( myFieldValue ) );
break;
} }
return true; ++myIndex;
}
else
{
return false;
} }
QDialog::accept();
} }


void QgsAttributeDialog::savePositionAndColumnWidth() void QgsAttributeDialog::saveGeometry()
{ {
QSettings settings; QSettings settings;
settings.setValue(_settingsPath+"geometry", saveGeometry()); settings.setValue(mSettingsPath+"geometry", QDialog::saveGeometry());
} }


void QgsAttributeDialog::resizeEvent(QResizeEvent *event) void QgsAttributeDialog::restoreGeometry()
{
savePositionAndColumnWidth();
QWidget::resizeEvent(event);
}

void QgsAttributeDialog::moveEvent(QMoveEvent *event)
{
savePositionAndColumnWidth();
QWidget::moveEvent(event);
}

void QgsAttributeDialog::restorePositionAndColumnWidth()
{ {
QSettings settings; QSettings settings;
restoreGeometry(settings.value(_settingsPath+"geometry").toByteArray()); QDialog::restoreGeometry(settings.value(mSettingsPath+"geometry").toByteArray());
} }


void QgsAttributeDialog::setAttributeValueChanged(int row, int column)
{
QgsDebugMsg("Entered with row " + QString::number(row) +
", column " + QString::number(column) + ".");

mRowIsDirty.at(row) = TRUE;
}
55 changes: 21 additions & 34 deletions src/app/qgsattributedialog.h
Expand Up @@ -25,49 +25,36 @@


class QDialog; class QDialog;
class QgsFeature; class QgsFeature;

class QLayout;
class QgsField; class QgsField;
typedef QMap<int, QgsField> QgsFieldMap; typedef QMap<int, QgsField> QgsFieldMap;


class QgsAttributeDialog: public QDialog, private Ui::QgsAttributeDialogBase class QgsAttributeDialog: public QDialog, private Ui::QgsAttributeDialogBase
{ {
Q_OBJECT Q_OBJECT;


public: public:
QgsAttributeDialog(const QgsFieldMap& fields, const QgsAttributeMap& attributes); QgsAttributeDialog(const QgsFieldMap thepFieldMap, QgsFeature * thepFeature);

~QgsAttributeDialog();
~QgsAttributeDialog();

/** Overloaded accept method which will write the feature field
/** Returns if the field value of a row was edited since this dialog opened */ * values, then delegate to QDialog::accept()
bool isDirty(int row); */

void accept();
/** Opens an attribute dialog and queries the attributes for a given feature. The /** Saves the size and position for the next time
attribute values are set to the feature if the dialog is accepted. * this dialog box was used.
\retval true if accepted */
\retval false if canceled */ void saveGeometry();
static bool queryAttributes(const QgsFieldMap& fields, QgsFeature& f); /** Restores the size and position from the last time

* this dialog box was used.
// Saves and restores the size and position from the last time */
// this dialog box was used. void restoreGeometry();
void savePositionAndColumnWidth();

void restorePositionAndColumnWidth();

void resizeEvent(QResizeEvent *event);

void moveEvent(QMoveEvent *event);

public slots:
//! Slot to be called when an attribute value is edited in the table.
void setAttributeValueChanged(int row, int column);


private: private:
QString _settingsPath; QString mSettingsPath;

QList<QWidget *> mpWidgets;
/** Returns the field value of a row */ QgsFieldMap mFieldMap;
QString value(int row); QgsFeature * mpFeature;

std::vector<bool> mRowIsDirty;
}; };


#endif #endif
43 changes: 26 additions & 17 deletions src/app/qgsmaptooladdfeature.cpp
Expand Up @@ -170,16 +170,23 @@ void QgsMapToolAddFeature::canvasReleaseEvent(QMouseEvent * e)
// add the fields to the QgsFeature // add the fields to the QgsFeature
const QgsFieldMap fields=provider->fields(); const QgsFieldMap fields=provider->fields();
for(QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it) for(QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it)
{ {
f->addAttribute(it.key(), provider->getDefaultValue(it.key()) ); f->addAttribute(it.key(), provider->getDefaultValue(it.key()) );
} }


// show the dialog to enter attribute values // show the dialog to enter attribute values
if (QgsAttributeDialog::queryAttributes(fields, *f)) QgsAttributeDialog * mypDialog = new QgsAttributeDialog(fields,f );
if (mypDialog->exec())
{
qDebug("Adding feature to layer");
vlayer->addFeature(*f); vlayer->addFeature(*f);
}
else else
{
qDebug("Adding feature to layer failed");
delete f; delete f;

}
delete mypDialog;
mCanvas->refresh(); mCanvas->refresh();
} }


Expand Down Expand Up @@ -429,19 +436,21 @@ void QgsMapToolAddFeature::canvasReleaseEvent(QMouseEvent * e)
f->addAttribute(it.key(), provider->getDefaultValue(it.key())); f->addAttribute(it.key(), provider->getDefaultValue(it.key()));
} }


if (QgsAttributeDialog::queryAttributes(fields, *f)) QgsAttributeDialog * mypDialog = new QgsAttributeDialog(fields,f );
{ if (mypDialog->exec())
if(vlayer->addFeature(*f)) {
{ if(vlayer->addFeature(*f))
//add points to other features to keep topology up-to-date {
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0); //add points to other features to keep topology up-to-date
if(topologicalEditing) int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
{ if(topologicalEditing)
vlayer->addTopologicalPoints(f->geometry()); {
} vlayer->addTopologicalPoints(f->geometry());
} }
} }
}
delete f; delete f;
delete mypDialog;


// delete the elements of mCaptureList // delete the elements of mCaptureList
mCaptureList.clear(); mCaptureList.clear();
Expand Down

0 comments on commit 820d87d

Please sign in to comment.