~ubuntu-branches/ubuntu/trusty/qgis/trusty

« back to all changes in this revision

Viewing changes to src/app/qgsattributeeditor.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
                         qgsattributeeditor.cpp  -  description
 
3
                             -------------------
 
4
    begin                : July 2009
 
5
    copyright            : (C) 2009 by Jürgen E. Fischer
 
6
    email                : jef@norbit.de
 
7
 ***************************************************************************/
 
8
 
 
9
/***************************************************************************
 
10
 *                                                                         *
 
11
 *   This program is free software; you can redistribute it and/or modify  *
 
12
 *   it under the terms of the GNU General Public License as published by  *
 
13
 *   the Free Software Foundation; either version 2 of the License, or     *
 
14
 *   (at your option) any later version.                                   *
 
15
 *                                                                         *
 
16
 ***************************************************************************/
 
17
/* $Id$ */
 
18
 
 
19
#include "qgsattributeeditor.h"
 
20
#include <qgsvectorlayer.h>
 
21
#include <qgsvectordataprovider.h>
 
22
#include <qgsuniquevaluerenderer.h>
 
23
#include <qgscategorizedsymbolrendererv2.h>
 
24
#include <qgssymbol.h>
 
25
 
 
26
#include <QPushButton>
 
27
#include <QLineEdit>
 
28
#include <QTextEdit>
 
29
#include <QFileDialog>
 
30
#include <QComboBox>
 
31
#include <QCheckBox>
 
32
#include <QSpinBox>
 
33
#include <QCompleter>
 
34
#include <QHBoxLayout>
 
35
 
 
36
#if QT_VERSION >= 0x040400
 
37
#include <QPlainTextEdit>
 
38
#endif
 
39
 
 
40
void QgsAttributeEditor::selectFileName( void )
 
41
{
 
42
  QPushButton *pb = qobject_cast<QPushButton *>( sender() );
 
43
  if ( !pb )
 
44
    return;
 
45
 
 
46
  QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
 
47
  if ( !hbox )
 
48
    return;
 
49
 
 
50
  QLineEdit *le = hbox->findChild<QLineEdit *>();
 
51
  if ( !le )
 
52
    return;
 
53
 
 
54
  QString fileName = QFileDialog::getOpenFileName( 0 , tr( "Select a file" ) );
 
55
  if ( fileName.isNull() )
 
56
    return;
 
57
 
 
58
  le->setText( fileName );
 
59
}
 
60
 
 
61
QComboBox *QgsAttributeEditor::comboBox( QWidget *editor, QWidget *parent )
 
62
{
 
63
  QComboBox *cb = NULL;
 
64
  if ( editor )
 
65
    cb = qobject_cast<QComboBox *>( editor );
 
66
  else
 
67
    cb = new QComboBox( parent );
 
68
 
 
69
  return cb;
 
70
}
 
71
 
 
72
QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
 
73
{
 
74
  if ( !vl )
 
75
    return NULL;
 
76
 
 
77
  QWidget *myWidget = NULL;
 
78
  QgsVectorLayer::EditType editType = vl->editType( idx );
 
79
  const QgsField &field = vl->pendingFields()[idx];
 
80
  QVariant::Type myFieldType = field.type();
 
81
 
 
82
  switch ( editType )
 
83
  {
 
84
    case QgsVectorLayer::UniqueValues:
 
85
    {
 
86
      QList<QVariant> values;
 
87
      vl->dataProvider()->uniqueValues( idx, values );
 
88
 
 
89
      QComboBox *cb = comboBox( editor, parent );
 
90
      if ( cb )
 
91
      {
 
92
        cb->setEditable( false );
 
93
 
 
94
        for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); it++ )
 
95
          cb->addItem( it->toString(), it->toString() );
 
96
 
 
97
        myWidget = cb;
 
98
      }
 
99
    }
 
100
    break;
 
101
 
 
102
    case QgsVectorLayer::Enumeration:
 
103
    {
 
104
      QStringList enumValues;
 
105
      vl->dataProvider()->enumValues( idx, enumValues );
 
106
 
 
107
      QComboBox *cb = comboBox( editor, parent );
 
108
      if ( cb )
 
109
      {
 
110
        QStringList::const_iterator s_it = enumValues.constBegin();
 
111
        for ( ; s_it != enumValues.constEnd(); ++s_it )
 
112
        {
 
113
          cb->addItem( *s_it, *s_it );
 
114
        }
 
115
 
 
116
        myWidget = cb;
 
117
      }
 
118
    }
 
119
    break;
 
120
 
 
121
    case QgsVectorLayer::ValueMap:
 
