mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
and there are display issues when loading a layer. The georeferencer plugin is currently disabled in the build due to unresolved UI issues. git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@4244 c8812cc2-4d05-0410-92ff-de0c093fc19c
2099 lines
62 KiB
C++
2099 lines
62 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 <q3filedialog.h>
|
|
#include <qsettings.h>
|
|
#include <qpixmap.h>
|
|
#include <q3listbox.h>
|
|
#include <qstringlist.h>
|
|
#include <qlabel.h>
|
|
#include <q3combobox.h>
|
|
#include <qspinbox.h>
|
|
#include <qmessagebox.h>
|
|
#include <qinputdialog.h>
|
|
#include <qsettings.h>
|
|
#include <qpainter.h>
|
|
#include <qpixmap.h>
|
|
#include <qpen.h>
|
|
#include <q3pointarray.h>
|
|
#include <qcursor.h>
|
|
#include <qnamespace.h>
|
|
#include <q3listview.h>
|
|
#include <qcolordialog.h>
|
|
#include <q3table.h>
|
|
#include <qstatusbar.h>
|
|
#include <qglobal.h>
|
|
//Added by qt3to4:
|
|
#include <QCloseEvent>
|
|
|
|
#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, Qt::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;
|
|
mNewMap = false;
|
|
|
|
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().toLocal8Bit().data() << 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().toLocal8Bit().data() << std::endl;
|
|
|
|
if ( vector->providerType() != "grass" ) {
|
|
QMessageBox::warning( 0, "Warning", "The selected vector is not in GRASS format." );
|
|
return;
|
|
}
|
|
|
|
std::cerr << "Vector layer type: " << vector->providerType().toLocal8Bit().data() << std::endl;
|
|
|
|
//TODO dynamic_cast ?
|
|
mProvider = (QgsGrassProvider *) vector->getDataProvider();
|
|
|
|
init();
|
|
}
|
|
|
|
QgsGrassEdit::QgsGrassEdit ( QgisApp *qgisApp, QgisIface *iface,
|
|
QgsGrassProvider *provider,
|
|
QWidget * parent, const char * name, Qt::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;
|
|
mNewMap = true;
|
|
|
|
mCanvas = mIface->getMapCanvas();
|
|
|
|
mProvider = provider;
|
|
|
|
init();
|
|
}
|
|
|
|
void QgsGrassEdit::init()
|
|
{
|
|
if ( !(mProvider->isGrassEditable()) ) {
|
|
QMessageBox::warning( 0, "Warning", "You are not owner of the mapset, "
|
|
"cannot open the vector for editing." );
|
|
return;
|
|
}
|
|
|
|
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,Q3ListView::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 ) {
|
|
Q3ListViewItem *lvi = new Q3ListViewItem ( symbologyList , "", "", mSymbName[i] );
|
|
lvi->setPixmap ( 1, pm );
|
|
lvi->setText ( 3, index );
|
|
} else {
|
|
Q3CheckListItem *clvi = new Q3CheckListItem ( symbologyList , "", Q3CheckListItem::CheckBox );
|
|
clvi->setText ( 2, mSymbName[i] );
|
|
clvi->setPixmap ( 1, pm );
|
|
clvi->setOn ( mSymbDisplay[i] );
|
|
clvi->setText ( 3, index );
|
|
}
|
|
}
|
|
|
|
connect( symbologyList, SIGNAL(pressed(Q3ListViewItem *, const QPoint &, int)),
|
|
this, SLOT(changeSymbology(Q3ListViewItem *, 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];
|
|
|
|
Q3TableItem *ti;
|
|
|
|
ti = new Q3TableItem( mAttributeTable, Q3TableItem::Never, col.name() );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( c, 0, ti );
|
|
|
|
ti = new Q3TableItem( mAttributeTable, Q3TableItem::Never, col.type() );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( c, 1, ti );
|
|
|
|
QString str;
|
|
str.sprintf("%d", col.length() );
|
|
ti = new Q3TableItem( mAttributeTable, Q3TableItem::Never, str );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( c, 2, ti );
|
|
}
|
|
} else {
|
|
mAttributeTable->setNumRows ( 1 );
|
|
|
|
Q3TableItem *ti;
|
|
|
|
ti = new Q3TableItem( mAttributeTable, Q3TableItem::Always, "cat" );
|
|
mAttributeTable->setItem ( 0, 0, ti );
|
|
|
|
ti = new Q3TableItem( mAttributeTable, Q3TableItem::Never, "integer" );
|
|
ti->setEnabled( false );
|
|
mAttributeTable->setItem ( 0, 1, ti );
|
|
|
|
ti = new Q3TableItem( mAttributeTable, Q3TableItem::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 );
|
|
|
|
Q3TableItem *ti;
|
|
|
|
ti = new Q3TableItem( mAttributeTable, Q3TableItem::Always, cn );
|
|
mAttributeTable->setItem ( r, 0, ti );
|
|
|
|
QStringList types;
|
|
types.push_back ( "integer" );
|
|
types.push_back ( "double precision" );
|
|
types.push_back ( "varchar" );
|
|
|
|
Q3ComboTableItem *cti = new Q3ComboTableItem ( mAttributeTable, types );
|
|
cti->setCurrentItem(0);
|
|
mAttributeTable->setItem ( r, 1, cti );
|
|
|
|
ti = new Q3TableItem( mAttributeTable, Q3TableItem::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;
|
|
|
|
Q3ComboTableItem *cti = (Q3ComboTableItem *) mAttributeTable->item ( row, 1 );
|
|
|
|
Q3TableItem *ti = mAttributeTable->item ( row, 2 );
|
|
|
|
if ( cti->currentText().compare( "varchar" ) != 0 ) {
|
|
Q3TableItem *nti = new Q3TableItem( mAttributeTable, Q3TableItem::Never, ti->text() );
|
|
nti->setEnabled(false);
|
|
mAttributeTable->setItem ( row, 2, nti );
|
|
//delete ti;
|
|
} else {
|
|
Q3TableItem *nti = new Q3TableItem( mAttributeTable, Q3TableItem::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();
|
|
|
|
Q3TableItem *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(Q3ListViewItem * 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;
|
|
|
|
Q3CheckListItem *clvi = (Q3CheckListItem *) 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();
|
|
|
|
// Add new layers
|
|
if ( mNewMap )
|
|
{
|
|
QString uri = mProvider->getDataSourceUri();
|
|
QChar sep = QDir::separator();
|
|
|
|
QStringList split = QStringList::split ( sep, uri );
|
|
split.pop_back(); // layer
|
|
QString map = split.last();
|
|
split.pop_back(); // map
|
|
QString mapset = split.last();
|
|
|
|
QStringList layers = QgsGrassSelect::vectorLayers (
|
|
QgsGrass::getDefaultGisdbase(), QgsGrass::getDefaultLocation(),
|
|
mapset, map );
|
|
|
|
for ( int i = 0; i < layers.count(); i++ )
|
|
{
|
|
uri = QgsGrass::getDefaultGisdbase() + "/"
|
|
+ QgsGrass::getDefaultLocation() + "/"
|
|
+ mapset + "/" + map + "/" + layers[i];
|
|
|
|
#ifdef QGISDEBUG
|
|
std::cerr << "layer = " << layers[i].local8Bit().data() << std::endl;
|
|
std::cerr << "uri = " << uri.local8Bit().data() << std::endl;
|
|
#endif
|
|
mIface->addVectorLayer( uri, layers[i], "grass");
|
|
}
|
|
}
|
|
|
|
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().toLocal8Bit().data() << std::endl;
|
|
|
|
if ( col.name() != *key ) {
|
|
std::cerr << " value = " << att.fieldValue().toLocal8Bit().data() << 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;
|
|
Q3PointArray 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
|
|
|
|
#if QT_VERSION < 0x040000
|
|
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] );
|
|
|
|
Q3PointArray 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();
|
|
#else
|
|
// TODO: Qt4 uses QRubberBand, need to refactor.
|
|
#endif
|
|
|
|
}
|
|
|
|
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;
|
|
Q3PointArray 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 );
|
|
}
|
|
|