~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/app/composer/qgscomposer.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-04-24 15:12:20 UTC
  • mfrom: (3.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120424151220-r88g00af5fpn5fc3
Tags: 1.7.4+1.7.5~20120320-1
The "Sometimes they come back" release.

* Branching from Qgis tree and adapting to current Debian Policy and
  standards. The target tree is currently set to release-1.7.
  (closes: #661491, #606304, #615683, #616182, #600308)
* Policy bumped to 3.9.3.
* Moving to debhelper compatibility level 9.
* Source format is now 3.0 with quilt support.
* Merged with 2bf42287 upstream git snapshot.
* Migrated to dh_python2 instead of python-central.
  (closes: #617048)
* Snapshot in qgis.org release-1.7: c936d031
* Added an automagic creation of a lintian override for sqlite embedding.
  This is required for uploading currently.
* Added missing ${misc:Depends} to make lintian happy.
* Copyright notes updated and debian/copyright moved to format 1.0.
* More licenses notices now reported in debian/copyright. Thanks ftpmasters.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include "qgscomposerscalebarwidget.h"
36
36
#include "qgscomposershape.h"
37
37
#include "qgscomposershapewidget.h"
 
38
#include "qgscomposerattributetable.h"
 
39
#include "qgscomposertablewidget.h"
38
40
#include "qgsexception.h"
 
41
#include "qgslogger.h"
39
42
#include "qgsproject.h"
40
43
#include "qgsmapcanvas.h"
41
44
#include "qgsmaprenderer.h"
44
47
#include "qgscursors.h"
45
48
 
46
49
#include <QCloseEvent>
 
50
#include <QCheckBox>
47
51
#include <QDesktopWidget>
48
52
#include <QFileDialog>
49
53
#include <QFileInfo>
 
54
#include <QIcon>
 
55
#include <QImageWriter>
50
56
#include <QMatrix>
51
57
#include <QMenuBar>
52
58
#include <QMessageBox>
 
59
#include <QPageSetupDialog>
53
60
#include <QPainter>
54
 
 
55
 
#include <QPrinter>
 
61
#include <QPixmap>
56
62
#include <QPrintDialog>
57
63
#include <QSettings>
58
 
#include <QIcon>
59
 
#include <QPixmap>
60
 
#if QT_VERSION < 0x040300
61
 
#include <Q3Picture>
62
 
#else
 
64
#include <QSizeGrip>
63
65
#include <QSvgGenerator>
64
 
#endif
65
66
#include <QToolBar>
66
67
#include <QToolButton>
67
 
#include <QImageWriter>
68
 
#include <QCheckBox>
69
 
#include <QSizeGrip>
70
 
#include "qgslogger.h"
71
 
 
72
 
QgsComposer::QgsComposer( QgisApp *qgis, const QString& title ): QMainWindow(), mTitle( title )
 
68
#include <QUndoView>
 
69
#include <QPaintEngine>
 
70
 
 
71
 
 
72
QgsComposer::QgsComposer( QgisApp *qgis, const QString& title ): QMainWindow(), mTitle( title ), mUndoView( 0 )
73
73
{
74
74
  setupUi( this );
75
75
  setWindowTitle( mTitle );
76
76
  setupTheme();
77
77
  QObject::connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( close() ) );
78
78
 
 
79
  QSettings settings;
 
80
  int size = settings.value( "/IconSize", 24 ).toInt();
 
81
  setIconSize( QSize( size, size ) );
 
82
 
79
83
  QToolButton* orderingToolButton = new QToolButton( this );
80
84
  orderingToolButton->setPopupMode( QToolButton::InstantPopup );
81
85
  orderingToolButton->setAutoRaise( true );
112
116
  toggleActionGroup->addAction( mActionSelectMoveItem );
113
117
  toggleActionGroup->addAction( mActionAddBasicShape );
114
118
  toggleActionGroup->addAction( mActionAddArrow );
 
119
  toggleActionGroup->addAction( mActionAddTable );
115
120
  toggleActionGroup->setExclusive( true );
116
121
 
117
122
  mActionAddNewMap->setCheckable( true );
138
143
  fileMenu->addAction( mActionExportAsPDF );
139
144
  fileMenu->addAction( mActionExportAsSVG );
140
145
  fileMenu->addSeparator();
 
146
  fileMenu->addAction( mActionPageSetup );
141
147
  fileMenu->addAction( mActionPrint );
142
148
  fileMenu->addSeparator();
143
149
  fileMenu->addAction( mActionQuit );
151
157
  viewMenu->addAction( mActionRefreshView );
152
158
 
153
159
  QMenu *layoutMenu = menuBar()->addMenu( tr( "Layout" ) );
 
160
  layoutMenu->addAction( mActionUndo );
 
161
  layoutMenu->addAction( mActionRedo );
 
162
  layoutMenu->addSeparator();
154
163
  layoutMenu->addAction( mActionAddNewMap );
155
164
  layoutMenu->addAction( mActionAddNewLabel );
156
165
  layoutMenu->addAction( mActionAddNewScalebar );
160
169
  layoutMenu->addAction( mActionMoveItemContent );
161
170
  layoutMenu->addAction( mActionAddBasicShape );
162
171
  layoutMenu->addAction( mActionAddArrow );
 
172
  layoutMenu->addAction( mActionAddTable );
163
173
  layoutMenu->addSeparator();
164
174
  layoutMenu->addAction( mActionGroupItems );
165
175
  layoutMenu->addAction( mActionUngroupItems );
193
203
  mView = new QgsComposerView( mViewFrame );
194
204
  connectSlots();
195
205
 
 
206
  //init undo/redo buttons
196
207
  mComposition  = new QgsComposition( mQgis->mapCanvas()->mapRenderer() );
 
208
  mActionUndo->setEnabled( false );
 
209
  mActionRedo->setEnabled( false );
 
210
  if ( mComposition->undoStack() )
 
211
  {
 
212
    connect( mComposition->undoStack(), SIGNAL( canUndoChanged( bool ) ), mActionUndo, SLOT( setEnabled( bool ) ) );
 
213
    connect( mComposition->undoStack(), SIGNAL( canRedoChanged( bool ) ), mActionRedo, SLOT( setEnabled( bool ) ) );
 
214
  }
 
215
 
 
216
 
197
217
  mComposition->setParent( mView );
198
218
  mView->setComposition( mComposition );
199
219
 
211
231
 
212
232
  mCompositionNameComboBox->insertItem( 0, tr( "Map 1" ) );
213
233
 
 
234
  //undo widget
 
235
  mUndoView = new QUndoView( mComposition->undoStack(), this );
 
236
  mOptionsTabWidget->addTab( mUndoView, tr( "Command history" ) );
 
237
 
214
238
  // Create size grip (needed by Mac OS X for QMainWindow if QStatusBar is not visible)
215
239
  mSizeGrip = new QSizeGrip( this );
216
240
  mSizeGrip->resize( mSizeGrip->sizeHint() );
248
272
  mActionZoomIn->setIcon( QgisApp::getThemeIcon( "/mActionZoomIn.png" ) );
249
273
  mActionZoomOut->setIcon( QgisApp::getThemeIcon( "/mActionZoomOut.png" ) );
250
274
  mActionRefreshView->setIcon( QgisApp::getThemeIcon( "/mActionDraw.png" ) );
 
275
  mActionUndo->setIcon( QgisApp::getThemeIcon( "/mActionUndo.png" ) );
 
276
  mActionRedo->setIcon( QgisApp::getThemeIcon( "/mActionRedo.png" ) );
251
277
  mActionAddImage->setIcon( QgisApp::getThemeIcon( "/mActionAddImage.png" ) );
252
278
  mActionAddNewMap->setIcon( QgisApp::getThemeIcon( "/mActionAddMap.png" ) );
253
279
  mActionAddNewLabel->setIcon( QgisApp::getThemeIcon( "/mActionLabel.png" ) );
255
281
  mActionAddNewScalebar->setIcon( QgisApp::getThemeIcon( "/mActionScaleBar.png" ) );
256
282
  mActionAddBasicShape->setIcon( QgisApp::getThemeIcon( "/mActionAddBasicShape.png" ) );
257
283
  mActionAddArrow->setIcon( QgisApp::getThemeIcon( "/mActionAddArrow.png" ) );
 
284
  mActionAddTable->setIcon( QgisApp::getThemeIcon( "/mActionOpenTable.png" ) );
258
285
  mActionSelectMoveItem->setIcon( QgisApp::getThemeIcon( "/mActionSelectPan.png" ) );
259
286
  mActionMoveItemContent->setIcon( QgisApp::getThemeIcon( "/mActionMoveItemContent.png" ) );
260
287
  mActionGroupItems->setIcon( QgisApp::getThemeIcon( "/mActionGroupItems.png" ) );
271
298
  mActionAlignBottom->setIcon( QgisApp::getThemeIcon( "/mActionAlignBottom.png" ) );
272
299
}
273
300
 
 
301
void QgsComposer::setIconSizes( int size )
 
302
{
 
303
  //Set the icon size of for all the toolbars created in the future.
 
304
  setIconSize( QSize( size, size ) );
 
305
 
 
306
  //Change all current icon sizes.
 
307
  QList<QToolBar *> toolbars = findChildren<QToolBar *>();
 
308
  foreach( QToolBar * toolbar, toolbars )
 
309
  {
 
310
    toolbar->setIconSize( QSize( size, size ) );
 
311
  }
 
312
}
 
313
 
274
314
void QgsComposer::connectSlots()
275
315
{
276
 
  connect( mView, SIGNAL( selectedItemChanged( const QgsComposerItem* ) ), this, SLOT( showItemOptions( const QgsComposerItem* ) ) );
 
316
  connect( mView, SIGNAL( selectedItemChanged( QgsComposerItem* ) ), this, SLOT( showItemOptions( QgsComposerItem* ) ) );
277
317
  connect( mView, SIGNAL( composerLabelAdded( QgsComposerLabel* ) ), this, SLOT( addComposerLabel( QgsComposerLabel* ) ) );
278
318
  connect( mView, SIGNAL( composerMapAdded( QgsComposerMap* ) ), this, SLOT( addComposerMap( QgsComposerMap* ) ) );
279
319
  connect( mView, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( deleteItem( QgsComposerItem* ) ) );
282
322
  connect( mView, SIGNAL( composerPictureAdded( QgsComposerPicture* ) ), this, SLOT( addComposerPicture( QgsComposerPicture* ) ) );
283
323
  connect( mView, SIGNAL( composerShapeAdded( QgsComposerShape* ) ), this, SLOT( addComposerShape( QgsComposerShape* ) ) );
284
324
  connect( mView, SIGNAL( composerArrowAdded( QgsComposerArrow* ) ), this, SLOT( addComposerArrow( QgsComposerArrow* ) ) );
 
325
  connect( mView, SIGNAL( composerTableAdded( QgsComposerAttributeTable* ) ), this, SLOT( addComposerTable( QgsComposerAttributeTable* ) ) );
285
326
  connect( mView, SIGNAL( actionFinished() ), this, SLOT( setSelectionTool() ) );
286
327
}
287
328
 
357
398
  mItemStackedWidget->addWidget( w );
358
399
}
359
400
 
360
 
void QgsComposer::showItemOptions( const QgsComposerItem* item )
 
401
void QgsComposer::showItemOptions( QgsComposerItem* item )
361
402
{
362
403
  QWidget* currentWidget = mItemStackedWidget->currentWidget();
363
404
 
368
409
    return;
369
410
  }
370
411
 
371
 
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.find( const_cast<QgsComposerItem*>( item ) );
 
412
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.find( item );
372
413
  if ( it == mItemWidgetMap.constEnd() )
373
414
  {
374
415
    return;
453
494
  mComposition->update();
454
495
}
455
496
 
 
497
// Hack to workaround Qt #5114 by disabling PatternTransform
 
498
class QgsPaintEngineHack : public QPaintEngine
 
499
{
 
500
  public:
 
501
    void fixFlags()
 
502
    {
 
503
      gccaps = 0;
 
504
      gccaps |= ( QPaintEngine::PrimitiveTransform
 
505
                  // | QPaintEngine::PatternTransform
 
506
                  | QPaintEngine::PixmapTransform
 
507
                  | QPaintEngine::PatternBrush
 
508
                  // | QPaintEngine::LinearGradientFill
 
509
                  // | QPaintEngine::RadialGradientFill
 
510
                  // | QPaintEngine::ConicalGradientFill
 
511
                  | QPaintEngine::AlphaBlend
 
512
                  // | QPaintEngine::PorterDuff
 
513
                  | QPaintEngine::PainterPaths
 
514
                  | QPaintEngine::Antialiasing
 
515
                  | QPaintEngine::BrushStroke
 
516
                  | QPaintEngine::ConstantOpacity
 
517
                  | QPaintEngine::MaskedBrush
 
518
                  // | QPaintEngine::PerspectiveTransform
 
519
                  | QPaintEngine::BlendModes
 
520
                  // | QPaintEngine::ObjectBoundingModeGradients
 
521
#if QT_VERSION >= 0x040500
 
522
                  | QPaintEngine::RasterOpModes
 
523
#endif
 
524
                  | QPaintEngine::PaintOutsidePaintEvent
 
525
                );
 
526
    }
 
527
};
 
528
 
456
529
void QgsComposer::on_mActionExportAsPDF_triggered()
457
530
{
458
531
  QSettings myQSettings;  // where we keep last used filter in persistent state
459
 
  QString myLastUsedFile = myQSettings.value( "/UI/lastSaveAsPdfFile", "qgis.pdf" ).toString();
460
 
  QFileInfo file( myLastUsedFile );
461
 
  QFileDialog *myQFileDialog = new QFileDialog( this, tr( "Choose a file name to save the map as" ),
462
 
      file.path(), tr( "PDF Format" ) + " (*.pdf *PDF)" );
463
 
  myQFileDialog->selectFile( file.fileName() );
464
 
  myQFileDialog->setFileMode( QFileDialog::AnyFile );
465
 
  myQFileDialog->setAcceptMode( QFileDialog::AcceptSave );
466
 
 
467
 
  int result = myQFileDialog->exec();
468
 
  raise();
469
 
  if ( result != QDialog::Accepted ) return;
470
 
 
471
 
  QString myOutputFileNameQString = myQFileDialog->selectedFiles().first();
472
 
  if ( myOutputFileNameQString == "" ) return;
473
 
 
474
 
  myQSettings.setValue( "/UI/lastSaveAsPdfFile", myOutputFileNameQString );
 
532
  QString lastUsedFile = myQSettings.value( "/UI/lastSaveAsPdfFile", "qgis.pdf" ).toString();
 
533
  QFileInfo file( lastUsedFile );
 
534
 
 
535
  QString outputFileName = QFileDialog::getSaveFileName(
 
536
                             this,
 
537
                             tr( "Choose a file name to save the map as" ),
 
538
                             file.path(),
 
539
                             tr( "PDF Format" ) + " (*.pdf *.PDF)" );
 
540
 
 
541
  if ( !outputFileName.endsWith( ".pdf", Qt::CaseInsensitive ) )
 
542
  {
 
543
    outputFileName += ".pdf";
 
544
  }
 
545
 
 
546
  myQSettings.setValue( "/UI/lastSaveAsPdfFile", outputFileName );
475
547
 
476
548
  QPrinter printer;
477
549
 
478
550
  printer.setOutputFormat( QPrinter::PdfFormat );
479
 
  printer.setOutputFileName( myOutputFileNameQString );
 
551
  printer.setOutputFileName( outputFileName );
480
552
  printer.setPaperSize( QSizeF( mComposition->paperWidth(), mComposition->paperHeight() ), QPrinter::Millimeter );
481
553
 
 
554
  QPaintEngine *engine = printer.paintEngine();
 
555
  if ( engine )
 
556
  {
 
557
    QgsPaintEngineHack *hack = static_cast<QgsPaintEngineHack*>( engine );
 
558
    hack->fixFlags();
 
559
  }
 
560
 
482
561
  print( printer );
483
562
}
484
563
 
485
564
void QgsComposer::on_mActionPrint_triggered()
486
565
{
487
 
  QPrinter printer;
488
 
  if ( mComposition )
489
 
  {
490
 
    if ( mComposition->paperWidth() >= mComposition->paperHeight() )
491
 
    {
492
 
      printer.setOrientation( QPrinter::Landscape );
493
 
    }
494
 
    else
495
 
    {
496
 
      printer.setOrientation( QPrinter::Portrait );
497
 
    }
498
 
  }
499
 
  printer.setPaperSize( QSizeF( mComposition->paperWidth(), mComposition->paperHeight() ), QPrinter::Millimeter );
500
 
  QPrintDialog printDialog( &printer, 0 );
 
566
  //orientation and page size are already set to QPrinter in the page setup dialog
 
567
  QPrintDialog printDialog( &mPrinter, 0 );
501
568
  if ( printDialog.exec() != QDialog::Accepted )
502
569
  {
503
570
    return;
504
571
  }
505
572
 
506
 
  print( printer );
 
573
  print( mPrinter );
507
574
}
508
575
 
509
576
void QgsComposer::print( QPrinter &printer )
510
577
{
511
 
  if ( !mComposition )
 
578
  if ( !mComposition || !mView )
512
579
    return;
513
580
 
514
581
  if ( containsWMSLayer() )
530
597
 
531
598
  QApplication::setOverrideCursor( Qt::BusyCursor );
532
599
 
533
 
  if ( mComposition->printAsRaster() )
 
600
  bool printAsRaster = mComposition->printAsRaster();
 
601
  //mView->setScene( 0 );
 
602
 
 
603
  if ( printAsRaster )
534
604
  {
535
605
    //print out via QImage, code copied from on_mActionExportAsImage_activated
536
606
    int width = ( int )( mComposition->printResolution() * mComposition->paperWidth() / 25.4 );
537
607
    int height = ( int )( mComposition-> printResolution() * mComposition->paperHeight() / 25.4 );
538
608
    QImage image( QSize( width, height ), QImage::Format_ARGB32 );
539
 
    image.setDotsPerMeterX( mComposition->printResolution() / 25.4 * 1000 );
540
 
    image.setDotsPerMeterY( mComposition->printResolution() / 25.4 * 1000 );
541
 
    image.fill( 0 );
542
 
    QPainter imagePainter( &image );
543
 
    QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
544
 
    QRectF targetArea( 0, 0, width, height );
545
 
    mComposition->render( &imagePainter, targetArea, sourceArea );
546
 
    imagePainter.end();
547
 
    p.drawImage( targetArea, image, targetArea );
 
609
    if ( !image.isNull() )
 
610
    {
 
611
      image.setDotsPerMeterX( mComposition->printResolution() / 25.4 * 1000 );
 
612
      image.setDotsPerMeterY( mComposition->printResolution() / 25.4 * 1000 );
 
613
      image.fill( 0 );
 
614
      QPainter imagePainter( &image );
 
615
      QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
 
616
      QRectF targetArea( 0, 0, width, height );
 
617
      mView->setPaintingEnabled( false );
 
618
      mComposition->render( &imagePainter, targetArea, sourceArea );
 
619
      mView->setPaintingEnabled( true );
 
620
      p.drawImage( targetArea, image, targetArea );
 
621
    }
 
622
    else
 
623
    {
 
624
      QApplication::restoreOverrideCursor();
 
625
      int answer = QMessageBox::warning( 0,
 
626
                                         tr( "Image too large" ),
 
627
                                         tr( "Creation of image with %1x%2 pixels failed.  Retry without 'Print As Raster'?" )
 
628
                                         .arg( width ).arg( height ),
 
629
                                         QMessageBox::Ok | QMessageBox::Cancel,
 
630
                                         QMessageBox::Ok );
 
631
      if ( answer == QMessageBox::Cancel )
 
632
      {
 
633
        mComposition->setPlotStyle( savedPlotStyle );
 
634
        return;
 
635
      }
 
636
 
 
637
      QApplication::setOverrideCursor( Qt::BusyCursor );
 
638
      printAsRaster = false;
 
639
    }
548
640
  }
549
 
  else
 
641
 
 
642
  if ( !printAsRaster )
550
643
  {
551
 
#if QT_VERSION < 0x040400
552
 
    QRectF paperRect( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
553
 
    QRect pageRect = printer.pageRect();
554
 
    mComposition->render( &p, pageRect, paperRect );
555
 
#else
556
644
    //better in case of custom page size, but only possible with Qt>=4.4.0
557
645
    QRectF paperRectMM = printer.pageRect( QPrinter::Millimeter );
558
646
    QRectF paperRectPixel = printer.pageRect( QPrinter::DevicePixel );
 
647
 
 
648
    mView->setPaintingEnabled( false );
559
649
    mComposition->render( &p, paperRectPixel, paperRectMM );
560
 
#endif
 
650
    mView->setPaintingEnabled( true );
561
651
  }
 
652
 
562
653
  mComposition->setPlotStyle( savedPlotStyle );
563
654
  QApplication::restoreOverrideCursor();
564
655
}
575
666
  int height = ( int )( mComposition-> printResolution() * mComposition->paperHeight() / 25.4 );
576
667
 
577
668
  int memuse = width * height * 3 / 1000000;  // pixmap + image
578
 
  QgsDebugMsg( QString( "Image %1 x %2" ).arg( width ).arg( height ) );
 
669
  QgsDebugMsg( QString( "Image %1x%2" ).arg( width ).arg( height ) );
579
670
  QgsDebugMsg( QString( "memuse = %1" ).arg( memuse ) );
580
671
 
581
 
  if ( memuse > 200 )   // cca 4500 x 4500
 
672
  if ( memuse > 200 )   // about 4500x4500
582
673
  {
583
674
    int answer = QMessageBox::warning( 0, tr( "Big image" ),
584
 
                                       tr( "To create image %1 x %2 requires circa %3 MB of memory" )
 
675
                                       tr( "To create image %1x%2 requires about %3 MB of memory. Proceed?" )
585
676
                                       .arg( width ).arg( height ).arg( memuse ),
586
 
                                       QMessageBox::Ok,  QMessageBox::Abort );
 
677
                                       QMessageBox::Ok | QMessageBox::Cancel,  QMessageBox::Ok );
587
678
 
588
679
    raise();
589
 
    if ( answer == QMessageBox::Abort ) return;
590
 
  }
591
 
 
592
 
  // Get file and format (stolen from qgisapp.cpp but modified significantely)
593
 
 
594
 
  //create a map to hold the QImageIO names and the filter names
595
 
  //the QImageIO name must be passed to the mapcanvas saveas image function
596
 
  typedef QMap<QString, QString> FilterMap;
597
 
  FilterMap myFilterMap;
598
 
 
599
 
  //find out the last used filter
600
 
  QSettings myQSettings;  // where we keep last used filter in persistent state
601
 
  QString myLastUsedFormat = myQSettings.value( "/UI/lastSaveAsImageFormat", "png" ).toString();
602
 
  QString myLastUsedFile = myQSettings.value( "/UI/lastSaveAsImageFile", "qgis.png" ).toString();
603
 
  QFileInfo file( myLastUsedFile );
604
 
 
605
 
  // get a list of supported output image types
606
 
  int myCounterInt = 0;
607
 
  QString myFilters;
608
 
  QString myLastUsedFilter;
609
 
  for ( ; myCounterInt < QImageWriter::supportedImageFormats().count(); myCounterInt++ )
610
 
  {
611
 
    QString myFormat = QString( QImageWriter::supportedImageFormats().at( myCounterInt ) );
612
 
    QString myFilter = tr( "%1 format (*.%2 *.%3)" )
613
 
                       .arg( myFormat ).arg( myFormat.toLower() ).arg( myFormat.toUpper() );
614
 
 
615
 
    if ( myCounterInt > 0 ) myFilters += ";;";
616
 
    myFilters += myFilter;
617
 
    myFilterMap[myFilter] = myFormat;
618
 
    if ( myFormat == myLastUsedFormat )
619
 
    {
620
 
      myLastUsedFilter = myFilter;
621
 
    }
622
 
  }
623
 
#ifdef QGISDEBUG
624
 
  QgsDebugMsg( "Available Filters Map: " );
625
 
  FilterMap::Iterator myIterator;
626
 
  for ( myIterator = myFilterMap.begin(); myIterator != myFilterMap.end(); ++myIterator )
627
 
  {
628
 
    QgsDebugMsg( QString( "%1  :  %2" ).arg( myIterator.key() ).arg( myIterator.value() ) );
629
 
  }
630
 
#endif
631
 
 
632
 
  //create a file dialog using the the filter list generated above
633
 
  std::auto_ptr < QFileDialog > myQFileDialog(
634
 
    new QFileDialog(
635
 
      this,
636
 
      tr( "Choose a file name to save the map image as" ),
637
 
      file.path(),
638
 
      myFilters
639
 
    )
640
 
  );
641
 
 
642
 
  myQFileDialog->setFileMode( QFileDialog::AnyFile );
643
 
 
644
 
  // set the filter to the last one used
645
 
  myQFileDialog->selectFilter( myLastUsedFilter );
646
 
 
647
 
  // set the 'Open' button to something that makes more sense
648
 
  myQFileDialog->setAcceptMode( QFileDialog::AcceptSave );
649
 
 
650
 
  //prompt the user for a file name
651
 
  QString myOutputFileNameQString;
652
 
 
653
 
  int result = myQFileDialog->exec();
654
 
  //raise();
655
 
 
656
 
  if ( result != QDialog::Accepted )
 
680
    if ( answer == QMessageBox::Cancel )
 
681
      return;
 
682
  }
 