122
    {
 
123
      const QMap<QString, QVariant> &map = vl->valueMap( idx );
 
124
 
 
125
      QComboBox *cb = comboBox( editor, parent );
 
126
      if ( cb )
 
127
      {
 
128
        for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); it++ )
 
129
        {
 
130
          cb->addItem( it.key(), it.value() );
 
131
        }
 
132
 
 
133
        myWidget = cb;
 
134
      }
 
135
    }
 
136
    break;
 
137
 
 
138
    case QgsVectorLayer::Classification:
 
139
    {
 
140
      QMap<QString, QString> classes;
 
141
 
 
142
      const QgsUniqueValueRenderer *uvr = dynamic_cast<const QgsUniqueValueRenderer *>( vl->renderer() );
 
143
      if ( uvr )
 
144
      {
 
145
        const QList<QgsSymbol *> symbols = uvr->symbols();
 
146
 
 
147
        for ( int i = 0; i < symbols.size(); i++ )
 
148
        {
 
149
          QString label = symbols[i]->label();
 
150
          QString name = symbols[i]->lowerValue();
 
151
 
 
152
          if ( label == "" )
 
153
            label = name;
 
154
 
 
155
          classes.insert( name, label );
 
156
        }
 
157
      }
 
158
 
 
159
      const QgsCategorizedSymbolRendererV2 *csr = dynamic_cast<const QgsCategorizedSymbolRendererV2 *>( vl->rendererV2() );
 
160
      if ( csr )
 
161
      {
 
162
        const QgsCategoryList &categories = (( QgsCategorizedSymbolRendererV2 * )csr )->categories(); // FIXME: QgsCategorizedSymbolRendererV2::categories() should be const
 
163
        for ( int i = 0; i < categories.size(); i++ )
 
164
        {
 
165
          QString label = categories[i].label();
 
166
          QString value = categories[i].value().toString();
 
167
          if ( label.isEmpty() )
 
168
            label = value;
 
169
          classes.insert( label, value );
 
170
        }
 
171
      }
 
172
 
 
173
      QComboBox *cb = comboBox( editor, parent );
 
174
      if ( cb )
 
175
      {
 
176
        for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); it++ )
 
177
        {
 
178
          cb->addItem( it.value(), it.key() );
 
179
        }
 
180
 
 
181
        myWidget = cb;
 
182
      }
 
183
    }
 
184
    break;
 
185
 
 
186
    case QgsVectorLayer::SliderRange:
 
187
    case QgsVectorLayer::EditRange:
 
188
    {
 
189
      if ( myFieldType == QVariant::Int )
 
190
      {
 
191
        int min = vl->range( idx ).mMin.toInt();
 
192
        int max = vl->range( idx ).mMax.toInt();
 
193
        int step = vl->range( idx ).mStep.toInt();
 
194
 
 
195
        if ( editType == QgsVectorLayer::EditRange )
 
196
        {
 
197
          QSpinBox *sb = NULL;
 
198
 
 
199
          if ( editor )
 
200
            sb = qobject_cast<QSpinBox *>( editor );
 
201
          else
 
202
            sb = new QSpinBox( parent );
 
203
 
 
204
          if ( sb )
 
205
          {
 
206
            sb->setRange( min, max );
 
207
            sb->setSingleStep( step );
 
208
 
 
209
            myWidget = sb;
 
210
          }
 
211
        }
 
212
        else
 
213
        {
 
214
          QSlider *sl = NULL;
 
215
 
 
216
          if ( editor )
 
217
            sl = qobject_cast<QSlider*>( editor );
 
218
          else
 
219
            sl = new QSlider( Qt::Horizontal, parent );
 
220
 
 
221
          if ( sl )
 
222
          {
 
223
            sl->setRange( min, max );
 
224
            sl->setSingleStep( step );
 
225
 
 
226
            myWidget = sl;
 
227
          }
 
228
        }
 
229
        break;
 
230
      }
 
231
      else if ( myFieldType == QVariant::Double )
 
232
      {
 
233
        QDoubleSpinBox *dsb = NULL;
 
234
        if ( editor )
 
235
          dsb = qobject_cast<QDoubleSpinBox*>( editor );
 
236
        else
 
237
          dsb = new QDoubleSpinBox( parent );
 
238
 
 
239
        if ( dsb )
 
240
        {
 
241
          double min = vl->range( idx ).mMin.toDouble();
 
242
          double max = vl->range( idx ).mMax.toDouble();
 
243
          double step = vl->range( idx ).mStep.toDouble();
 
244
 
 
245
          dsb->setRange( min, max );
 
246
          dsb->setSingleStep( step );
 
247
 
 
248
          myWidget = dsb;
 
249
        }
 
250
        break;
 
251
      }
 
252
    }
 
