mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
Problems: Polygon outlines are not drawn. This was checked twice and no cause was found. Projections do not work in all circumstances Note that both the proj4 library and sqlite3 are now required. The build system has not been modified to test for these yet. Qt 3.3.x is required to build this source tree. Make sure to increment the EXTRA_VERSION in configure.in when committing changes. Make sure to update the Changelog with each commit git-svn-id: http://svn.osgeo.org/qgis/trunk@3112 c8812cc2-4d05-0410-92ff-de0c093fc19c
2030 lines
60 KiB
C++
2030 lines
60 KiB
C++
/***************************************************************************
|
|
qgsgrassselect.cpp - Select GRASS layer dialog
|
|
-------------------
|
|
begin : March, 2004
|
|
copyright : (C) 2004 by Radim Blazek
|
|
email : blazek@itc.it
|
|
***************************************************************************/
|
|
/***************************************************************************
|
|
* *
|
|
* 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 <iostream>
|
|
#include <qdir.h>
|
|
#include <qevent.h>
|
|
#include <qfile.h>
|
|
#include <qfiledialog.h>
|
|
#include <qsettings.h>
|
|
#include <qpixmap.h>
|
|
#include <qlistbox.h>
|
|
#include <qstringlist.h>
|
|
#include <qlabel.h>
|
|
#include <qcombobox.h>
|
|
#include <qspinbox.h>
|
|
#include <qmessagebox.h>
|
|
#include <qinputdialog.h>
|
|
#include <qsettings.h>
|
|
#include <qpainter.h>
|
|
#include <qpixmap.h>
|
|
#include <qpen.h>
|
|
#include <qpointarray.h>
|
|
#include <qcursor.h>
|
|
#include <qnamespace.h>
|
|
#include <qlistview.h>
|
|
#include <qcolordialog.h>
|
|
#include <qtable.h>
|
|
#include <qstatusbar.h>
|
|
|
|
#include "../../src/qgis.h"
|
|
#include "../../src/qgsmapcanvas.h"
|
|
#include "../../src/qgsmaplayer.h"
|
|
#include "../../src/qgsvectorlayer.h"
|
|
#include "../../src/qgsdataprovider.h"
|
|
#include "../../src/qgsmaptopixel.h"
|
|
#include "../../src/qgsfield.h"
|
|
#include "../../src/qgsfeatureattribute.h"
|
|
|
|
extern "C" {
|
|
#include <gis.h>
|
|
#include <Vect.h>
|
|
}
|
|
|
|
#include "../../providers/grass/qgsgrass.h"
|
|
#include "../../providers/grass/qgsgrassprovider.h"
|
|
#include "qgsgrassattributes.h"
|
|
#include "qgsgrassedit.h"
|
|
|
|
bool QgsGrassEdit::mRunning = false;
|
|
|
|
QgsGrassEdit::QgsGrassEdit ( QgisApp *qgisApp, QgisIface *iface,
|
|
QWidget * parent, const char * name, WFlags f )
|
|
:QgsGrassEditBase ( parent, name, f )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit()" << std::endl;
|
|
#endif
|
|
|
|
mRunning = true;
|
|
mValid = false;
|
|
mTool = QgsGrassEdit::NONE;
|
|
mSuspend = false;
|
|
mQgisApp = qgisApp;
|
|
mIface = iface;
|
|
|
|
mCanvas = mIface->getMapCanvas();
|
|
|
|
// TODO QGIS: crash if canvas is empty
|
|
QgsMapLayer *layer = (QgsMapLayer *) mIface->activeLayer();
|
|
|
|
if ( !layer ) {
|
|
std::cerr << "No layer is selected." << std::endl;
|
|
QMessageBox::warning( 0, "Warning", "No layer is selected." );
|
|
return;
|
|
}
|
|
|
|
std::cerr << "layer name: " << layer->name() << std::endl;
|
|
|
|
if ( layer->type() != QgsMapLayer::VECTOR ) {
|
|
std::cerr << "The selected layer is not vector." << std::endl;
|
|
QMessageBox::warning( 0, "Warning", "The selected layer is not vector." );
|
|
return;
|
|
}
|
|
|
|
//TODO dynamic_cast ?
|
|
QgsVectorLayer *vector = (QgsVectorLayer*)layer;
|
|
|
|
std::cerr << "Vector layer type: " << vector->providerType() << std::endl;
|
|
|
|
if ( vector->providerType() != "grass" ) {
|
|
QMessageBox::warning( 0, "Warning", "The selected vector is not in GRASS format." );
|
|
return;
|
|
}
|
|
|
|
//TODO dynamic_cast ?
|
|
mProvider = (QgsGrassProvider *) vector->getDataProvider();
|
|
|
|
if ( !(mProvider->isGrassEditable()) ) {
|
|
QMessageBox::warning( 0, "Warning", "You are not owner of the mapset, "
|
|
"cannot open the vector for editing." );
|
|
return;
|
|
}
|
|
|
|
std::cerr << "Vector layer type: " << vector->providerType() << std::endl;
|
|
if ( !(mProvider->startEdit()) ) {
|
|
QMessageBox::warning( 0, "Warning", "Cannot open vector for update." );
|
|
return;
|
|
}
|
|
|
|
mEditPoints = Vect_new_line_struct ();
|
|
mPoints = Vect_new_line_struct ();
|
|
mLastDynamicPoints = Vect_new_line_struct ();
|
|
mCats = Vect_new_cats_struct ();
|
|
|
|
// Set lines symbology from map
|
|
int nlines = mProvider->numLines();
|
|
mLineSymb.resize(nlines+1000);
|
|
for ( int line = 1; line <= nlines; line++ ) {
|
|
mLineSymb[line] = lineSymbFromMap ( line );
|
|
}
|
|
|
|
// Set nodes symbology from map
|
|
int nnodes = mProvider->numNodes();
|
|
mNodeSymb.resize(nnodes+1000);
|
|
for ( int node = 1; node <= nnodes; node++ ) {
|
|
mNodeSymb[node] = nodeSymbFromMap ( node );
|
|
}
|
|
|
|
// Set default colors
|
|
mSymb.resize(SYMB_COUNT);
|
|
mSymb[SYMB_BACKGROUND].setColor ( QColor ( 255, 255, 255 ) ); // white
|
|
mSymb[SYMB_HIGHLIGHT].setColor ( QColor ( 255, 255, 0 ) ); // yellow
|
|
mSymb[SYMB_DYNAMIC].setColor ( QColor ( 125, 125, 125 ) ); // grey
|
|
mSymb[SYMB_POINT].setColor ( QColor ( 0, 0, 0 ) ); // black
|
|
mSymb[SYMB_LINE].setColor ( QColor ( 0, 0, 0 ) ); // black
|
|
mSymb[SYMB_BOUNDARY_0].setColor ( QColor ( 255, 0, 0 ) ); // red
|
|
mSymb[SYMB_BOUNDARY_1].setColor ( QColor ( 255, 125, 0 ) ); // orange
|
|
mSymb[SYMB_BOUNDARY_2].setColor ( QColor ( 0, 255, 0 ) ); // green
|
|
mSymb[SYMB_CENTROID_IN].setColor ( QColor ( 0, 255, 0 ) ); // green
|
|
mSymb[SYMB_CENTROID_OUT].setColor ( QColor ( 255, 0, 0 ) ); // red
|
|
mSymb[SYMB_CENTROID_DUPL].setColor ( QColor ( 255, 0, 255 ) ); // magenta
|
|
mSymb[SYMB_NODE_1].setColor ( QColor ( 255, 0, 0 ) ); // red
|
|
mSymb[SYMB_NODE_2].setColor ( QColor ( 0, 255, 0 ) ); // green
|
|
|
|
// Set mSymbDisplay
|
|
mSymbDisplay.resize(SYMB_COUNT);
|
|
mSymbDisplay[SYMB_BACKGROUND] = true;
|
|
mSymbDisplay[SYMB_HIGHLIGHT] = true;
|
|
mSymbDisplay[SYMB_DYNAMIC] = true;
|
|
mSymbDisplay[SYMB_POINT] = true;
|
|
mSymbDisplay[SYMB_LINE] = true;
|
|
mSymbDisplay[SYMB_BOUNDARY_0] = true;
|
|
mSymbDisplay[SYMB_BOUNDARY_1] = true;
|
|
mSymbDisplay[SYMB_BOUNDARY_2] = true;
|
|
mSymbDisplay[SYMB_CENTROID_IN] = true;
|
|
mSymbDisplay[SYMB_CENTROID_OUT] = true;
|
|
mSymbDisplay[SYMB_CENTROID_DUPL] = true;
|
|
mSymbDisplay[SYMB_NODE_1] = true;
|
|
mSymbDisplay[SYMB_NODE_2] = true;
|
|
|
|
// Set symbology names
|
|
mSymbName.resize(SYMB_COUNT);
|
|
mSymbName[SYMB_BACKGROUND] = "Background";
|
|
mSymbName[SYMB_HIGHLIGHT] = "Highlight";
|
|
mSymbName[SYMB_DYNAMIC] = "Dynamic (XOR mode)";
|
|
mSymbName[SYMB_POINT] = "Point";
|
|
mSymbName[SYMB_LINE] = "Line";
|
|
mSymbName[SYMB_BOUNDARY_0] = "Boundary (no area)";
|
|
mSymbName[SYMB_BOUNDARY_1] = "Boundary (1 area)";
|
|
mSymbName[SYMB_BOUNDARY_2] = "Boundary (2 areas)";
|
|
mSymbName[SYMB_CENTROID_IN] = "Centroid (in area)";
|
|
mSymbName[SYMB_CENTROID_OUT] = "Centroid (outside area)";
|
|
mSymbName[SYMB_CENTROID_DUPL] = "Centroid (duplicate in area)";
|
|
mSymbName[SYMB_NODE_1] = "Node (1 line)";
|
|
mSymbName[SYMB_NODE_2] = "Node (2 lines)";
|
|
|
|
// Restore symbology
|
|
QSettings settings;
|
|
for ( int i = 0; i < SYMB_COUNT; i++ ) {
|
|
bool ok;
|
|
QString sn;
|
|
sn.sprintf( "/qgis/grass/edit/symb/display/%d", i );
|
|
bool displ = settings.readBoolEntry (sn, true, &ok );
|
|
if ( ok ) {
|
|
mSymbDisplay[i] = displ;
|
|
}
|
|
|
|
sn.sprintf( "/qgis/grass/edit/symb/color/%d", i );
|
|
QString colorName = settings.readEntry (sn, "", &ok );
|
|
if ( ok ) {
|
|
QColor color( colorName );
|
|
mSymb[i].setColor( color );
|
|
}
|
|
}
|
|
|
|
// Set Symbology in dialog
|
|
symbologyList->setColumnText(0,"Disp");
|
|
symbologyList->setColumnWidth(0,20);
|
|
symbologyList->addColumn("Color");
|
|
symbologyList->setColumnWidth(0,50);
|
|
symbologyList->addColumn("Type");
|
|
symbologyList->setColumnWidthMode(2,QListView::Maximum);
|
|
symbologyList->addColumn("Index", 0);
|
|
symbologyList->clear();
|
|
symbologyList->setSorting(-1);
|
|
|
|
for ( int i = SYMB_COUNT-1; i >= 0; i-- ) {
|
|
if ( i == SYMB_NODE_0 ) continue;
|
|
|
|
QPixmap pm ( 40, 15 );
|
|
pm.fill( mSymb[i].color() );
|
|
QString index;
|
|
index.sprintf ("%d", i );
|
|
|
|
if ( i == SYMB_BACKGROUND || i == SYMB_HIGHLIGHT || i == SYMB_DYNAMIC ) {
|
|
QListViewItem *lvi = new QListViewItem ( symbologyList , "", "", mSymbName[i] );
|
|
lvi->setPixmap ( 1, pm );
|
|
lvi->setText ( 3, index );
|
|
} else {
|
|
QCheckListItem *clvi = new QCheckListItem ( symbologyList , "", QCheckListItem::CheckBox );
|
|
clvi->setText ( 2, mSymbName[i] );
|
|
clvi->setPixmap ( 1, pm );
|
|
clvi->setOn ( mSymbDisplay[i] );
|
|
clvi->setText ( 3, index );
|
|
}
|
|
}
|
|
|
|
connect( symbologyList, SIGNAL(pressed(QListViewItem *, const QPoint &, int)),
|
|
this, SLOT(changeSymbology(QListViewItem *, const QPoint &, int)));
|
|
|
|
// Init table tab
|
|
mAttributeTable->setLeftMargin(0); // hide row labels
|
|
mAttributeTable->horizontalHeader()->setLabel( 0, "Column" );
|
|
mAttributeTable->horizontalHeader()->setLabel( 1, "Type" );
|
|
mAttributeTable->horizontalHeader()->setLabel( 2, "Length" );
|
|
|
|
int ndblinks = mProvider->numDbLinks();
|
|
|
|
if ( ndblinks > 0 ) {
|
|
for ( int i = 0; i < ndblinks; i++ ) {
|
|
int f = mProvider->dbLinkField ( i );
|
|
|
|
QString str;
|
|
str.sprintf ( "%d", f );
|
|
mTableField->insertItem ( str );
|
|
mFieldBox->insertItem( str );
|
|
if ( i == 0 ) {
|
|
setAttributeTable( f );
|
|
}
|
|
}
|
|
mTableField->setCurrentItem ( 0 );
|
|
mFieldBox->setCurrentItem ( 0 );
|
|
} else {
|
|
mTableField->insertItem ( "1" );
|
|
setAttributeTable ( 1 );
|
|
|
|
mFieldBox->insertItem("1");
|
|
}
|
|
|
|
connect( mAttributeTable, SIGNAL(valueChanged(int,int)), this, SLOT(columnTypeChanged(int,int)) );
|
|
|
|
// Set variables
|
|
mSize = 9;
|
|
mLastDynamicIcon = ICON_NONE;
|
|
Vect_reset_line ( mLastDynamicPoints );
|
|
mSelectedLine = 0;
|
|
mAttributes = 0;
|
|
|
|
// Read max cats
|
|
for (int i = 0; i < mProvider->cidxGetNumFields(); i++ ) {
|
|
int field = mProvider->cidxGetFieldNumber(i);
|
|
if ( field > 0 ) {
|
|
int cat = mProvider->cidxGetMaxCat(i);
|
|
MaxCat mc;
|
|
mc.field = field;
|
|
mc.maxCat = cat;
|
|
mMaxCats.push_back(mc);
|
|
}
|
|
}
|
|
|
|
connect( mCanvas, SIGNAL(xyClickCoordinates(QgsPoint &, Qt::ButtonState)),
|
|
this, SLOT(mouseEventReceiverClick(QgsPoint &, Qt::ButtonState)));
|
|
connect( mCanvas, SIGNAL(xyCoordinates(QgsPoint &)),
|
|
this, SLOT(mouseEventReceiverMove(QgsPoint &)));
|
|
connect( mCanvas, SIGNAL(renderComplete(QPainter *)), this, SLOT(postRender(QPainter *)));
|
|
|
|
mPixmap = mCanvas->canvasPixmap();
|
|
|
|
// Init GUI values
|
|
mCatModeBox->insertItem( "Next not used", CAT_MODE_NEXT );
|
|
mCatModeBox->insertItem( "Manual entry", CAT_MODE_MANUAL );
|
|
mCatModeBox->insertItem( "No category", CAT_MODE_NOCAT );
|
|
catModeChanged ( );
|
|
|
|
// TODO: how to get keyboard events from canvas (shortcuts)
|
|
|
|
restorePosition();
|
|
|
|
mValid = true;
|
|
}
|
|
|
|
void QgsGrassEdit::attributeTableFieldChanged ( void )
|
|
{
|
|
int field = mTableField->currentText().toInt();
|
|
|
|
setAttributeTable ( field );
|
|
}
|
|
|
|
void QgsGrassEdit::setAttributeTable ( int field )
|
|
{
|
|
mAttributeTable->setNumRows ( 0 );
|
|
|
|
QString *key = mProvider->key ( field );
|
|
|
|
if ( !key->isEmpty() ) { // Database link defined
|
|
std::vector<QgsField> *cols = mProvider->columns ( field );
|
|
|
|
mAttributeTable->setNumRows ( cols->size() );
|
|
|
|
|
|
for ( int c = 0; c < cols->size(); c++ ) {
|
|
QgsField col = (*cols)[c];
|
|
|
|
QTableItem *ti;
|
|
|
|
ti = new QTableItem( mAttributeTable, QTableItem::Never, col.name() );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( c, 0, ti );
|
|
|
|
ti = new QTableItem( mAttributeTable, QTableItem::Never, col.type() );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( c, 1, ti );
|
|
|
|
QString str;
|
|
str.sprintf("%d", col.length() );
|
|
ti = new QTableItem( mAttributeTable, QTableItem::Never, str );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( c, 2, ti );
|
|
}
|
|
} else {
|
|
mAttributeTable->setNumRows ( 1 );
|
|
|
|
QTableItem *ti;
|
|
|
|
ti = new QTableItem( mAttributeTable, QTableItem::Always, "cat" );
|
|
mAttributeTable->setItem ( 0, 0, ti );
|
|
|
|
ti = new QTableItem( mAttributeTable, QTableItem::Never, "integer" );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( 0, 1, ti );
|
|
|
|
ti = new QTableItem( mAttributeTable, QTableItem::Never, "" );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( 0, 2, ti );
|
|
}
|
|
}
|
|
|
|
void QgsGrassEdit::addColumn ( void )
|
|
{
|
|
int r = mAttributeTable->numRows();
|
|
mAttributeTable->setNumRows( r+1 );
|
|
mAttributeTable->setRowReadOnly ( r, false );
|
|
|
|
QString cn;
|
|
cn.sprintf ( "column%d", r+1 );
|
|
|
|
QTableItem *ti;
|
|
|
|
ti = new QTableItem( mAttributeTable, QTableItem::Always, cn );
|
|
mAttributeTable->setItem ( r, 0, ti );
|
|
|
|
QStringList types;
|
|
types.push_back ( "integer" );
|
|
types.push_back ( "double precision" );
|
|
types.push_back ( "varchar" );
|
|
|
|
QComboTableItem *cti = new QComboTableItem ( mAttributeTable, types );
|
|
cti->setCurrentItem(0);
|
|
mAttributeTable->setItem ( r, 1, cti );
|
|
|
|
ti = new QTableItem( mAttributeTable, QTableItem::Never, "20" );
|
|
ti->setEnabled(false);
|
|
mAttributeTable->setItem ( r, 2, ti );
|
|
}
|
|
|
|
void QgsGrassEdit::columnTypeChanged ( int row, int col )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::columnChanged() row = " << row << " col = " << col << std::endl;
|
|
#endif
|
|
|
|
if ( col != 1 ) return;
|
|
|
|
QComboTableItem *cti = (QComboTableItem *) mAttributeTable->item ( row, 1 );
|
|
|
|
QTableItem *ti = mAttributeTable->item ( row, 2 );
|
|
|
|
if ( cti->currentText().compare( "varchar" ) != 0 ) {
|
|
QTableItem *nti = new QTableItem( mAttributeTable, QTableItem::Never, ti->text() );
|
|
nti->setEnabled(false);
|
|
mAttributeTable->setItem ( row, 2, nti );
|
|
//delete ti;
|
|
} else {
|
|
QTableItem *nti = new QTableItem( mAttributeTable, QTableItem::Always, ti->text() );
|
|
nti->setEnabled(true);
|
|
mAttributeTable->setItem ( row, 2, nti );
|
|
//delete ti;
|
|
}
|
|
mAttributeTable->updateCell ( row, 2 );
|
|
}
|
|
|
|
void QgsGrassEdit::alterTable ( void )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::alterTable()" << std::endl;
|
|
#endif
|
|
|
|
// Create new table if first column name is editable otherwise alter table
|
|
int field = mTableField->currentText().toInt();
|
|
|
|
QTableItem *ti;
|
|
ti = mAttributeTable->item ( 0, 0 );
|
|
|
|
QString sql;
|
|
|
|
if ( mAttributeTable->item(0,0)->isEnabled() ) {
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "Create new table" << std::endl;
|
|
#endif
|
|
|
|
for ( int i = 0; i < mAttributeTable->numRows(); i++ ) {
|
|
if ( i > 0 ) sql.append(", " );
|
|
|
|
|
|
sql.append ( mAttributeTable->item(i,0)->text() + " " + mAttributeTable->item(i,1)->text() );
|
|
|
|
if ( mAttributeTable->item(i,1)->text().compare("varchar") == 0 ) {
|
|
sql.append ( " (" + mAttributeTable->item(i,2)->text() + ")" );
|
|
}
|
|
}
|
|
|
|
QString *error = mProvider->createTable ( field, mAttributeTable->item(0,0)->text(), sql );
|
|
|
|
if ( !error->isEmpty() ) {
|
|
QMessageBox::warning( 0, "Warning", *error );
|
|
} else {
|
|
QMessageBox::information( 0, "Info", "The table was created" );
|
|
QString str;
|
|
str.sprintf ( "%d", field );
|
|
mFieldBox->insertItem( str );
|
|
}
|
|
delete error;
|
|
} else {
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "Alter table" << std::endl;
|
|
#endif
|
|
|
|
for ( int i = 0; i < mAttributeTable->numRows(); i++ ) {
|
|
if ( !(mAttributeTable->item(i,0)->isEnabled()) ) continue;
|
|
|
|
sql = mAttributeTable->item(i,0)->text() + " " + mAttributeTable->item(i,1)->text();
|
|
|
|
if ( mAttributeTable->item(i,1)->text().compare("varchar") == 0 ) {
|
|
sql.append ( " (" + mAttributeTable->item(i,2)->text() + ")" );
|
|
}
|
|
|
|
QString *error = mProvider->addColumn ( field, sql );
|
|
|
|
if ( !error->isEmpty() ) {
|
|
QMessageBox::warning( 0, "Warning", *error );
|
|
}
|
|
delete error;
|
|
}
|
|
}
|
|
|
|
setAttributeTable ( field );
|
|
}
|
|
|
|
void QgsGrassEdit::changeSymbology(QListViewItem * item, const QPoint & pnt, int col)
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::changeSymbology() col = " << col << std::endl;
|
|
#endif
|
|
|
|
QSettings settings;
|
|
|
|
if ( !item ) return;
|
|
|
|
int index = item->text(3).toInt();
|
|
|
|
if ( col == 0 ) {
|
|
if ( index == SYMB_BACKGROUND || index == SYMB_HIGHLIGHT || index == SYMB_DYNAMIC ) return;
|
|
|
|
QCheckListItem *clvi = (QCheckListItem *) item;
|
|
mSymbDisplay[index] = clvi->isOn();
|
|
|
|
int ww = settings.readNumEntry("/qgis/grass/windows/edit/w", 420);
|
|
QString sn;
|
|
// TODO use a name instead of index
|
|
sn.sprintf( "/qgis/grass/edit/symb/display/%d", index );
|
|
settings.writeEntry ( sn, mSymbDisplay[index] );
|
|
} else if ( col == 1 ) {
|
|
QColor color = QColorDialog::getColor ( mSymb[index].color(), this );
|
|
mSymb[index].setColor( color );
|
|
|
|
QPixmap pm ( 40, 15 );
|
|
pm.fill( mSymb[index].color() );
|
|
item->setPixmap ( 1, pm );
|
|
|
|
QString sn;
|
|
// TODO use a name instead of index
|
|
sn.sprintf( "/qgis/grass/edit/symb/color/%d", index );
|
|
settings.writeEntry ( sn, mSymb[index].color().name() );
|
|
}
|
|
}
|
|
|
|
void QgsGrassEdit::restorePosition()
|
|
{
|
|
QSettings settings;
|
|
int ww = settings.readNumEntry("/qgis/grass/windows/edit/w", 420);
|
|
int wh = settings.readNumEntry("/qgis/grass/windows/edit/h", 150);
|
|
int wx = settings.readNumEntry("/qgis/grass/windows/edit/x", 100);
|
|
int wy = settings.readNumEntry("/qgis/grass/windows/edit/y", 100);
|
|
resize(ww,wh);
|
|
move(wx,wy);
|
|
}
|
|
|
|
void QgsGrassEdit::saveWindowLocation()
|
|
{
|
|
QSettings settings;
|
|
QPoint p = this->pos();
|
|
QSize s = this->size();
|
|
settings.writeEntry("/qgis/grass/windows/edit/x", p.x());
|
|
settings.writeEntry("/qgis/grass/windows/edit/y", p.y());
|
|
settings.writeEntry("/qgis/grass/windows/edit/w", s.width());
|
|
settings.writeEntry("/qgis/grass/windows/edit/h", s.height());
|
|
}
|
|
|
|
void QgsGrassEdit::updateSymb ( void )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::updateSymb" << std::endl;
|
|
#endif
|
|
|
|
// Set lines symbology from map
|
|
int nlines = mProvider->numLines();
|
|
if ( nlines+1 >= mLineSymb.size() )
|
|
mLineSymb.resize(nlines+1000);
|
|
|
|
nlines = mProvider->numUpdatedLines();
|
|
for ( int i = 0; i < nlines; i++ ) {
|
|
int line = mProvider->updatedLine(i);
|
|
std::cerr << "updated line = " << line << std::endl;
|
|
if ( !(mProvider->lineAlive(line)) ) continue;
|
|
mLineSymb[line] = lineSymbFromMap ( line );
|
|
}
|
|
|
|
// Set nodes symbology from map
|
|
int nnodes = mProvider->numNodes();
|
|
if ( nnodes+1 >= mNodeSymb.size() )
|
|
mNodeSymb.resize(nnodes+1000);
|
|
|
|
nnodes = mProvider->numUpdatedNodes();
|
|
for ( int i = 0; i < nnodes; i++ ) {
|
|
int node = mProvider->updatedNode(i);
|
|
if ( !(mProvider->nodeAlive(node)) ) continue;
|
|
mNodeSymb[node] = nodeSymbFromMap ( node );
|
|
std::cerr << "node = " << node << " mNodeSymb = " << mNodeSymb[node] << std::endl;
|
|
}
|
|
}
|
|
|
|
int QgsGrassEdit::nodeSymbFromMap ( int node )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::nodeSymbFromMap() node = " << node << std::endl;
|
|
#endif
|
|
|
|
int nlines = mProvider->nodeNLines ( node );
|
|
|
|
int count = 0;
|
|
|
|
for ( int i = 0; i < nlines; i++ ) {
|
|
int line = abs ( mProvider->nodeLine(node,i) );
|
|
int type = mProvider->readLine ( NULL, NULL, line );
|
|
|
|
if ( type & GV_LINES )
|
|
count++;
|
|
}
|
|
|
|
if ( count == 0 )
|
|
return SYMB_NODE_0;
|
|
else if ( count == 1 )
|
|
return SYMB_NODE_1;
|
|
|
|
return SYMB_NODE_2;
|
|
}
|
|
|
|
int QgsGrassEdit::lineSymbFromMap ( int line )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::lineSymbFromMap() line = " << line << std::endl;
|
|
#endif
|
|
|
|
int type = mProvider->readLine ( NULL, NULL, line );
|
|
|
|
if ( type < 0 ) return 0;
|
|
|
|
switch ( type ) {
|
|
case GV_POINT:
|
|
return SYMB_POINT;
|
|
break;
|
|
|
|
case GV_LINE:
|
|
return SYMB_LINE;
|
|
break;
|
|
|
|
case GV_BOUNDARY:
|
|
int left, right, nareas;
|
|
|
|
if ( !(mProvider->lineAreas(line, &left, &right)) ) return 0;
|
|
|
|
/* Count areas/isles on both sides */
|
|
nareas = 0;
|
|
if ( left != 0 ) nareas++;
|
|
if ( right != 0 ) nareas++;
|
|
if ( nareas == 0 ) return SYMB_BOUNDARY_0;
|
|
else if ( nareas == 1 ) return SYMB_BOUNDARY_1;
|
|
else return SYMB_BOUNDARY_2;
|
|
break;
|
|
|
|
case GV_CENTROID:
|
|
int area = mProvider->centroidArea ( line );
|
|
if ( area == 0 ) return SYMB_CENTROID_OUT;
|
|
else if ( area > 0 ) return SYMB_CENTROID_IN;
|
|
else return SYMB_CENTROID_DUPL; /* area < 0 */
|
|
break;
|
|
}
|
|
|
|
return 0; // Should not happen
|
|
}
|
|
|
|
QgsGrassEdit::~QgsGrassEdit()
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::~QgsGrassEdit()" << std::endl;
|
|
#endif
|
|
|
|
if ( mValid )
|
|
eraseDynamic();
|
|
|
|
saveWindowLocation();
|
|
mRunning = false;
|
|
}
|
|
|
|
bool QgsGrassEdit::isRunning(void)
|
|
{
|
|
return mRunning;
|
|
}
|
|
|
|
bool QgsGrassEdit::isValid(void)
|
|
{
|
|
return mValid;
|
|
}
|
|
|
|
void QgsGrassEdit::closeEdit(void)
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::close()" << std::endl;
|
|
#endif
|
|
|
|
if ( mAttributes ) {
|
|
delete mAttributes;
|
|
}
|
|
|
|
mProvider->closeEdit();
|
|
|
|
hide();
|
|
|
|
delete this;
|
|
}
|
|
|
|
void QgsGrassEdit::closeEvent(QCloseEvent *e)
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::closeEvent()" << std::endl;
|
|
#endif
|
|
|
|
e->accept();
|
|
|
|
closeEdit();
|
|
}
|
|
|
|
void QgsGrassEdit::catModeChanged ( void )
|
|
{
|
|
int mode = mCatModeBox->currentItem();
|
|
|
|
int field = mFieldBox->currentText().toInt();
|
|
|
|
if ( mode == CAT_MODE_NEXT ) { // Find next not used
|
|
QString c = "1"; // Default for new field
|
|
for (int i = 0; i < mMaxCats.size(); i++ ) {
|
|
if ( mMaxCats[i].field == field ) {
|
|
c.sprintf("%d", mMaxCats[i].maxCat+1);
|
|
break;
|
|
}
|
|
}
|
|
mCatEntry->setText ( c );
|
|
mCatEntry->setEnabled(false);
|
|
mFieldBox->setDisabled(false);
|
|
} else if ( mode == CAT_MODE_MANUAL ) {
|
|
mCatEntry->setEnabled(true);
|
|
mFieldBox->setDisabled(false);
|
|
} else { // CAT_MODE_NOCAT
|
|
mCatEntry->clear ();
|
|
mCatEntry->setEnabled(false);
|
|
mFieldBox->setDisabled(true);
|
|
}
|
|
}
|
|
|
|
void QgsGrassEdit::fieldChanged ( void )
|
|
{
|
|
int mode = mCatModeBox->currentItem();
|
|
int field = mFieldBox->currentText().toInt();
|
|
|
|
if ( mode == CAT_MODE_NEXT ) { // Find next not used
|
|
QString c = "1"; // Default for new field
|
|
for (int i = 0; i < mMaxCats.size(); i++ ) {
|
|
if ( mMaxCats[i].field == field ) {
|
|
c.sprintf("%d", mMaxCats[i].maxCat+1);
|
|
break;
|
|
}
|
|
}
|
|
mCatEntry->setText ( c );
|
|
}
|
|
}
|
|
|
|
int QgsGrassEdit::writeLine ( int type, struct line_pnts *Points )
|
|
{
|
|
int mode = mCatModeBox->currentItem();
|
|
int field = mFieldBox->currentText().toInt();
|
|
int cat = mCatEntry->text().toInt();
|
|
|
|
Vect_reset_cats ( mCats );
|
|
if ( mode == CAT_MODE_NEXT || mode == CAT_MODE_MANUAL ) {
|
|
Vect_cat_set ( mCats, field, cat );
|
|
|
|
// Insert new DB record if link is defined and the record for this cat does not exist
|
|
QString *key = mProvider->key ( field );
|
|
|
|
if ( !key->isEmpty() ) { // Database link defined
|
|
std::vector<QgsFeatureAttribute> *atts = mProvider->attributes ( field, cat );
|
|
|
|
if ( atts->size() == 0 ) { // Nothing selected
|
|
QString *error = mProvider->insertAttributes ( field, cat );
|
|
|
|
if ( !error->isEmpty() ) {
|
|
QMessageBox::warning( 0, "Warning", *error );
|
|
}
|
|
delete error;
|
|
}
|
|
|
|
delete atts;
|
|
}
|
|
}
|
|
Vect_line_prune ( Points );
|
|
int line = mProvider->writeLine ( type, Points, mCats );
|
|
|
|
increaseMaxCat();
|
|
return line;
|
|
}
|
|
|
|
void QgsGrassEdit::increaseMaxCat ( void )
|
|
{
|
|
int mode = mCatModeBox->currentItem();
|
|
int field = mFieldBox->currentText().toInt();
|
|
int cat = mCatEntry->text().toInt();
|
|
|
|
if ( mode == CAT_MODE_NEXT || mode == CAT_MODE_MANUAL ) {
|
|
int found = 0;
|
|
for (int i = 0; i < mMaxCats.size(); i++ ) {
|
|
if ( mMaxCats[i].field == field ) {
|
|
if ( cat > mMaxCats[i].maxCat ) {
|
|
mMaxCats[i].maxCat = cat;
|
|
}
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if ( !found ) {
|
|
MaxCat mc;
|
|
mc.field = field;
|
|
mc.maxCat = cat;
|
|
mMaxCats.push_back(mc);
|
|
}
|
|
|
|
if ( mode == CAT_MODE_NEXT ) {
|
|
QString c;
|
|
c.sprintf("%d", cat+1);
|
|
mCatEntry->setText ( c );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
double QgsGrassEdit::threshold ( void )
|
|
{
|
|
int snapPixels = mSnapPixels->text().toInt();
|
|
|
|
// Convert to map units (not nice)
|
|
mTransform = mCanvas->getCoordinateTransform();
|
|
double x1 = mTransform->toMapCoordinates( 0, 0 ).x();
|
|
double x2 = mTransform->toMapCoordinates( snapPixels, 0 ).x();
|
|
|
|
return ( x2 - x1 );
|
|
}
|
|
|
|
void QgsGrassEdit::snap ( double *x, double *y )
|
|
{
|
|
double thresh = threshold();
|
|
|
|
int node = mProvider->findNode ( *x, *y, thresh );
|
|
|
|
if ( node > 0 ) {
|
|
mProvider->nodeCoor ( node, x, y );
|
|
}
|
|
}
|
|
|
|
void QgsGrassEdit::snap ( QgsPoint & point )
|
|
{
|
|
double x = point.x();
|
|
double y = point.y();
|
|
|
|
snap ( &x, &y );
|
|
|
|
point.setX(x);
|
|
point.setY(y);
|
|
}
|
|
|
|
void QgsGrassEdit::newPoint(void) { startTool(QgsGrassEdit::NEW_POINT); }
|
|
void QgsGrassEdit::newLine(void) {
|
|
std::cerr << "QgsGrassEdit::newLine" << std::endl;
|
|
startTool(QgsGrassEdit::NEW_LINE);
|
|
}
|
|
void QgsGrassEdit::newBoundary(void) {
|
|
std::cerr << "QgsGrassEdit::newBoundary" << std::endl;
|
|
startTool(QgsGrassEdit::NEW_BOUNDARY);
|
|
}
|
|
void QgsGrassEdit::newCentroid(void) { startTool(QgsGrassEdit::NEW_CENTROID); }
|
|
void QgsGrassEdit::moveVertex(void) { startTool(QgsGrassEdit::MOVE_VERTEX); }
|
|
void QgsGrassEdit::addVertex(void) { startTool(QgsGrassEdit::ADD_VERTEX); }
|
|
void QgsGrassEdit::deleteVertex(void) { startTool(QgsGrassEdit::DELETE_VERTEX); }
|
|
void QgsGrassEdit::splitLine(void) { startTool(QgsGrassEdit::SPLIT_LINE); }
|
|
void QgsGrassEdit::moveLine(void) { startTool(QgsGrassEdit::MOVE_LINE); }
|
|
void QgsGrassEdit::deleteLine(void) { startTool(QgsGrassEdit::DELETE_LINE); }
|
|
void QgsGrassEdit::editCats(void) { startTool(QgsGrassEdit::EDIT_CATS); }
|
|
void QgsGrassEdit::editAttributes(void) { startTool(QgsGrassEdit::EDIT_ATTRIBUTES); }
|
|
|
|
void QgsGrassEdit::startTool(int tool)
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::startTool() tool = " << tool << std::endl;
|
|
#endif
|
|
|
|
// Delete last dynamic drawing from canvas
|
|
eraseDynamic();
|
|
if ( mSelectedLine > 0 )
|
|
displayElement ( mSelectedLine, mSymb[mLineSymb[mSelectedLine]], mSize );
|
|
|
|
/* Close old tool */
|
|
switch ( mTool ) {
|
|
case QgsGrassEdit::NEW_LINE:
|
|
case QgsGrassEdit::NEW_BOUNDARY:
|
|
/* Write the line to vector */
|
|
if ( mEditPoints->n_points > 1 ) {
|
|
int type;
|
|
|
|
if ( mTool == QgsGrassEdit::NEW_LINE )
|
|
type = GV_LINE;
|
|
else // boundary
|
|
type = GV_BOUNDARY;
|
|
|
|
int line;
|
|
line = writeLine ( type, mEditPoints );
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
if ( mAttributes ) delete mAttributes;
|
|
mAttributes = new QgsGrassAttributes ( this, mProvider, line, mQgisApp );
|
|
for ( int i = 0; i < mCats->n_cats; i++ ) {
|
|
addAttributes ( mCats->field[i], mCats->cat[i] );
|
|
}
|
|
mAttributes->show();
|
|
}
|
|
setCanvasPropmt( tr("New vertex"), "", "");
|
|
break;
|
|
|
|
case QgsGrassEdit::NONE:
|
|
case QgsGrassEdit::NEW_POINT:
|
|
case QgsGrassEdit::NEW_CENTROID:
|
|
case QgsGrassEdit::MOVE_VERTEX:
|
|
case QgsGrassEdit::ADD_VERTEX:
|
|
case QgsGrassEdit::DELETE_VERTEX:
|
|
case QgsGrassEdit::SPLIT_LINE:
|
|
case QgsGrassEdit::MOVE_LINE:
|
|
case QgsGrassEdit::DELETE_LINE:
|
|
case QgsGrassEdit::EDIT_CATS:
|
|
case QgsGrassEdit::EDIT_ATTRIBUTES:
|
|
break;
|
|
default:
|
|
std::cerr << "Unknown tool" << std::endl;
|
|
break;
|
|
}
|
|
|
|
// All necessary data were written -> reset mEditPoints etc.
|
|
Vect_reset_line ( mEditPoints );
|
|
mSelectedLine = 0;
|
|
|
|
// TODO: mTool != NEW_LINE is a hack for lines until more buttons can be recieved
|
|
if ( mAttributes && mTool != QgsGrassEdit::NEW_LINE && mTool != QgsGrassEdit::NEW_BOUNDARY ) {
|
|
delete mAttributes;
|
|
mAttributes = 0;
|
|
}
|
|
|
|
// Start new tool
|
|
mTool = tool;
|
|
|
|
switch ( mTool ) {
|
|
case QgsGrassEdit::NONE:
|
|
break;
|
|
case QgsGrassEdit::NEW_POINT:
|
|
setCanvasPropmt( tr("New point"), "", "" );
|
|
break;
|
|
case QgsGrassEdit::NEW_CENTROID:
|
|
setCanvasPropmt( tr("New centroid"), "", "" );
|
|
break;
|
|
case QgsGrassEdit::NEW_LINE:
|
|
case QgsGrassEdit::NEW_BOUNDARY:
|
|
setCanvasPropmt( tr("New vertex"), "", "");
|
|
break;
|
|
case QgsGrassEdit::MOVE_VERTEX:
|
|
setCanvasPropmt( tr("Select vertex"), "", "" );
|
|
break;
|
|
case QgsGrassEdit::ADD_VERTEX:
|
|
setCanvasPropmt( tr("Select line segment"), "", "" );
|
|
break;
|
|
case QgsGrassEdit::DELETE_VERTEX:
|
|
setCanvasPropmt( tr("Select vertex"), "", "" );
|
|
break;
|
|
case QgsGrassEdit::SPLIT_LINE:
|
|
setCanvasPropmt( tr("Select position on line"), "", "" );
|
|
break;
|
|
|
|
case QgsGrassEdit::MOVE_LINE:
|
|
case QgsGrassEdit::DELETE_LINE:
|
|
case QgsGrassEdit::EDIT_ATTRIBUTES:
|
|
setCanvasPropmt( tr("Select element"), "", "" );
|
|
break;
|
|
case QgsGrassEdit::EDIT_CATS:
|
|
mTool = QgsGrassEdit::NONE;
|
|
QMessageBox::warning( 0, "Warning", "Tool not yet implemented." );
|
|
break;
|
|
default:
|
|
std::cerr << "Unknown tool" << std::endl;
|
|
break;
|
|
}
|
|
|
|
mCanvas->setMapTool ( QGis::EmitPoint );
|
|
mCanvas->setCursor ( Qt::CrossCursor );
|
|
}
|
|
|
|
void QgsGrassEdit::mouseEventReceiverClick( QgsPoint & point, Qt::ButtonState button )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::mouseEventReceiverClick()" << std::endl;
|
|
#endif
|
|
|
|
double thresh = threshold();
|
|
QPen pen;
|
|
|
|
switch ( mTool ) {
|
|
case QgsGrassEdit::NEW_POINT:
|
|
case QgsGrassEdit::NEW_CENTROID:
|
|
Vect_reset_line ( mEditPoints );
|
|
snap ( point );
|
|
Vect_append_point ( mEditPoints, point.x(), point.y(), 0.0 );
|
|
|
|
int type;
|
|
if ( mTool == QgsGrassEdit::NEW_POINT )
|
|
type = GV_POINT;
|
|
else // centroid
|
|
type = GV_CENTROID;
|
|
|
|
int line;
|
|
line = writeLine ( type, mEditPoints );
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
if ( mAttributes ) delete mAttributes;
|
|
mAttributes = new QgsGrassAttributes ( this, mProvider, line, mQgisApp );
|
|
for ( int i = 0; i < mCats->n_cats; i++ ) {
|
|
addAttributes ( mCats->field[i], mCats->cat[i] );
|
|
}
|
|
mAttributes->show();
|
|
break;
|
|
|
|
case QgsGrassEdit::NEW_LINE:
|
|
case QgsGrassEdit::NEW_BOUNDARY:
|
|
switch ( button ) {
|
|
case Qt::LeftButton:
|
|
snap ( point );
|
|
Vect_append_point ( mEditPoints, point.x(), point.y(), 0.0 );
|
|
break;
|
|
case Qt::MidButton:
|
|
if ( mEditPoints->n_points > 0 ) {
|
|
eraseDynamic();
|
|
mEditPoints->n_points--;
|
|
}
|
|
break;
|
|
case Qt::RightButton:
|
|
eraseDynamic();
|
|
if ( mEditPoints->n_points > 1 ) {
|
|
int type;
|
|
|
|
if ( mTool == QgsGrassEdit::NEW_LINE )
|
|
type = GV_LINE;
|
|
else // boundary
|
|
type = GV_BOUNDARY;
|
|
|
|
int line;
|
|
line = writeLine ( type, mEditPoints );
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
if ( mAttributes ) delete mAttributes;
|
|
mAttributes = new QgsGrassAttributes ( this, mProvider, line, mQgisApp );
|
|
for ( int i = 0; i < mCats->n_cats; i++ ) {
|
|
addAttributes ( mCats->field[i], mCats->cat[i] );
|
|
}
|
|
mAttributes->show();
|
|
}
|
|
Vect_reset_line ( mEditPoints );
|
|
break;
|
|
}
|
|
if ( mEditPoints->n_points == 0 ) {
|
|
setCanvasPropmt( tr("New point"), "", "");
|
|
} else if ( mEditPoints->n_points == 1 ) {
|
|
setCanvasPropmt( tr("New point"), tr("Undo last point"), "" );
|
|
} else if ( mEditPoints->n_points > 1 ) {
|
|
setCanvasPropmt( tr("New point"), tr("Undo last point"), tr("Close line"));
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::DELETE_LINE:
|
|
switch ( button ) {
|
|
case Qt::LeftButton:
|
|
// Delete previously selected line
|
|
if ( mSelectedLine > 0 ) {
|
|
eraseElement ( mSelectedLine );
|
|
mProvider->deleteLine ( mSelectedLine );
|
|
updateSymb();
|
|
displayUpdated();
|
|
}
|
|
|
|
// Select new/next line
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_POINT|GV_CENTROID, thresh );
|
|
|
|
if ( mSelectedLine == 0 )
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_LINE|GV_BOUNDARY, thresh );
|
|
|
|
if ( mSelectedLine ) { // highlite, propmt
|
|
displayElement ( mSelectedLine, mSymb[SYMB_HIGHLIGHT], mSize );
|
|
setCanvasPropmt( tr("Delete selected / select next"), "", tr("Release selected") );
|
|
} else {
|
|
setCanvasPropmt( tr("Select element"), "", "" );
|
|
}
|
|
break;
|
|
|
|
case Qt::RightButton:
|
|
displayElement ( mSelectedLine, mSymb[mLineSymb[mSelectedLine]], mSize );
|
|
mSelectedLine = 0;
|
|
setCanvasPropmt( tr("Select element"), "", "" );
|
|
break;
|
|
|
|
case Qt::MidButton:
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case QgsGrassEdit::MOVE_LINE:
|
|
switch ( button ) {
|
|
case Qt::LeftButton:
|
|
// Move previously selected line
|
|
if ( mSelectedLine > 0 ) {
|
|
eraseDynamic();
|
|
eraseElement ( mSelectedLine );
|
|
|
|
// Transform coordinates
|
|
int type = mProvider->readLine ( mPoints, mCats, mSelectedLine );
|
|
for ( int i = 0; i < mPoints->n_points; i++ ) {
|
|
mPoints->x[i] += point.x() - mLastPoint.x();
|
|
mPoints->y[i] += point.y() - mLastPoint.y();
|
|
}
|
|
|
|
mProvider->rewriteLine ( mSelectedLine, type, mPoints, mCats );
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
|
|
setCanvasPropmt( tr("Select element"), "", "" );
|
|
} else {
|
|
// Select new/next line
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_POINT|GV_CENTROID, thresh );
|
|
|
|
if ( mSelectedLine == 0 )
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_LINE|GV_BOUNDARY, thresh );
|
|
|
|
if ( mSelectedLine ) { // highlite
|
|
mProvider->readLine ( mEditPoints, NULL, mSelectedLine );
|
|
displayElement ( mSelectedLine, mSymb[SYMB_HIGHLIGHT], mSize );
|
|
setCanvasPropmt( tr("New location"), "", tr("Release selected") );
|
|
} else {
|
|
setCanvasPropmt( tr("Select element"), "", "" );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Qt::RightButton:
|
|
eraseDynamic();
|
|
displayElement ( mSelectedLine, mSymb[mLineSymb[mSelectedLine]], mSize );
|
|
mSelectedLine = 0;
|
|
setCanvasPropmt( tr("Select element"), "", "" );
|
|
break;
|
|
|
|
case Qt::MidButton:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::MOVE_VERTEX:
|
|
switch ( button ) {
|
|
case Qt::LeftButton:
|
|
// Move previously selected vertex
|
|
if ( mSelectedLine > 0 ) {
|
|
eraseDynamic();
|
|
eraseElement ( mSelectedLine );
|
|
|
|
// Move vertex
|
|
int type = mProvider->readLine ( mPoints, mCats, mSelectedLine );
|
|
snap ( point );
|
|
mPoints->x[mSelectedPart] = point.x();
|
|
mPoints->y[mSelectedPart] = point.y();
|
|
|
|
Vect_line_prune ( mPoints );
|
|
mProvider->rewriteLine ( mSelectedLine, type, mPoints, mCats );
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
|
|
setCanvasPropmt( tr("Select vertex"), "", "" );
|
|
} else {
|
|
// Select new line
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_LINES, thresh );
|
|
|
|
if ( mSelectedLine ) { // highlite
|
|
mProvider->readLine ( mEditPoints, NULL, mSelectedLine );
|
|
displayElement ( mSelectedLine, mSymb[SYMB_HIGHLIGHT], mSize );
|
|
|
|
double xl, yl; // nearest point on the line
|
|
|
|
// Note first segment is 1!
|
|
mSelectedPart = Vect_line_distance ( mEditPoints, point.x(), point.y(), 0.0, 0,
|
|
&xl, &yl, NULL, NULL, NULL, NULL );
|
|
|
|
double dist1 = Vect_points_distance ( xl, yl, 0.0, mEditPoints->x[mSelectedPart-1],
|
|
mEditPoints->y[mSelectedPart-1], 0.0, 0);
|
|
double dist2 = Vect_points_distance ( xl, yl, 0.0, mEditPoints->x[mSelectedPart],
|
|
mEditPoints->y[mSelectedPart], 0.0, 0);
|
|
|
|
if ( dist1 < dist2 ) mSelectedPart--;
|
|
|
|
setCanvasPropmt( tr("Select new position"), "", "Release vertex" );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Qt::RightButton:
|
|
eraseDynamic();
|
|
displayElement ( mSelectedLine, mSymb[mLineSymb[mSelectedLine]], mSize );
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
|
|
setCanvasPropmt( tr("Select vertex"), "", "" );
|
|
break;
|
|
|
|
case Qt::MidButton:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::ADD_VERTEX:
|
|
switch ( button ) {
|
|
case Qt::LeftButton:
|
|
// Add vertex to previously selected line
|
|
if ( mSelectedLine > 0 ) {
|
|
eraseDynamic();
|
|
eraseElement ( mSelectedLine );
|
|
|
|
// Move vertex
|
|
int type = mProvider->readLine ( mPoints, mCats, mSelectedLine );
|
|
|
|
if ( mAddVertexEnd && mSelectedPart == mEditPoints->n_points-1 ) {
|
|
snap ( point );
|
|
Vect_append_point ( mPoints, point.x(), point.y(), 0.0 );
|
|
} else {
|
|
Vect_line_insert_point ( mPoints, mSelectedPart, point.x(), point.y(), 0.0 );
|
|
}
|
|
|
|
Vect_line_prune ( mPoints );
|
|
mProvider->rewriteLine ( mSelectedLine, type, mPoints, mCats );
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
|
|
setCanvasPropmt( tr("Select line segment"), "", "" );
|
|
} else {
|
|
// Select new line
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_LINES, thresh );
|
|
|
|
if ( mSelectedLine ) { // highlite
|
|
mProvider->readLine ( mEditPoints, NULL, mSelectedLine );
|
|
displayElement ( mSelectedLine, mSymb[SYMB_HIGHLIGHT], mSize );
|
|
|
|
double xl, yl; // nearest point on the line
|
|
|
|
// Note first segment is 1!
|
|
mSelectedPart = Vect_line_distance ( mEditPoints, point.x(), point.y(), 0.0, 0,
|
|
&xl, &yl, NULL, NULL, NULL, NULL );
|
|
|
|
double dist1 = Vect_points_distance ( xl, yl, 0.0, mEditPoints->x[mSelectedPart-1],
|
|
mEditPoints->y[mSelectedPart-1], 0.0, 0);
|
|
double dist2 = Vect_points_distance ( xl, yl, 0.0, mEditPoints->x[mSelectedPart],
|
|
mEditPoints->y[mSelectedPart], 0.0, 0);
|
|
|
|
double maxdist = (dist1 + dist2)/4;
|
|
|
|
if ( mSelectedPart == 1 && dist1 < maxdist ) {
|
|
mSelectedPart = 0;
|
|
mAddVertexEnd = true;
|
|
} else if ( mSelectedPart == mEditPoints->n_points-1 && dist2 < maxdist ) {
|
|
mAddVertexEnd = true;
|
|
} else {
|
|
mAddVertexEnd = false;
|
|
}
|
|
|
|
setCanvasPropmt( tr("New vertex position"), "", tr("Release") );
|
|
} else {
|
|
setCanvasPropmt( tr("Select line segment"), "", "" );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Qt::RightButton:
|
|
eraseDynamic();
|
|
displayElement ( mSelectedLine, mSymb[mLineSymb[mSelectedLine]], mSize );
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
|
|
setCanvasPropmt( tr("Select line segment"), "", "" );
|
|
break;
|
|
|
|
case Qt::MidButton:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
|
|
case QgsGrassEdit::DELETE_VERTEX:
|
|
switch ( button ) {
|
|
case Qt::LeftButton:
|
|
// Delete previously selected vertex
|
|
if ( mSelectedLine > 0 ) {
|
|
eraseDynamic();
|
|
eraseElement ( mSelectedLine );
|
|
|
|
// Move vertex
|
|
int type = mProvider->readLine ( mPoints, mCats, mSelectedLine );
|
|
Vect_line_delete_point ( mPoints, mSelectedPart );
|
|
|
|
mProvider->rewriteLine ( mSelectedLine, type, mPoints, mCats );
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
|
|
setCanvasPropmt( tr("Select vertex"), "", "" );
|
|
} else {
|
|
// Select new/next line
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_LINES, thresh );
|
|
|
|
if ( mSelectedLine ) { // highlite
|
|
mProvider->readLine ( mEditPoints, NULL, mSelectedLine );
|
|
|
|
displayElement ( mSelectedLine, mSymb[SYMB_HIGHLIGHT], mSize );
|
|
|
|
double xl, yl; // nearest point on the line
|
|
|
|
// Note first segment is 1!
|
|
mSelectedPart = Vect_line_distance ( mEditPoints, point.x(), point.y(), 0.0, 0,
|
|
&xl, &yl, NULL, NULL, NULL, NULL );
|
|
|
|
double dist1 = Vect_points_distance ( xl, yl, 0.0, mEditPoints->x[mSelectedPart-1],
|
|
mEditPoints->y[mSelectedPart-1], 0.0, 0);
|
|
double dist2 = Vect_points_distance ( xl, yl, 0.0, mEditPoints->x[mSelectedPart],
|
|
mEditPoints->y[mSelectedPart], 0.0, 0);
|
|
|
|
if ( dist1 < dist2 ) mSelectedPart--;
|
|
|
|
displayDynamic ( mEditPoints->x[mSelectedPart], mEditPoints->y[mSelectedPart],
|
|
QgsGrassEdit::ICON_BOX, mSize );
|
|
|
|
setCanvasPropmt( tr("Delete vertex"), "", tr("Release vertex") );
|
|
} else {
|
|
setCanvasPropmt( tr("Select vertex"), "", "" );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case Qt::RightButton:
|
|
eraseDynamic();
|
|
displayElement ( mSelectedLine, mSymb[mLineSymb[mSelectedLine]], mSize );
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
|
|
setCanvasPropmt( tr("Select vertex"), "", "" );
|
|
break;
|
|
|
|
case Qt::MidButton:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::SPLIT_LINE:
|
|
switch ( button ) {
|
|
case Qt::LeftButton:
|
|
// Split previously selected line
|
|
if ( mSelectedLine > 0 ) {
|
|
eraseDynamic();
|
|
eraseElement ( mSelectedLine );
|
|
|
|
int type = mProvider->readLine ( mPoints, mCats, mSelectedLine );
|
|
|
|
double xl, yl;
|
|
Vect_line_distance ( mPoints, mLastPoint.x(), mLastPoint.y(), 0.0, 0,
|
|
&xl, &yl, NULL, NULL, NULL, NULL );
|
|
|
|
mPoints->n_points = mSelectedPart;
|
|
Vect_append_point ( mPoints, xl, yl, 0.0 );
|
|
mProvider->rewriteLine ( mSelectedLine, type, mPoints, mCats );
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
Vect_reset_line ( mPoints );
|
|
Vect_append_point ( mPoints, xl, yl, 0.0 );
|
|
for ( int i = mSelectedPart; i < mEditPoints->n_points; i++ ) {
|
|
Vect_append_point ( mPoints, mEditPoints->x[i], mEditPoints->y[i], 0.0 );
|
|
}
|
|
|
|
mProvider->writeLine ( type, mPoints, mCats );
|
|
|
|
updateSymb();
|
|
displayUpdated();
|
|
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
setCanvasPropmt( tr("Select position on line"), "", "" );
|
|
} else {
|
|
// Select new/next line
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_LINES, thresh );
|
|
|
|
if ( mSelectedLine ) { // highlite
|
|
mProvider->readLine ( mEditPoints, NULL, mSelectedLine );
|
|
|
|
displayElement ( mSelectedLine, mSymb[SYMB_HIGHLIGHT], mSize );
|
|
|
|
double xl, yl; // nearest point on the line
|
|
|
|
// Note first segment is 1!
|
|
mSelectedPart = Vect_line_distance ( mEditPoints, point.x(), point.y(), 0.0, 0,
|
|
&xl, &yl, NULL, NULL, NULL, NULL );
|
|
|
|
displayDynamic ( xl, yl, QgsGrassEdit::ICON_X, mSize );
|
|
|
|
setCanvasPropmt( tr("Split the line"), "", tr("Release the line") );
|
|
} else {
|
|
setCanvasPropmt( tr("Select point on line"), "", "" );
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case Qt::RightButton:
|
|
eraseDynamic();
|
|
displayElement ( mSelectedLine, mSymb[mLineSymb[mSelectedLine]], mSize );
|
|
mSelectedLine = 0;
|
|
Vect_reset_line ( mEditPoints );
|
|
|
|
setCanvasPropmt( tr("Select point on line"), "", "" );
|
|
break;
|
|
|
|
case Qt::MidButton:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::EDIT_ATTRIBUTES:
|
|
// Redraw previously selected line
|
|
if ( mSelectedLine > 0 ) {
|
|
displayElement ( mSelectedLine, mSymb[mLineSymb[mSelectedLine]], mSize );
|
|
}
|
|
|
|
// Select new/next line
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_POINT|GV_CENTROID, thresh );
|
|
|
|
if ( mSelectedLine == 0 )
|
|
mSelectedLine = mProvider->findLine ( point.x(), point.y(), GV_LINE|GV_BOUNDARY, thresh );
|
|
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "mSelectedLine = " << mSelectedLine << std::endl;
|
|
#endif
|
|
|
|
if ( mAttributes ) {
|
|
delete mAttributes;
|
|
mAttributes = 0;
|
|
}
|
|
|
|
if ( mSelectedLine ) { // highlite
|
|
displayElement ( mSelectedLine, mSymb[SYMB_HIGHLIGHT], mSize );
|
|
|
|
mProvider->readLine ( NULL, mCats, mSelectedLine );
|
|
|
|
mAttributes = new QgsGrassAttributes ( this, mProvider, mSelectedLine, mQgisApp );
|
|
for ( int i = 0; i < mCats->n_cats; i++ ) {
|
|
addAttributes ( mCats->field[i], mCats->cat[i] );
|
|
}
|
|
mAttributes->show();
|
|
}
|
|
|
|
break;
|
|
|
|
case QgsGrassEdit::EDIT_CATS:
|
|
std::cerr << "Tool not yet implemented." << std::endl;
|
|
break;
|
|
|
|
case QgsGrassEdit::NONE:
|
|
break;
|
|
// nothing to do
|
|
|
|
default:
|
|
std::cerr << "Unknown tool" << std::endl;
|
|
break;
|
|
}
|
|
|
|
// Set last click
|
|
mLastPoint = point;
|
|
|
|
statusBar()->message(mCanvasPrompt);
|
|
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "n_points = " << mEditPoints->n_points << std::endl;
|
|
#endif
|
|
|
|
}
|
|
|
|
void QgsGrassEdit::addAttributes ( int field, int cat )
|
|
{
|
|
QString *key = mProvider->key ( field );
|
|
|
|
QString lab;
|
|
lab.sprintf ( "%d:%d", field, cat );
|
|
int tab = mAttributes->addTab( lab );
|
|
mAttributes->setField ( tab, field );
|
|
|
|
QString catLabel;
|
|
if ( key->isEmpty() ) {
|
|
catLabel = "Category";
|
|
} else {
|
|
catLabel = *key;
|
|
}
|
|
mAttributes->setCat ( tab, catLabel, cat );
|
|
|
|
if ( !key->isEmpty() ) { // Database link defined
|
|
std::vector<QgsField> *cols = mProvider->columns ( field );
|
|
|
|
if ( cols->size() == 0 ) {
|
|
QString str;
|
|
str.setNum( field );
|
|
QMessageBox::warning( 0, "Warning", "Cannot describe table for field " + str );
|
|
} else {
|
|
std::vector<QgsFeatureAttribute> *atts =
|
|
mProvider->attributes ( field, cat );
|
|
|
|
if ( atts->size() == 0 ) { // cannot select attributes
|
|
mAttributes->addTextRow ( tab, "WARNING: ATTRIBUTES MISSING" );
|
|
} else {
|
|
int size;
|
|
if ( atts->size() < cols->size() )
|
|
size = atts->size();
|
|
else
|
|
size = cols->size();
|
|
|
|
for ( int j = 0; j < cols->size(); j++ ) {
|
|
QgsField col = (*cols)[j];
|
|
QgsFeatureAttribute att = (*atts)[j];
|
|
std::cerr << " name = " << col.name() << std::endl;
|
|
|
|
if ( col.name() != *key ) {
|
|
std::cerr << " value = " << att.fieldValue() << std::endl;
|
|
mAttributes->addAttribute ( tab, col.name(), att.fieldValue(), col.type() );
|
|
}
|
|
}
|
|
}
|
|
delete atts;
|
|
}
|
|
delete cols;
|
|
}
|
|
}
|
|
|
|
void QgsGrassEdit::addCat ( int line )
|
|
{
|
|
int mode = mCatModeBox->currentItem();
|
|
int field = mFieldBox->currentText().toInt();
|
|
int cat = mCatEntry->text().toInt();
|
|
|
|
int type = mProvider->readLine ( mPoints, mCats, line );
|
|
if ( mode == CAT_MODE_NEXT || mode == CAT_MODE_MANUAL ) {
|
|
Vect_cat_set ( mCats, field, cat );
|
|
}
|
|
|
|
line = mProvider->rewriteLine ( line, type, mPoints, mCats );
|
|
if ( mAttributes ) mAttributes->setLine ( line );
|
|
updateSymb();
|
|
increaseMaxCat();
|
|
|
|
// Insert new DB record if link is defined and the record for this cat does not exist
|
|
QString *key = mProvider->key ( field );
|
|
|
|
if ( !key->isEmpty() ) { // Database link defined
|
|
std::vector<QgsFeatureAttribute> *atts = mProvider->attributes ( field, cat );
|
|
|
|
if ( atts->size() == 0 ) { // Nothing selected
|
|
QString *error = mProvider->insertAttributes ( field, cat );
|
|
|
|
if ( !error->isEmpty() ) {
|
|
QMessageBox::warning( 0, "Warning", *error );
|
|
}
|
|
delete error;
|
|
}
|
|
|
|
delete atts;
|
|
}
|
|
|
|
addAttributes( field, cat );
|
|
}
|
|
|
|
void QgsGrassEdit::deleteCat ( int line, int field, int cat )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::deleteCat" << std::endl;
|
|
#endif
|
|
|
|
int type = mProvider->readLine ( mPoints, mCats, line );
|
|
Vect_field_cat_del ( mCats, field, cat );
|
|
|
|
line = mProvider->rewriteLine ( line, type, mPoints, mCats );
|
|
if ( mAttributes ) mAttributes->setLine ( line );
|
|
updateSymb();
|
|
}
|
|
|
|
void QgsGrassEdit::mouseEventReceiverMove ( QgsPoint & newPoint )
|
|
{
|
|
#if QGISDEBUG > 3
|
|
std::cerr << "QgsGrassEdit::mouseEventReceiverMove() mTool = " << mTool << std::endl;
|
|
#endif
|
|
|
|
if ( mCanvas->mapTool() != QGis::EmitPoint ) return;
|
|
|
|
statusBar()->message(mCanvasPrompt);
|
|
|
|
switch ( mTool ) {
|
|
case QgsGrassEdit::NEW_LINE:
|
|
case QgsGrassEdit::NEW_BOUNDARY:
|
|
if ( mEditPoints->n_points > 0 ) {
|
|
/* Draw the line with new segment */
|
|
Vect_reset_line ( mPoints );
|
|
Vect_append_points ( mPoints, mEditPoints, GV_FORWARD );
|
|
Vect_append_point ( mPoints, static_cast<int>(newPoint.x()),
|
|
static_cast<int>(newPoint.y()), 0.0 );
|
|
displayDynamic ( mPoints );
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::MOVE_LINE:
|
|
// Move previously selected line
|
|
if ( mSelectedLine > 0 ) {
|
|
// Transform coordinates
|
|
Vect_reset_line ( mPoints );
|
|
Vect_append_points ( mPoints, mEditPoints, GV_FORWARD );
|
|
|
|
for ( int i = 0; i < mPoints->n_points; i++ ) {
|
|
mPoints->x[i] += newPoint.x() - mLastPoint.x();
|
|
mPoints->y[i] += newPoint.y() - mLastPoint.y();
|
|
}
|
|
|
|
displayDynamic ( mPoints );
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::MOVE_VERTEX:
|
|
if ( mSelectedLine > 0 ) {
|
|
// Transform coordinates
|
|
Vect_reset_line ( mPoints );
|
|
if ( mSelectedPart == 0 ) {
|
|
Vect_append_point ( mPoints, mEditPoints->x[1], mEditPoints->y[1], 0.0 );
|
|
Vect_append_point ( mPoints, newPoint.x(), newPoint.y(), 0.0 );
|
|
} else if ( mSelectedPart == mEditPoints->n_points-1 ) {
|
|
Vect_append_point ( mPoints, mEditPoints->x[mSelectedPart-1],
|
|
mEditPoints->y[mSelectedPart-1], 0.0 );
|
|
Vect_append_point ( mPoints, newPoint.x(), newPoint.y(), 0.0 );
|
|
} else {
|
|
Vect_append_point ( mPoints, mEditPoints->x[mSelectedPart-1],
|
|
mEditPoints->y[mSelectedPart-1], 0.0 );
|
|
Vect_append_point ( mPoints, newPoint.x(), newPoint.y(), 0.0 );
|
|
Vect_append_point ( mPoints, mEditPoints->x[mSelectedPart+1],
|
|
mEditPoints->y[mSelectedPart+1], 0.0 );
|
|
}
|
|
for (int i = 0; i < mPoints->n_points; i++ ) {
|
|
std::cerr << mPoints->x[i] << " " << mPoints->y[i] << std::endl;
|
|
}
|
|
|
|
displayDynamic ( mPoints );
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::ADD_VERTEX:
|
|
if ( mSelectedLine > 0 ) {
|
|
Vect_reset_line ( mPoints );
|
|
if ( mAddVertexEnd ) {
|
|
Vect_append_point ( mPoints, mEditPoints->x[mSelectedPart],
|
|
mEditPoints->y[mSelectedPart], 0.0 );
|
|
Vect_append_point ( mPoints, newPoint.x(), newPoint.y(), 0.0 );
|
|
} else {
|
|
Vect_append_point ( mPoints, mEditPoints->x[mSelectedPart-1],
|
|
mEditPoints->y[mSelectedPart-1], 0.0 );
|
|
Vect_append_point ( mPoints, newPoint.x(), newPoint.y(), 0.0 );
|
|
Vect_append_point ( mPoints, mEditPoints->x[mSelectedPart],
|
|
mEditPoints->y[mSelectedPart], 0.0 );
|
|
}
|
|
for (int i = 0; i < mPoints->n_points; i++ ) {
|
|
std::cerr << mPoints->x[i] << " " << mPoints->y[i] << std::endl;
|
|
}
|
|
|
|
displayDynamic ( mPoints );
|
|
}
|
|
break;
|
|
|
|
case QgsGrassEdit::NONE:
|
|
case QgsGrassEdit::NEW_POINT:
|
|
case QgsGrassEdit::NEW_CENTROID:
|
|
case QgsGrassEdit::DELETE_VERTEX:
|
|
case QgsGrassEdit::SPLIT_LINE:
|
|
case QgsGrassEdit::DELETE_LINE:
|
|
case QgsGrassEdit::EDIT_CATS:
|
|
case QgsGrassEdit::EDIT_ATTRIBUTES:
|
|
// Nothing to do
|
|
break;
|
|
default:
|
|
std::cerr << "Unknown tool" << std::endl;
|
|
break;
|
|
}
|
|
mCanvas->repaint(false);
|
|
statusBar()->message(mCanvasPrompt);
|
|
}
|
|
|
|
void QgsGrassEdit::postRender(QPainter *painter)
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::postRender" << std::endl;
|
|
#endif
|
|
|
|
displayMap();
|
|
|
|
// Redisplay highlighted
|
|
if ( mSelectedLine ) {
|
|
displayElement ( mSelectedLine, mSymb[SYMB_HIGHLIGHT], mSize );
|
|
}
|
|
|
|
// Redisplay current dynamic
|
|
displayLastDynamic ( );
|
|
}
|
|
|
|
void QgsGrassEdit::displayMap (void)
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::displayMap" << std::endl;
|
|
#endif
|
|
|
|
mTransform = mCanvas->getCoordinateTransform();
|
|
|
|
|
|
QPainter *painter = new QPainter();
|
|
painter->begin(mPixmap);
|
|
|
|
// Display lines
|
|
int nlines = mProvider->numLines();
|
|
|
|
QPen pen;
|
|
|
|
// TODO?: 2 loops, first lines, then points
|
|
for ( int line = 1; line <= nlines; line++ ) {
|
|
displayElement ( line, mSymb[mLineSymb[line]], mSize, painter );
|
|
}
|
|
|
|
// Display nodes
|
|
int nnodes = mProvider->numNodes();
|
|
|
|
pen.setColor(QColor(255,0,0));
|
|
|
|
if ( mSymbDisplay[SYMB_NODE_1] || mSymbDisplay[SYMB_NODE_2] ) {
|
|
for ( int node = 1; node <= nnodes; node++ ) {
|
|
if ( mNodeSymb[node] == SYMB_NODE_0 ) continue; // do not display nodes with points only
|
|
displayNode ( node, mSymb[mNodeSymb[node]], mSize, painter );
|
|
}
|
|
}
|
|
|
|
painter->end();
|
|
mCanvas->repaint(false);
|
|
}
|
|
|
|
void QgsGrassEdit::displayUpdated (void)
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::displayUpdated" << std::endl;
|
|
#endif
|
|
|
|
mTransform = mCanvas->getCoordinateTransform();
|
|
|
|
QPainter *painter = new QPainter();
|
|
painter->begin(mPixmap);
|
|
|
|
// Display lines
|
|
int nlines = mProvider->numUpdatedLines();
|
|
|
|
for ( int i = 0; i < nlines; i++ ) {
|
|
int line = mProvider->updatedLine(i);
|
|
if ( !(mProvider->lineAlive(line)) ) continue;
|
|
|
|
displayElement ( line, mSymb[mLineSymb[line]], mSize, painter );
|
|
}
|
|
|
|
// Display nodes
|
|
int nnodes = mProvider->numUpdatedNodes();
|
|
for ( int i = 0; i < nnodes; i++ ) {
|
|
int node = mProvider->updatedNode(i);
|
|
if ( !(mProvider->nodeAlive(node)) ) continue;
|
|
if ( mNodeSymb[node] == SYMB_NODE_0 ) continue; // do not display nodes with points only
|
|
displayNode ( node, mSymb[mNodeSymb[node]], mSize, painter );
|
|
}
|
|
|
|
painter->end();
|
|
mCanvas->repaint(false);
|
|
}
|
|
|
|
void QgsGrassEdit::displayElement ( int line, const QPen & pen, int size, QPainter *painter)
|
|
{
|
|
#if QGISDEBUG > 3
|
|
std::cerr << "QgsGrassEdit::displayElement() line = " << line << std::endl;
|
|
#endif
|
|
|
|
if ( !mSymbDisplay[mLineSymb[line]] ) return;
|
|
|
|
int type = mProvider->readLine ( mPoints, NULL, line );
|
|
if ( type < 0 ) return;
|
|
|
|
QPainter *myPainter;
|
|
if ( !painter ) {
|
|
myPainter = new QPainter();
|
|
myPainter->begin(mPixmap);
|
|
} else {
|
|
myPainter = painter;
|
|
}
|
|
|
|
if ( type & GV_POINTS ) {
|
|
displayIcon ( mPoints->x[0], mPoints->y[0], pen, QgsGrassEdit::ICON_CROSS, size, painter );
|
|
} else { // line
|
|
QgsPoint point;
|
|
QPointArray pointArray(mPoints->n_points);
|
|
|
|
for ( int i = 0; i < mPoints->n_points; i++ ) {
|
|
point.setX(mPoints->x[i]);
|
|
point.setY(mPoints->y[i]);
|
|
mTransform->transform(&point);
|
|
pointArray.setPoint( i, static_cast<int>(point.x()),
|
|
static_cast<int>(point.y()) );
|
|
}
|
|
|
|
myPainter->setPen ( pen );
|
|
myPainter->drawPolyline ( pointArray );
|
|
}
|
|
|
|
if ( !painter ) {
|
|
myPainter->end();
|
|
mCanvas->repaint(false);
|
|
delete myPainter;
|
|
}
|
|
}
|
|
|
|
void QgsGrassEdit::eraseElement ( int line )
|
|
{
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "QgsGrassEdit::eraseElement() line = " << line << std::endl;
|
|
#endif
|
|
|
|
int type = mProvider->readLine ( NULL, NULL, line );
|
|
if ( type < 0 ) return;
|
|
|
|
// Erase line
|
|
displayElement ( line, mSymb[SYMB_BACKGROUND], mSize );
|
|
|
|
// Erase nodes
|
|
if ( type & GV_LINES ) {
|
|
int node1, node2;
|
|
mProvider->lineNodes( line, &node1, &node2 );
|
|
|
|
double x, y;
|
|
mProvider->nodeCoor( node1, &x, &y );
|
|
displayIcon ( x, y, mSymb[SYMB_BACKGROUND], QgsGrassEdit::ICON_X, mSize );
|
|
|
|
mProvider->nodeCoor( node2, &x, &y );
|
|
displayIcon ( x, y, mSymb[SYMB_BACKGROUND], QgsGrassEdit::ICON_X, mSize );
|
|
}
|
|
}
|
|
|
|
void QgsGrassEdit::eraseDynamic ( void )
|
|
{
|
|
displayDynamic ( 0, 0.0, 0.0, ICON_NONE, 0 );
|
|
}
|
|
|
|
void QgsGrassEdit::displayDynamic ( struct line_pnts *Points )
|
|
{
|
|
displayDynamic ( Points, 0.0, 0.0, ICON_NONE, 0 );
|
|
}
|
|
|
|
void QgsGrassEdit::displayDynamic ( double x, double y, int type, int size )
|
|
{
|
|
#if QGISDEBUG > 3
|
|
std::cerr << "QgsGrassEdit::displayDynamic icon" << std::endl;
|
|
#endif
|
|
|
|
displayDynamic ( 0, x, y, type, size );
|
|
}
|
|
|
|
void QgsGrassEdit::displayDynamic ( struct line_pnts *Points, double x, double y, int type, int size )
|
|
{
|
|
std::cerr << "QgsGrassEdit::displayDynamic Points = " << Points << " type = " << type << std::endl;
|
|
#if QGISDEBUG > 3
|
|
std::cerr << "QgsGrassEdit::displayDynamic Points = " << Points << " type = " << type << std::endl;
|
|
#endif
|
|
|
|
mTransform = mCanvas->getCoordinateTransform();
|
|
|
|
// Delete last drawing
|
|
displayLastDynamic ( );
|
|
|
|
Vect_reset_line ( mLastDynamicPoints );
|
|
if ( Points ) {
|
|
Vect_append_points ( mLastDynamicPoints, Points, GV_FORWARD );
|
|
}
|
|
|
|
if ( type != ICON_NONE ) {
|
|
mLastDynamicIconX = x;
|
|
mLastDynamicIconY = y;
|
|
}
|
|
mLastDynamicIcon = type;
|
|
|
|
displayLastDynamic ( );
|
|
}
|
|
|
|
void QgsGrassEdit::displayLastDynamic ( void )
|
|
{
|
|
#if QGISDEBUG > 3
|
|
std::cerr << "QgsGrassEdit::displayLastDynamic" << std::endl;
|
|
#endif
|
|
|
|
QPainter myPainter;
|
|
myPainter.begin(mPixmap);
|
|
|
|
// Use of XOR can result in repeated :
|
|
// 'QPainter: Internal error; no available GC '
|
|
// which is probably only false warning, see qt/src/kernel/qpainter_x11.cpp
|
|
myPainter.setRasterOp(Qt::XorROP); // Must be after begin()
|
|
myPainter.setPen ( mSymb[SYMB_DYNAMIC] );
|
|
|
|
QPointArray pa ( mLastDynamicPoints->n_points );
|
|
for ( int i = 0; i < mLastDynamicPoints->n_points; i++ ) {
|
|
QgsPoint point;
|
|
point.setX(mLastDynamicPoints->x[i]);
|
|
point.setY(mLastDynamicPoints->y[i]);
|
|
mTransform->transform(&point);
|
|
pa.setPoint( i, static_cast<int>(point.x()), static_cast<int>(point.y()) );
|
|
}
|
|
myPainter.drawPolyline ( pa );
|
|
|
|
if ( mLastDynamicIcon != ICON_NONE ) {
|
|
displayIcon ( mLastDynamicIconX, mLastDynamicIconY, mSymb[SYMB_DYNAMIC], mLastDynamicIcon,
|
|
mSize, &myPainter );
|
|
}
|
|
|
|
myPainter.end();
|
|
}
|
|
|
|
void QgsGrassEdit::displayNode ( int node, const QPen & pen, int size, QPainter *painter )
|
|
{
|
|
#if QGISDEBUG > 3
|
|
std::cerr << "QgsGrassEdit::displayNode() node = " << node << std::endl;
|
|
#endif
|
|
|
|
if ( !mSymbDisplay[mNodeSymb[node]] ) return;
|
|
|
|
double x, y;
|
|
|
|
if ( !(mProvider->nodeCoor(node,&x,&y )) ) return;
|
|
|
|
displayIcon ( x, y, pen, QgsGrassEdit::ICON_X, size, painter );
|
|
}
|
|
|
|
void QgsGrassEdit::displayIcon ( double x, double y, const QPen & pen,
|
|
int type, int size, QPainter *painter )
|
|
{
|
|
#if QGISDEBUG > 3
|
|
std::cerr << "QgsGrassEdit::displayIcon()" << std::endl;
|
|
#endif
|
|
|
|
QgsPoint point;
|
|
QPointArray pointArray(2);
|
|
|
|
point.setX(x);
|
|
point.setY(y);
|
|
mTransform->transform(&point);
|
|
|
|
int px = static_cast<int>(point.x());
|
|
int py = static_cast<int>(point.y());
|
|
int m = (size-1)/2;
|
|
|
|
QPainter *myPainter;
|
|
if ( !painter ) {
|
|
myPainter = new QPainter();
|
|
myPainter->begin(mPixmap);
|
|
} else {
|
|
myPainter = painter;
|
|
}
|
|
|
|
myPainter->setPen ( pen );
|
|
|
|
switch ( type ) {
|
|
case QgsGrassEdit::ICON_CROSS :
|
|
pointArray.setPoint( 0, px-m, py );
|
|
pointArray.setPoint( 1, px+m, py );
|
|
myPainter->drawPolyline ( pointArray );
|
|
|
|
pointArray.setPoint( 0, px, py+m );
|
|
pointArray.setPoint( 1, px, py-m );
|
|
myPainter->drawPolyline ( pointArray );
|
|
break;
|
|
case QgsGrassEdit::ICON_X :
|
|
pointArray.setPoint( 0, px-m, py+m );
|
|
pointArray.setPoint( 1, px+m, py-m );
|
|
myPainter->drawPolyline ( pointArray );
|
|
|
|
pointArray.setPoint( 0, px-m, py-m );
|
|
pointArray.setPoint( 1, px+m, py+m );
|
|
myPainter->drawPolyline ( pointArray );
|
|
break;
|
|
case QgsGrassEdit::ICON_BOX :
|
|
pointArray.resize(5);
|
|
pointArray.setPoint( 0, px-m, py-m );
|
|
pointArray.setPoint( 1, px+m, py-m );
|
|
pointArray.setPoint( 2, px+m, py+m );
|
|
pointArray.setPoint( 3, px-m, py+m );
|
|
pointArray.setPoint( 4, px-m, py-m );
|
|
myPainter->drawPolyline ( pointArray );
|
|
break;
|
|
}
|
|
|
|
if ( !painter ) {
|
|
myPainter->end();
|
|
mCanvas->repaint(false);
|
|
delete myPainter;
|
|
}
|
|
}
|
|
|
|
void QgsGrassEdit::setCanvasPropmt( QString left, QString mid, QString rigth)
|
|
{
|
|
std::cerr << "QgsGrassEdit::setCanvasPropmt" << std::endl;
|
|
mCanvasPrompt = "";
|
|
if ( left.length() > 0 ) mCanvasPrompt.append ( tr("Left: ") + left + " " );
|
|
if ( mid.length() > 0 ) mCanvasPrompt.append ( tr("Middle: ") + mid + " " );
|
|
if ( rigth.length() > 0 ) mCanvasPrompt.append ( tr("Rigth: ") + rigth );
|
|
}
|
|
|