683
 
 
684
  QPair<QString, QString> fileNExt = QgisGui::getSaveAsImageName( this, tr( "Choose a file name to save the map image as" ) );
 
685
 
 
686
  QgsDebugMsg( QString( "Selected filter: %1" ).arg( fileNExt.first ) );
 
687
  QgsDebugMsg( QString( "Image type: %1" ).arg( fileNExt.second ) );
 
688
 
 
689
  if ( fileNExt.first.isEmpty() )
657
690
  {
658
691
    return;
659
692
  }
660
693
 
661
 
  myOutputFileNameQString = myQFileDialog->selectedFiles().last();
662
 
  QgsDebugMsg( myOutputFileNameQString );
663
 
  QString myFilterString = myQFileDialog->selectedFilter();
664
 
  QgsDebugMsg( QString( "Selected filter: %1" ).arg( myFilterString ) );
665
 
  QgsDebugMsg( QString( "Image type: %1" ).arg( myFilterMap[myFilterString] ) );
666
 
 
667
 
  // Add the file type suffix to the fileName if required
668
 
  if ( !myOutputFileNameQString.endsWith( myFilterMap[myFilterString] ) )
669
 
  {
670
 
    myOutputFileNameQString += "." + myFilterMap[myFilterString];
671
 
  }
672
 
 
673
 
  myQSettings.setValue( "/UI/lastSaveAsImageFormat", myFilterMap[myFilterString] );