253
 
 
254
    case QgsVectorLayer::CheckBox:
 
255
    {
 
256
      QCheckBox *cb = NULL;
 
257
      if ( editor )
 
258
        cb = qobject_cast<QCheckBox*>( editor );
 
259
      else
 
260
        cb = new QCheckBox( parent );
 
261
 
 
262
      if ( cb )
 
263
      {
 
264
        myWidget = cb;
 
265
        break;
 
266
      }
 
267
    }
 
268
 
 
269
    // fall-through
 
270
 
 
271
    case QgsVectorLayer::LineEdit:
 
272
    case QgsVectorLayer::TextEdit:
 
273
    case QgsVectorLayer::UniqueValuesEditable:
 
274
    {
 
275
      QLineEdit *le = NULL;
 
276
      QTextEdit *te = NULL;
 
277
#if QT_VERSION >= 0x040400
 
278
      QPlainTextEdit *pte = NULL;
 
279
#endif
 
280
 
 
281
      if ( editor )
 
282
      {
 
283
        le = qobject_cast<QLineEdit *>( editor );
 
284
        te = qobject_cast<QTextEdit *>( editor );
 
285
#if QT_VERSION >= 0x040400
 
286
        pte = qobject_cast<QPlainTextEdit *>( editor );
 
287
#endif
 
288
      }
 
289
      else if ( editType == QgsVectorLayer::TextEdit )
 
290
      {
 
291
#if QT_VERSION >= 0x040400
 
292
        pte = new QPlainTextEdit( parent );
 
293
#else
 
294
        te = new QTextEdit( parent );
 
295
        te->setAcceptRichText( false );
 
296
#endif
 
297
      }
 
298
      else
 
299
      {
 
300
        le = new QLineEdit( parent );
 
301
      }
 
302
 
 
303
      if ( le )
 
304
      {
 
305
 
 
306
        if ( editType == QgsVectorLayer::UniqueValuesEditable )
 
307
        {
 
308
          QList<QVariant> values;
 
309
          vl->dataProvider()->uniqueValues( idx, values );
 
310
 
 
311
          QStringList svalues;
 
312
          for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); it++ )
 
313
            svalues << it->toString();
 
314
 
 
315
          QCompleter *c = new QCompleter( svalues );
 
316
          c->setCompletionMode( QCompleter::PopupCompletion );
 
317
          le->setCompleter( c );
 
318
        }
 
319
 
 
320
        if ( myFieldType == QVariant::Int )
 
321
        {
 
322
          le->setValidator( new QIntValidator( le ) );
 
323
        }
 
324
        else if ( myFieldType == QVariant::Double )
 
325
        {
 
326
          le->setValidator( new QDoubleValidator( le ) );
 
327
        }
 
328
 
 
329
        myWidget = le;
 
330
      }
 
331
 
 
332
      if ( te )
 
333
      {
 
334
#if QT_VERSION >= 0x040400
 
335
        te->setAcceptRichText( true );
 
336
#endif
 
337
        myWidget = te;
 
338
      }
 
339
 
 
340
#if QT_VERSION >= 0x040400
 
341
      if ( pte )
 
342
      {
 
343
        myWidget = pte;
 
344
      }
 
345
#endif
 
346
    }
 
347
    break;
 
348
 
 
349
    case QgsVectorLayer::Hidden:
 
350
      myWidget = NULL;
 
351
      break;
 
352
 
 
353
    case QgsVectorLayer::FileName:
 
354
    {
 
355
      QPushButton *pb = NULL;
 
356
      QLineEdit *le = qobject_cast<QLineEdit *>( editor );
 
357
      if ( le )
 
358
      {
 
359
        if ( le )
 
360
          myWidget = le;
 
361
 
 
362
        if ( editor->parent() )
 
363
        {
 
364
          pb = editor->parent()->findChild<QPushButton *>();
 
365
        }
 
366
      }
 
367
      else
 
368
      {
 
369
        le = new QLineEdit();
 
370
 
 
371
        pb = new QPushButton( tr( "..." ) );
 
372
 
 
373
        QHBoxLayout *hbl = new QHBoxLayout();
 
374
        hbl->addWidget( le );
 
375
        hbl->addWidget( pb );
 
376
 
 
377
        myWidget = new QWidget( parent );
 
378
        myWidget->setBackgroundRole( QPalette::Window );
 
379
        myWidget->setAutoFillBackground( true );
 
380
        myWidget->setLayout( hbl );
 
381
      }
 
382
 
 
383
      if ( pb )
 
384
        connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectFileName() ) );
 