674
 
  myQSettings.setValue( "/UI/lastSaveAsImageFile", myOutputFileNameQString );
675
 
 
676
 
  if ( myOutputFileNameQString == "" ) return;
677
 
 
678
 
  mComposition->setPlotStyle( QgsComposition::Print );
679
 
  mView->setScene( 0 );
680
 
 
681
694
  QImage image( QSize( width, height ), QImage::Format_ARGB32 );
 
695
  if ( image.isNull() )
 
696
  {
 
697
    QMessageBox::warning( 0,
 
698
                          tr( "Image too big" ),
 
699
                          tr( "Creation of image with %1x%2 pixels failed.  Export aborted." )
 
700
                          .arg( width ).arg( height ),
 
701
                          QMessageBox::Ok );
 
702
    return;
 
703
  }
 
704
 
 
705
  mComposition->setPlotStyle( QgsComposition::Print );
682
706
  image.setDotsPerMeterX( mComposition->printResolution() / 25.4 * 1000 );
683
707
  image.setDotsPerMeterY( mComposition->printResolution() / 25.4 * 1000 );
684
708
  image.fill( 0 );
685
709
  QPainter p( &image );
686
710
  QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
687
711
  QRectF targetArea( 0, 0, width, height );
 
712
  mView->setPaintingEnabled( false );