385
    }
 
386
    break;
 
387
 
 
388
    case QgsVectorLayer::Immutable:
 
389
      return NULL;
 
390
 
 
391
  }
 
392
 
 
393
  if ( editType == QgsVectorLayer::Immutable )
 
394
  {
 
395
    myWidget->setEnabled( false );
 
396
  }
 
397
 
 
398
  setValue( myWidget, vl, idx, value );
 
399
 
 
400
  return myWidget;
 
401
}
 
402
 
 
403
bool QgsAttributeEditor::retrieveValue( QWidget *widget, QgsVectorLayer *vl, int idx, QVariant &value )
 
404
{
 
405
  if ( !widget )
 
406
    return false;
 
407
 
 
408
  const QgsField &theField = vl->pendingFields()[idx];
 
409
  QgsVectorLayer::EditType editType = vl->editType( idx );
 
410
  bool modified = false;
 
411
  QString text;
 
412
 
 
413
  QLineEdit *le = qobject_cast<QLineEdit *>( widget );
 
414
  if ( le )
 
415
  {
 
416
    text = le->text();
 
417
    modified = le->isModified();
 
418
    if ( text == "NULL" )
 
419
    {
 
420
      text = QString::null;
 
421
    }
 
422
  }
 
423
 
 
424
  QTextEdit *te = qobject_cast<QTextEdit *>( widget );
 
425
  if ( te )
 
426
  {
 
427
#if QT_VERSION >= 0x040400
 
428
    text = te->toHtml();
 
429
#else
 
430
    text = te->toPlainText();
 
431
#endif
 
432
    modified = te->document()->isModified();
 
433
    if ( text == "NULL" )
 
434
    {
 
435
      text = QString::null;
 
436
    }
 
437
  }
 
438
 
 
439
#if QT_VERSION >= 0x040400
 
440
  QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( widget );
 
441
  if ( pte )
 
442
  {
 
443
    text = pte->toPlainText();
 
444
    modified = pte->document()->isModified();
 
445
    if ( text == "NULL" )
 
446
    {
 
447
      text = QString::null;
 
448
    }
 
449
  }
 
450
#endif
 
451
 
 
452
  QComboBox *cb = qobject_cast<QComboBox *>( widget );
 
453
  if ( cb )
 
454
  {
 
455
    if ( editType == QgsVectorLayer::UniqueValues ||
 
456
         editType == QgsVectorLayer::ValueMap ||
 
457
         editType == QgsVectorLayer::Classification )
 
458
    {
 
459
      text = cb->itemData( cb->currentIndex() ).toString();
 
460
    }
 
461
    else
 
462
    {
 
463
      text = cb->currentText();
 
464
    }
 
465
  }
 
466
 
 
467
  QSpinBox *sb = qobject_cast<QSpinBox *>( widget );
 
468
  if ( sb )
 
469
  {
 
470
    text = QString::number( sb->value() );
 
471
  }
 
472
 
 
473
  QSlider *slider = qobject_cast<QSlider *>( widget );
 
474
  if ( slider )
 
475
  {
 
476
    text = QString::number( slider->value() );
 
477
  }
 
478
 
 
479
  QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( widget );
 
480
  if ( dsb )
 
481
  {
 
482
    text = QString::number( dsb->value() );
 
483
  }
 
484
 
 
485
  QCheckBox *ckb = qobject_cast<QCheckBox *>( widget );
 
486
  if ( ckb )
 
487
  {
 
488
    QPair<QString, QString> states = vl->checkedState( idx );
 
489
    text = ckb->isChecked() ? states.first : states.second;
 
490
  }
 
491
 
 
492
  le = widget->findChild<QLineEdit *>();
 
493
  if ( le )
 
494
  {
 
495
    text = le->text();
 
496
  }
 
497
 
 
498
  switch ( theField.type() )
 
499
  {
 
500
    case QVariant::Int:
 
501
    {
 
502
      bool ok;
 
503
      int myIntValue = text.toInt( &ok );
 
504
      if ( ok && !text.isEmpty() )
 
505
      {
 
506
        value = QVariant( myIntValue );
 
507
        modified = true;
 
508
      }
 
509
      else if ( modified )
 
510
      {
 
511
        value = QVariant( theField.type() );
 
512
      }
 
513
    }
 
514
    break;
 
515
    case QVariant::Double:
 
516
    {
 
517
      bool ok;
 
518
      double myDblValue = text.toDouble( &ok );
 
519
      if ( ok && !text.isEmpty() )
 
520
      {
 
521
        value = QVariant( myDblValue );
 
522
        modified = true;
 
523
      }
 
524
      else if ( modified )
 
525
      {
 
526
        value = QVariant( theField.type() );
 
527
      }
 
528
    }
 
529
    break;
 
530
    default: //string
 
531
      modified = true;
 
532
      value = QVariant( text );
 
533
      break;
 
534
  }
 
535
 
 
536
  return modified;
 
537
}
 