688
713
  mComposition->render( &p, targetArea, sourceArea );
689
714
  p.end();
690
 
 
691
715
  mComposition->setPlotStyle( QgsComposition::Preview );
692
 
  image.save( myOutputFileNameQString, myFilterMap[myFilterString].toLocal8Bit().data() );
693
 
  mView->setScene( mComposition );
 
716
  mView->setPaintingEnabled( true );
 
717
  image.save( fileNExt.first, fileNExt.second.toLocal8Bit().constData() );
694
718
}
695
719
 
696
720
 
701
725
    showWMSPrintingWarning();
702
726
  }
703
727
 
704
 
  QString myQSettingsLabel = "/UI/displaySVGWarning";
705
 
  QSettings myQSettings;
 
728
  QString settingsLabel = "/UI/displaySVGWarning";
 
729
  QSettings settings;
706
730
 
707
 
  bool displaySVGWarning = myQSettings.value( myQSettingsLabel, true ).toBool();
 
731
  bool displaySVGWarning = settings.value( settingsLabel, true ).toBool();
708
732
 
709
733
  if ( displaySVGWarning )
710
734
  {
713
737
    m->setCheckBoxText( tr( "Don't show this message again" ) );
714
738
    m->setCheckBoxState( Qt::Unchecked );
715
739
    m->setCheckBoxVisible( true );
716
 
    m->setCheckBoxQSettingsLabel( myQSettingsLabel );
 
740
    m->setCheckBoxQSettingsLabel( settingsLabel );
717
741
    m->setMessageAsHtml( tr( "<p>The SVG export function in Qgis has several "
718
742
                             "problems due to bugs and deficiencies in the " )
719
743
                         + tr( "Qt4 svg code. In particular, there are problems "
726
750
                               "</p>" ) );
727
751
    m->exec();
728
752
  }
729
 
  QString myLastUsedFile = myQSettings.value( "/UI/lastSaveAsSvgFile", "qgis.svg" ).toString();
730
 
  QFileInfo file( myLastUsedFile );
731
 
  QFileDialog *myQFileDialog = new QFileDialog( this, tr( "Choose a file name to save the map as" ),
732
 
      file.path(), tr( "SVG Format" ) + " (*.svg *SVG)" );
733
 
  myQFileDialog->selectFile( file.fileName() );
734
 
  myQFileDialog->setFileMode( QFileDialog::AnyFile );
735
 
  myQFileDialog->setAcceptMode( QFileDialog::AcceptSave );
736
 
 
737
 
  int result = myQFileDialog->exec();
738
 
  raise();
739
 
  if ( result != QDialog::Accepted ) return;
740
 
 
741
 
  QString myOutputFileNameQString = myQFileDialog->selectedFiles().first();
742
 
  if ( myOutputFileNameQString == "" ) return;
743
 
 
744
 
  myQSettings.setValue( "/UI/lastSaveAsSvgFile", myOutputFileNameQString );
745
 
 
746
 
  //mView->setScene(0);//don't redraw the scene on the display while we render
 
753
 
 
754
  QString lastUsedFile = settings.value( "/UI/lastSaveAsSvgFile", "qgis.svg" ).toString();
 