538
 
 
539
bool QgsAttributeEditor::setValue( QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
 
540
{
 
541
  if ( !editor )
 
542
    return false;
 
543
 
 
544
  QgsVectorLayer::EditType editType = vl->editType( idx );
 
545
  const QgsField &field = vl->pendingFields()[idx];
 
546
  QVariant::Type myFieldType = field.type();
 
547
 
 
548
  switch ( editType )
 
549
  {
 
550
    case QgsVectorLayer::Classification:
 
551
    case QgsVectorLayer::UniqueValues:
 
552
    case QgsVectorLayer::Enumeration:
 
553
    case QgsVectorLayer::ValueMap:
 
554
    {
 
555
      QComboBox *cb = qobject_cast<QComboBox *>( editor );
 
556
      if ( cb == NULL )
 
557
        return false;
 
558
 
 
559
      int idx = cb->findData( value );
 
560
      if ( idx < 0 )
 
561
        return false;
 
562
 
 
563
      cb->setCurrentIndex( idx );
 
564
    }
 
565
    break;
 
566
 
 
567
    case QgsVectorLayer::SliderRange:
 
568
    case QgsVectorLayer::EditRange:
 
569
    {
 
570
      if ( myFieldType == QVariant::Int )
 
571
      {
 
572
        if ( editType == QgsVectorLayer::EditRange )
 
573
        {
 
574
          QSpinBox *sb = qobject_cast<QSpinBox *>( editor );
 
575
          if ( sb == NULL )
 
576
            return false;
 
577
          sb->setValue( value.toInt() );
 
578
        }
 
579
        else
 
580
        {
 
581
          QSlider *sl = qobject_cast<QSlider *>( editor );
 
582
          if ( sl == NULL )
 
583
            return false;
 
584
          sl->setValue( value.toInt() );
 
585
        }
 
586
        break;
 
587
      }
 
588
      else if ( myFieldType == QVariant::Double )
 
589
      {
 
590
        QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( editor );
 
591
        if ( dsb == NULL )
 
592
          return false;
 
593
        dsb->setValue( value.toDouble() );
 
594
      }
 
595
    }
 
596
 
 
597
    case QgsVectorLayer::CheckBox:
 
598
    {
 
599
      QCheckBox *cb = qobject_cast<QCheckBox *>( editor );
 
600
      if ( cb )
 
601
      {
 
602
        QPair<QString, QString> states = vl->checkedState( idx );
 
603
        cb->setChecked( value == states.first );
 
604
        break;
 
605
      }
 
606
    }
 
607
 
 
608
    // fall-through
 
609
 
 
610
    case QgsVectorLayer::LineEdit:
 
611
    case QgsVectorLayer::UniqueValuesEditable:
 
612
    case QgsVectorLayer::Immutable:
 
613
    default:
 
614
    {
 
615
      QLineEdit *le = qobject_cast<QLineEdit *>( editor );
 
616
      QTextEdit *te = qobject_cast<QTextEdit *>( editor );
 
617
#if QT_VERSION >= 0x040400
 
618
      QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( editor );
 
619
      if ( !le && !te && !pte )
 
620
        return false;
 
621
#else
 
622
      if ( !le && !te )
 
623
        return false;
 
624
#endif
 
625
 
 
626
      QString text;
 
627
      if ( value.isNull() )
 
628
        if ( myFieldType == QVariant::Int || myFieldType == QVariant::Double )
 
629
          text = "";
 
630
        else
 
631
          text = "NULL";
 
632
      else
 
633
        text = value.toString();
 
634
 
 
635
      if ( le )
 
636
        le->setText( text );
 
637
#if QT_VERSION >= 0x040400
 
638
      if ( te )
 
639
        te->setHtml( text );
 
640
      if ( pte )
 
641
        pte->setPlainText( text );
 
642
#else
 
643
      if ( te )
 
644
        te->setPlainText( text );
 
645
#endif
 
646
    }
 
647
    break;
 
648
 
 
649
    case QgsVectorLayer::FileName:
 
650
    {
 
651
      QLineEdit *le = editor->findChild<QLineEdit *>();
 
652
      if ( le == NULL )
 
653
        return false;
 
654
      le->setText( value.toString() );
 
655
    }
 
656
    break;
 
657
  }
 
658
 
 
659
  return true;
 
660
}