755
  QFileInfo file( lastUsedFile );
 
756
 
 
757
  QString outputFileName = QFileDialog::getSaveFileName(
 
758
                             this,
 
759
                             tr( "Choose a file name to save the map as" ),
 
760
                             file.path(),
 
761
                             tr( "SVG Format" ) + " (*.svg *.SVG)" );
 
762
 
 
763
  if ( outputFileName.isEmpty() )
 
764
  {
 
765
    return;
 
766
  }
 
767
 
 
768
 
 
769
  if ( !outputFileName.endsWith( ".svg", Qt::CaseInsensitive ) )
 
770
  {
 
771
    outputFileName += ".svg" ;
 
772
  }
 
773
 
 
774
  settings.setValue( "/UI/lastSaveAsSvgFile", outputFileName );
747
775
  mComposition->setPlotStyle( QgsComposition::Print );
748
776
 
749
777
  QSvgGenerator generator;
750
778
#if QT_VERSION >= 0x040500
751
779
  generator.setTitle( QgsProject::instance()->title() );
752
780
#endif
753
 
  generator.setFileName( myOutputFileNameQString );
 
781
  generator.setFileName( outputFileName );
754
782
  //width in pixel
755
783
  int width = ( int )( mComposition->paperWidth() * mComposition->printResolution() / 25.4 );
756
784
  //height in pixel
757
785
  int height = ( int )( mComposition->paperHeight() * mComposition->printResolution() / 25.4 );
758
786
  generator.setSize( QSize( width, height ) );
 
787
#if QT_VERSION >= 0x040500
 
788
  generator.setViewBox( QRect( 0, 0, width, height ) );
 
789
#endif
759
790
  generator.setResolution( mComposition->printResolution() ); //because the rendering is done in mm, convert the dpi
760
791
 
761
792
  QPainter p( &generator );
762
793
 
763
794
  QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
764
795
  QRectF targetArea( 0, 0, width, height );
 
796
  mView->setPaintingEnabled( false );
765
797
  mComposition->render( &p, targetArea, sourceArea );
766
 
 
767
798
  p.end();
768
 
 
769
799
  mComposition->setPlotStyle( QgsComposition::Preview );
770
 
  //mView->setScene(mComposition->canvas()); //now that we're done, set the view to show the scene again
 
800
  mView->setPaintingEnabled( true );
771
801
}
772
802
 
773
803
void QgsComposer::on_mActionSelectMoveItem_triggered()
826
856
  }
827
857
}
828
858
 
 
859
void QgsComposer::on_mActionAddTable_triggered()
 
860
{
 
861
  if ( mView )
 
862
  {
 
863
    mView->setCurrentTool( QgsComposerView::AddTable );
 
864
  }
 
865
}
 
866
 
829
867
void QgsComposer::on_mActionAddArrow_triggered()
830
868
{
831
869
  if ( mView )
839
877
  //show file dialog
840
878
  QSettings settings;
841
879
  QString lastSaveDir = settings.value( "UI/lastComposerTemplateDir", "" ).toString();
842
 
  QString saveFileName = QFileDialog::getSaveFileName( 0, tr( "save template" ), lastSaveDir, "*.qpt" );
 
880
  QString saveFileName = QFileDialog::getSaveFileName(
 
881
                           this,
 
882
                           tr( "Save template" ),
 
883
                           lastSaveDir,
 
884
                           tr( "Composer templates" ) + " (*.qpt *.QPT)" );
 
885
 
843
886
  if ( saveFileName.isEmpty() )
844
887
  {
845
888
    return;
890
933
    return;
891
934
  }
892
935
 
 
936
  emit composerWillBeRemoved( mView );
 
937
 
893
938
  QDomDocument templateDocument;
894
939
  if ( !templateDocument.setContent( &templateFile, false ) )
895
940
  {
899
944
 
900
945
  deleteItems();
901
946
  readXML( templateDocument );
902
 
 
903
 
  //clean up after template read (e.g. legend and map extent)
904
 
  cleanupAfterTemplateRead();
 
947
  emit composerAdded( mView );
905
948
}
906
949
 
907
950
void QgsComposer::on_mActionMoveItemContent_triggered()
1008
1051
  }
1009
1052
}
1010
1053
 
 
1054
void QgsComposer::on_mActionUndo_triggered()
 
1055
{
 
1056
  if ( mComposition && mComposition->undoStack() )
 
1057
  {
 
1058
    mComposition->undoStack()->undo();
 
1059
  }
 
1060
}
 
1061
 
 
1062
void QgsComposer::on_mActionRedo_triggered()
 
1063
{
 
1064
  if ( mComposition && mComposition->undoStack() )
 
1065
  {
 
1066
    mComposition->undoStack()->redo();
 
1067
  }
 
1068
}
 
1069
 
1011
1070
void QgsComposer::moveEvent( QMoveEvent *e ) { saveWindowState(); }
1012
1071
 
1013
1072
void QgsComposer::resizeEvent( QResizeEvent *e )
1030
1089
  QSettings settings;
1031
1090
  restoreGeometry( settings.value( "/Composer/geometry" ).toByteArray() );
1032
1091
  QVariant splitterState = settings.value( "/Composer/splitterState" );
1033
 
  if ( splitterState != QVariant::QVariant() )
 
1092
  if ( !splitterState.isNull() )
1034
1093
  {
1035
1094
    //mSplitter->restoreState(settings.value("/Composer/splitterState").toByteArray());
1036
1095
  }
1099
1158
    return;
1100
1159
  }
1101
1160
  readXML( composerNodeList.at( 0 ).toElement(), doc, true );
 
1161
  cleanupAfterTemplateRead();
1102
1162
}
1103
1163
 
1104
1164
void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument& doc, bool fromTemplate )
1260
1320
    showItemOptions( newArrow );
1261
1321
  }
1262
1322
 
 
1323
  //composer tables
 
1324
  QDomNodeList composerTableList = composerElem.elementsByTagName( "ComposerAttributeTable" );
 
1325
  for ( int i = 0; i < composerTableList.size(); ++i )
 
1326
  {
 
1327
    QDomElement currentTableElem = composerTableList.at( i ).toElement();
 
1328
    QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( mComposition );
 
1329
    newTable->readXML( currentTableElem, doc );
 
1330
    addComposerTable( newTable );
 
1331
    mComposition->addItem( newTable );
 
1332
    mComposition->update();
 
1333
    mComposition->clearSelection();
 
1334
    newTable->setSelected( true );
 
1335
    showItemOptions( newTable );
 
1336
  }
 
1337
 
1263
1338
  mComposition->sortZList();
1264
1339
  mView->setComposition( mComposition );
1265
1340
 
 
1341
  if ( mUndoView )
 
1342
  {
 
1343
    //init undo/redo buttons
 
1344
    mActionUndo->setEnabled( false );
 
1345
    mActionRedo->setEnabled( false );
 
1346
    if ( mComposition->undoStack() )
 
1347
    {
 
1348
      mUndoView->setStack( mComposition->undoStack() );
 
1349
      connect( mComposition->undoStack(), SIGNAL( canUndoChanged( bool ) ), mActionUndo, SLOT( setEnabled( bool ) ) );
 
1350
      connect( mComposition->undoStack(), SIGNAL( canRedoChanged( bool ) ), mActionRedo, SLOT( setEnabled( bool ) ) );
 
1351
    }
 
1352
  }
 
1353
 
 
1354
 
 
1355
 
1266
1356
  setSelectionTool();
1267
1357
}
1268
1358
 
1296
1386
    return;
1297
1387
  }
1298
1388
 
 
1389
  map->setMapCanvas( mapCanvas() ); //set canvas to composer map to have the possibility to draw canvas items
1299
1390
  QgsComposerMapWidget* mapWidget = new QgsComposerMapWidget( map );
1300
1391
  connect( this, SIGNAL( zoomLevelChanged() ), map, SLOT( renderModeUpdateCachedImage() ) );
1301
1392
  mItemWidgetMap.insert( map, mapWidget );
1331
1422
  }
1332
1423
 
1333
1424
  QgsComposerLegendWidget* lWidget = new QgsComposerLegendWidget( legend );
 
1425
  if ( sender() ) //only update if created from GUI (not after XML read)
 
1426
  {
 
1427
    lWidget->updateLegend();
 
1428
  }
1334
1429
  mItemWidgetMap.insert( legend, lWidget );
1335
1430
}
1336
1431
 
1355
1450
  mItemWidgetMap.insert( shape, sWidget );
1356
1451
}
1357
1452
 
 
1453
void QgsComposer::addComposerTable( QgsComposerAttributeTable* table )
 
1454
{
 
1455
  if ( !table )
 
1456
  {
 
1457
    return;
 
1458
  }
 
1459
  QgsComposerTableWidget* tWidget = new QgsComposerTableWidget( table );
 
1460
  mItemWidgetMap.insert( table, tWidget );
 
1461
}
 
1462
 
1358
1463
void QgsComposer::deleteItem( QgsComposerItem* item )
1359
1464
{
1360
1465
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.find( item );
1364
1469
    return;
1365
1470
  }
1366
1471
 
1367
 
  delete( it.key() );
 
1472
  //the item itself is not deleted here (usually, this is done in the destructor of QgsAddRemoveItemCommand)
1368
1473
  delete( it.value() );
1369
1474
  mItemWidgetMap.remove( it.key() );
1370
1475
}
1466
1571
  }
1467
1572
}
1468
1573
 
 
1574
void QgsComposer::on_mActionPageSetup_triggered()
 
1575
{
 
1576
  if ( !mComposition )
 
1577
  {
 
1578
    return;
 
1579
  }
1469
1580
 
 
1581
  QPageSetupDialog pageSetupDialog( &mPrinter, this );
 
1582
  pageSetupDialog.exec();
 
1583
}