qgscomposer.cpp

modified source file, fixing the problem - Nikos Ves, 2010-06-02 05:51 AM

Download (47.3 KB)

 
1
/***************************************************************************
2
                         qgscomposer.cpp  -  description
3
                             -------------------
4
    begin                : January 2005
5
    copyright            : (C) 2005 by Radim Blazek
6
    email                : [email protected]
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
#include "qgscomposer.h"
18

    
19
#include "qgisapp.h"
20
#include "qgsapplication.h"
21
#include "qgscomposerview.h"
22
#include "qgscomposition.h"
23
#include "qgscompositionwidget.h"
24
#include "qgscomposerarrow.h"
25
#include "qgscomposerarrowwidget.h"
26
#include "qgscomposerlabel.h"
27
#include "qgscomposerlabelwidget.h"
28
#include "qgscomposerlegend.h"
29
#include "qgscomposerlegendwidget.h"
30
#include "qgscomposermap.h"
31
#include "qgscomposermapwidget.h"
32
#include "qgscomposerpicture.h"
33
#include "qgscomposerpicturewidget.h"
34
#include "qgscomposerscalebar.h"
35
#include "qgscomposerscalebarwidget.h"
36
#include "qgscomposershape.h"
37
#include "qgscomposershapewidget.h"
38
#include "qgscomposerattributetable.h"
39
#include "qgscomposertablewidget.h"
40
#include "qgsexception.h"
41
#include "qgsproject.h"
42
#include "qgsmapcanvas.h"
43
#include "qgsmaprenderer.h"
44
#include "qgsmessageviewer.h"
45
#include "qgscontexthelp.h"
46
#include "qgscursors.h"
47

    
48
#include <QCloseEvent>
49
#include <QDesktopWidget>
50
#include <QFileDialog>
51
#include <QFileInfo>
52
#include <QMatrix>
53
#include <QMenuBar>
54
#include <QMessageBox>
55
#include <QPageSetupDialog>
56
#include <QPainter>
57

    
58
#include <QPrintDialog>
59
#include <QSettings>
60
#include <QIcon>
61
#include <QPixmap>
62
#include <QSvgGenerator>
63
#include <QToolBar>
64
#include <QToolButton>
65
#include <QImageWriter>
66
#include <QCheckBox>
67
#include <QSizeGrip>
68
#include "qgslogger.h"
69

    
70
QgsComposer::QgsComposer( QgisApp *qgis, const QString& title ): QMainWindow(), mTitle( title )
71
{
72
  setupUi( this );
73
  setWindowTitle( mTitle );
74
  setupTheme();
75
  QObject::connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( close() ) );
76

    
77
  QToolButton* orderingToolButton = new QToolButton( this );
78
  orderingToolButton->setPopupMode( QToolButton::InstantPopup );
79
  orderingToolButton->setAutoRaise( true );
80
  orderingToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly );
81

    
82
  orderingToolButton->addAction( mActionRaiseItems );
83
  orderingToolButton->addAction( mActionLowerItems );
84
  orderingToolButton->addAction( mActionMoveItemsToTop );
85
  orderingToolButton->addAction( mActionMoveItemsToBottom );
86
  orderingToolButton->setDefaultAction( mActionRaiseItems );
87
  toolBar->addWidget( orderingToolButton );
88

    
89
  QToolButton* alignToolButton = new QToolButton( this );
90
  alignToolButton->setPopupMode( QToolButton::InstantPopup );
91
  alignToolButton->setAutoRaise( true );
92
  alignToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly );
93

    
94
  alignToolButton->addAction( mActionAlignLeft );
95
  alignToolButton->addAction( mActionAlignHCenter );
96
  alignToolButton->addAction( mActionAlignRight );
97
  alignToolButton->addAction( mActionAlignTop );
98
  alignToolButton->addAction( mActionAlignVCenter );
99
  alignToolButton->addAction( mActionAlignBottom );
100
  alignToolButton->setDefaultAction( mActionAlignLeft );
101
  toolBar->addWidget( alignToolButton );
102

    
103
  QActionGroup* toggleActionGroup = new QActionGroup( this );
104
  toggleActionGroup->addAction( mActionMoveItemContent );
105
  toggleActionGroup->addAction( mActionAddNewMap );
106
  toggleActionGroup->addAction( mActionAddNewLabel );
107
  toggleActionGroup->addAction( mActionAddNewLegend );
108
  toggleActionGroup->addAction( mActionAddNewScalebar );
109
  toggleActionGroup->addAction( mActionAddImage );
110
  toggleActionGroup->addAction( mActionSelectMoveItem );
111
  toggleActionGroup->addAction( mActionAddBasicShape );
112
  toggleActionGroup->addAction( mActionAddArrow );
113
  toggleActionGroup->addAction( mActionAddTable );
114
  toggleActionGroup->setExclusive( true );
115

    
116
  mActionAddNewMap->setCheckable( true );
117
  mActionAddNewLabel->setCheckable( true );
118
  mActionAddNewLegend->setCheckable( true );
119
  mActionSelectMoveItem->setCheckable( true );
120
  mActionAddNewScalebar->setCheckable( true );
121
  mActionAddImage->setCheckable( true );
122
  mActionMoveItemContent->setCheckable( true );
123
  mActionAddBasicShape->setCheckable( true );
124
  mActionAddArrow->setCheckable( true );
125

    
126
#ifdef Q_WS_MAC
127
  QMenu *appMenu = menuBar()->addMenu( tr( "QGIS" ) );
128
  appMenu->addAction( QgisApp::instance()->actionAbout() );
129
  appMenu->addAction( QgisApp::instance()->actionOptions() );
130
#endif
131

    
132
  QMenu *fileMenu = menuBar()->addMenu( tr( "File" ) );
133
  fileMenu->addAction( mActionLoadFromTemplate );
134
  fileMenu->addAction( mActionSaveAsTemplate );
135
  fileMenu->addSeparator();
136
  fileMenu->addAction( mActionExportAsImage );
137
  fileMenu->addAction( mActionExportAsPDF );
138
  fileMenu->addAction( mActionExportAsSVG );
139
  fileMenu->addSeparator();
140
  fileMenu->addAction( mActionPageSetup );
141
  fileMenu->addAction( mActionPrint );
142
  fileMenu->addSeparator();
143
  fileMenu->addAction( mActionQuit );
144
  QObject::connect( mActionQuit, SIGNAL( triggered() ), this, SLOT( close() ) );
145

    
146
  QMenu *viewMenu = menuBar()->addMenu( tr( "View" ) );
147
  viewMenu->addAction( mActionZoomIn );
148
  viewMenu->addAction( mActionZoomOut );
149
  viewMenu->addAction( mActionZoomAll );
150
  viewMenu->addSeparator();
151
  viewMenu->addAction( mActionRefreshView );
152

    
153
  QMenu *layoutMenu = menuBar()->addMenu( tr( "Layout" ) );
154
  layoutMenu->addAction( mActionAddNewMap );
155
  layoutMenu->addAction( mActionAddNewLabel );
156
  layoutMenu->addAction( mActionAddNewScalebar );
157
  layoutMenu->addAction( mActionAddNewLegend );
158
  layoutMenu->addAction( mActionAddImage );
159
  layoutMenu->addAction( mActionSelectMoveItem );
160
  layoutMenu->addAction( mActionMoveItemContent );
161
  layoutMenu->addAction( mActionAddBasicShape );
162
  layoutMenu->addAction( mActionAddArrow );
163
  layoutMenu->addAction( mActionAddTable );
164
  layoutMenu->addSeparator();
165
  layoutMenu->addAction( mActionGroupItems );
166
  layoutMenu->addAction( mActionUngroupItems );
167
  layoutMenu->addAction( mActionRaiseItems );
168
  layoutMenu->addAction( mActionLowerItems );
169
  layoutMenu->addAction( mActionMoveItemsToTop );
170
  layoutMenu->addAction( mActionMoveItemsToBottom );
171

    
172
#ifdef Q_WS_MAC
173
#ifndef Q_WS_MAC64 /* assertion failure in NSMenuItem setSubmenu (Qt 4.5.0-snapshot-20080830) */
174
  menuBar()->addMenu( QgisApp::instance()->windowMenu() );
175

    
176
  menuBar()->addMenu( QgisApp::instance()->helpMenu() );
177
#endif
178
#endif
179

    
180
  mQgis = qgis;
181
  mFirstTime = true;
182

    
183
  // Create action to select this window
184
  mWindowAction = new QAction( windowTitle(), this );
185
  connect( mWindowAction, SIGNAL( triggered() ), this, SLOT( activate() ) );
186

    
187
  QgsDebugMsg( "entered." );
188

    
189
  setMouseTracking( true );
190
  //mSplitter->setMouseTracking(true);
191
  mViewFrame->setMouseTracking( true );
192

    
193
  //create composer view
194
  mView = new QgsComposerView( mViewFrame );
195
  connectSlots();
196

    
197
  mComposition  = new QgsComposition( mQgis->mapCanvas()->mapRenderer() );
198
  mComposition->setParent( mView );
199
  mView->setComposition( mComposition );
200

    
201
  QgsCompositionWidget* compositionWidget = new QgsCompositionWidget( mCompositionOptionsFrame, mComposition );
202
  QObject::connect( mComposition, SIGNAL( paperSizeChanged() ), compositionWidget, SLOT( displayCompositionWidthHeight() ) );
203
  compositionWidget->show();
204

    
205
  mCompositionOptionsLayout = new QGridLayout( mCompositionOptionsFrame );
206
  mCompositionOptionsLayout->setMargin( 0 );
207
  mCompositionOptionsLayout->addWidget( compositionWidget );
208

    
209
  QGridLayout *l = new QGridLayout( mViewFrame );
210
  l->setMargin( 0 );
211
  l->addWidget( mView, 0, 0 );
212

    
213
  mCompositionNameComboBox->insertItem( 0, tr( "Map 1" ) );
214

    
215
  // Create size grip (needed by Mac OS X for QMainWindow if QStatusBar is not visible)
216
  mSizeGrip = new QSizeGrip( this );
217
  mSizeGrip->resize( mSizeGrip->sizeHint() );
218
  mSizeGrip->move( rect().bottomRight() - mSizeGrip->rect().bottomRight() );
219

    
220
  restoreWindowState();
221
  setSelectionTool();
222

    
223
  mView->setFocus();
224

    
225
  //connect with signals from QgsProject to write project files
226
  if ( QgsProject::instance() )
227
  {
228
    connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument& ) ), this, SLOT( writeXML( QDomDocument& ) ) );
229
  }
230
}
231

    
232
QgsComposer::~QgsComposer()
233
{
234
  deleteItems();
235
}
236

    
237
void QgsComposer::setupTheme()
238
{
239
  //now set all the icons - getThemeIcon will fall back to default theme if its
240
  //missing from active theme
241
  mActionQuit->setIcon( QgisApp::getThemeIcon( "/mActionFileExit.png" ) );
242
  mActionLoadFromTemplate->setIcon( QgisApp::getThemeIcon( "/mActionFileOpen.png" ) );
243
  mActionSaveAsTemplate->setIcon( QgisApp::getThemeIcon( "/mActionFileSaveAs.png" ) );
244
  mActionExportAsImage->setIcon( QgisApp::getThemeIcon( "/mActionSaveMapAsImage.png" ) );
245
  mActionExportAsSVG->setIcon( QgisApp::getThemeIcon( "/mActionSaveAsSVG.png" ) );
246
  mActionExportAsPDF->setIcon( QgisApp::getThemeIcon( "/mActionSaveAsPDF.png" ) );
247
  mActionPrint->setIcon( QgisApp::getThemeIcon( "/mActionFilePrint.png" ) );
248
  mActionZoomAll->setIcon( QgisApp::getThemeIcon( "/mActionZoomFullExtent.png" ) );
249
  mActionZoomIn->setIcon( QgisApp::getThemeIcon( "/mActionZoomIn.png" ) );
250
  mActionZoomOut->setIcon( QgisApp::getThemeIcon( "/mActionZoomOut.png" ) );
251
  mActionRefreshView->setIcon( QgisApp::getThemeIcon( "/mActionDraw.png" ) );
252
  mActionAddImage->setIcon( QgisApp::getThemeIcon( "/mActionAddImage.png" ) );
253
  mActionAddNewMap->setIcon( QgisApp::getThemeIcon( "/mActionAddMap.png" ) );
254
  mActionAddNewLabel->setIcon( QgisApp::getThemeIcon( "/mActionLabel.png" ) );
255
  mActionAddNewLegend->setIcon( QgisApp::getThemeIcon( "/mActionAddLegend.png" ) );
256
  mActionAddNewScalebar->setIcon( QgisApp::getThemeIcon( "/mActionScaleBar.png" ) );
257
  mActionAddBasicShape->setIcon( QgisApp::getThemeIcon( "/mActionAddBasicShape.png" ) );
258
  mActionAddArrow->setIcon( QgisApp::getThemeIcon( "/mActionAddArrow.png" ) );
259
  mActionAddTable->setIcon( QgisApp::getThemeIcon( "/mActionOpenTable.png" ) );
260
  mActionSelectMoveItem->setIcon( QgisApp::getThemeIcon( "/mActionSelectPan.png" ) );
261
  mActionMoveItemContent->setIcon( QgisApp::getThemeIcon( "/mActionMoveItemContent.png" ) );
262
  mActionGroupItems->setIcon( QgisApp::getThemeIcon( "/mActionGroupItems.png" ) );
263
  mActionUngroupItems->setIcon( QgisApp::getThemeIcon( "/mActionUngroupItems.png" ) );
264
  mActionRaiseItems->setIcon( QgisApp::getThemeIcon( "/mActionRaiseItems.png" ) );
265
  mActionLowerItems->setIcon( QgisApp::getThemeIcon( "/mActionLowerItems.png" ) );
266
  mActionMoveItemsToTop->setIcon( QgisApp::getThemeIcon( "/mActionMoveItemsToTop.png" ) );
267
  mActionMoveItemsToBottom->setIcon( QgisApp::getThemeIcon( "/mActionMoveItemsToBottom.png" ) );
268
  mActionAlignLeft->setIcon( QgisApp::getThemeIcon( "/mActionAlignLeft.png" ) );
269
  mActionAlignHCenter->setIcon( QgisApp::getThemeIcon( "/mActionAlignHCenter.png" ) );
270
  mActionAlignRight->setIcon( QgisApp::getThemeIcon( "/mActionAlignRight.png" ) );
271
  mActionAlignTop->setIcon( QgisApp::getThemeIcon( "/mActionAlignTop.png" ) );
272
  mActionAlignVCenter->setIcon( QgisApp::getThemeIcon( "/mActionAlignVCenter.png" ) );
273
  mActionAlignBottom->setIcon( QgisApp::getThemeIcon( "/mActionAlignBottom.png" ) );
274
}
275

    
276
void QgsComposer::connectSlots()
277
{
278
  connect( mView, SIGNAL( selectedItemChanged( const QgsComposerItem* ) ), this, SLOT( showItemOptions( const QgsComposerItem* ) ) );
279
  connect( mView, SIGNAL( composerLabelAdded( QgsComposerLabel* ) ), this, SLOT( addComposerLabel( QgsComposerLabel* ) ) );
280
  connect( mView, SIGNAL( composerMapAdded( QgsComposerMap* ) ), this, SLOT( addComposerMap( QgsComposerMap* ) ) );
281
  connect( mView, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( deleteItem( QgsComposerItem* ) ) );
282
  connect( mView, SIGNAL( composerScaleBarAdded( QgsComposerScaleBar* ) ), this, SLOT( addComposerScaleBar( QgsComposerScaleBar* ) ) );
283
  connect( mView, SIGNAL( composerLegendAdded( QgsComposerLegend* ) ), this, SLOT( addComposerLegend( QgsComposerLegend* ) ) );
284
  connect( mView, SIGNAL( composerPictureAdded( QgsComposerPicture* ) ), this, SLOT( addComposerPicture( QgsComposerPicture* ) ) );
285
  connect( mView, SIGNAL( composerShapeAdded( QgsComposerShape* ) ), this, SLOT( addComposerShape( QgsComposerShape* ) ) );
286
  connect( mView, SIGNAL( composerArrowAdded( QgsComposerArrow* ) ), this, SLOT( addComposerArrow( QgsComposerArrow* ) ) );
287
  connect( mView, SIGNAL( composerTableAdded( QgsComposerAttributeTable* ) ), this, SLOT( addComposerTable( QgsComposerAttributeTable* ) ) );
288
  connect( mView, SIGNAL( actionFinished() ), this, SLOT( setSelectionTool() ) );
289
}
290

    
291
void QgsComposer::open( void )
292
{
293
  if ( mFirstTime )
294
  {
295
    //mComposition->createDefault();
296
    mFirstTime = false;
297
    show();
298
    zoomFull(); // zoomFull() does not work properly until we have called show()
299
  }
300

    
301
  else
302
  {
303
    show(); //make sure the window is displayed - with a saved project, it's possible to not have already called show()
304
    //is that a bug?
305
    activate(); //bring the composer window to the front
306
  }
307
}
308

    
309
void QgsComposer::activate()
310
{
311
  show();
312
  raise();
313
  setWindowState( windowState() & ~Qt::WindowMinimized );
314
  activateWindow();
315
}
316

    
317
#ifdef Q_WS_MAC
318
void QgsComposer::changeEvent( QEvent* event )
319
{
320
  QMainWindow::changeEvent( event );
321
  switch ( event->type() )
322
  {
323
    case QEvent::ActivationChange:
324
      if ( QApplication::activeWindow() == this )
325
      {
326
        mWindowAction->setChecked( true );
327
      }
328
      break;
329

    
330
    default:
331
      break;
332
  }
333
}
334

    
335
void QgsComposer::showEvent( QShowEvent *event )
336
{
337
  QMainWindow::showEvent( event );
338
  // add to menu if (re)opening window (event not due to unminimize)
339
  if ( !event->spontaneous() )
340
  {
341
    QgisApp::instance()->addWindow( mWindowAction );
342
  }
343
}
344
#endif
345

    
346
void QgsComposer::setTitle( const QString& title )
347
{
348
  mTitle = title;
349
  setWindowTitle( mTitle );
350
  if ( mWindowAction )
351
  {
352
    mWindowAction->setText( title );
353
  }
354
}
355

    
356
void QgsComposer::showCompositionOptions( QWidget *w )
357
{
358
  QWidget* currentWidget = mItemStackedWidget->currentWidget();
359
  mItemStackedWidget->removeWidget( currentWidget );
360
  mItemStackedWidget->addWidget( w );
361
}
362

    
363
void QgsComposer::showItemOptions( const QgsComposerItem* item )
364
{
365
  QWidget* currentWidget = mItemStackedWidget->currentWidget();
366

    
367
  if ( !item )
368
  {
369
    mItemStackedWidget->removeWidget( currentWidget );
370
    mItemStackedWidget->setCurrentWidget( 0 );
371
    return;
372
  }
373

    
374
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.find( const_cast<QgsComposerItem*>( item ) );
375
  if ( it == mItemWidgetMap.constEnd() )
376
  {
377
    return;
378
  }
379

    
380
  QWidget* newWidget = it.value();
381

    
382
  if ( !newWidget || newWidget == currentWidget ) //bail out if new widget does not exist or is already there
383
  {
384
    return;
385
  }
386

    
387
  mItemStackedWidget->removeWidget( currentWidget );
388
  mItemStackedWidget->addWidget( newWidget );
389
  mItemStackedWidget->setCurrentWidget( newWidget );
390
  //newWidget->show();
391
}
392

    
393
QgsMapCanvas *QgsComposer::mapCanvas( void )
394
{
395
  return mQgis->mapCanvas();
396
}
397

    
398
QgsComposerView *QgsComposer::view( void )
399
{
400
  return mView;
401
}
402

    
403
/*QgsComposition *QgsComposer::composition(void)
404
{
405
  return mComposition;
406
  }*/
407

    
408
void QgsComposer::zoomFull( void )
409
{
410
  if ( mView )
411
  {
412
    mView->fitInView( 0, 0, mComposition->paperWidth() + 1, mComposition->paperHeight() + 1, Qt::KeepAspectRatio );
413
  }
414
}
415

    
416
void QgsComposer::on_mActionZoomAll_triggered()
417
{
418
  zoomFull();
419
  mView->update();
420
  emit zoomLevelChanged();
421
}
422

    
423
void QgsComposer::on_mActionZoomIn_triggered()
424
{
425
  mView->scale( 2, 2 );
426
  mView->update();
427
  emit zoomLevelChanged();
428
}
429

    
430
void QgsComposer::on_mActionZoomOut_triggered()
431
{
432
  mView->scale( .5, .5 );
433
  mView->update();
434
  emit zoomLevelChanged();
435
}
436

    
437
void QgsComposer::on_mActionRefreshView_triggered()
438
{
439
  if ( !mComposition )
440
  {
441
    return;
442
  }
443

    
444
  //refresh preview of all composer maps
445
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.begin();
446
  for ( ; it != mItemWidgetMap.end(); ++it )
447
  {
448
    QgsComposerMap* map = dynamic_cast<QgsComposerMap*>( it.key() );
449
    if ( map && !map->isDrawing() )
450
    {
451
      map->cache();
452
      map->update();
453
    }
454
  }
455

    
456
  mComposition->update();
457
}
458

    
459
void QgsComposer::on_mActionExportAsPDF_triggered()
460
{
461
  QSettings myQSettings;  // where we keep last used filter in persistent state
462
  QString myFormat = "pdf";
463
  QString myLastUsedFile = myQSettings.value( "/UI/lastSaveAsPdfFile", "qgis.pdf" ).toString();
464
  QFileInfo file( myLastUsedFile );
465
  QFileDialog *myQFileDialog = new QFileDialog( this, tr( "Choose a file name to save the map as" ),
466
      file.path(), tr( "PDF Format" ) + " (*.pdf *.PDF)" );
467
  myQFileDialog->selectFile( file.fileName() );
468
  myQFileDialog->setFileMode( QFileDialog::AnyFile );
469
  myQFileDialog->setAcceptMode( QFileDialog::AcceptSave );
470

    
471
  int result = myQFileDialog->exec();
472
  raise();
473
  if ( result != QDialog::Accepted ) return;
474

    
475
  QString myOutputFileNameQString = myQFileDialog->selectedFiles().first();
476
  if ( myOutputFileNameQString == "" ) return;
477

    
478
  // Add the file type suffix to the fileName if required
479
  int x = QString::compare(myOutputFileNameQString.right(3), myFormat, Qt::CaseInsensitive);
480
  if ( false != x)
481
  {
482
    myOutputFileNameQString += "." + myFormat;
483
  }
484

    
485

    
486
  myQSettings.setValue( "/UI/lastSaveAsPdfFile", myOutputFileNameQString );
487

    
488
  QPrinter printer;
489

    
490
  printer.setOutputFormat( QPrinter::PdfFormat );
491
  printer.setOutputFileName( myOutputFileNameQString );
492
  printer.setPaperSize( QSizeF( mComposition->paperWidth(), mComposition->paperHeight() ), QPrinter::Millimeter );
493

    
494
  print( printer );
495
}
496

    
497
void QgsComposer::on_mActionPrint_triggered()
498
{
499
  //QPrinter printer;
500
  if ( mComposition )
501
  {
502
    if ( mComposition->paperWidth() >= mComposition->paperHeight() )
503
    {
504
      mPrinter.setOrientation( QPrinter::Landscape );
505
    }
506
    else
507
    {
508
      mPrinter.setOrientation( QPrinter::Portrait );
509
    }
510
  }
511
  mPrinter.setPaperSize( QSizeF( mComposition->paperWidth(), mComposition->paperHeight() ), QPrinter::Millimeter );
512
  QPrintDialog printDialog( &mPrinter, 0 );
513
  if ( printDialog.exec() != QDialog::Accepted )
514
  {
515
    return;
516
  }
517

    
518
  print( mPrinter );
519
}
520

    
521
void QgsComposer::print( QPrinter &printer )
522
{
523
  if ( !mComposition )
524
    return;
525

    
526
  if ( containsWMSLayer() )
527
  {
528
    showWMSPrintingWarning();
529
  }
530

    
531
  //set resolution based on composer setting
532
  printer.setFullPage( true );
533
  printer.setColorMode( QPrinter::Color );
534

    
535
  //set user-defined resolution
536
  printer.setResolution( mComposition->printResolution() );
537

    
538
  QPainter p( &printer );
539

    
540
  QgsComposition::PlotStyle savedPlotStyle = mComposition->plotStyle();
541
  mComposition->setPlotStyle( QgsComposition::Print );
542

    
543
  QApplication::setOverrideCursor( Qt::BusyCursor );
544

    
545
  if ( mComposition->printAsRaster() )
546
  {
547
    //print out via QImage, code copied from on_mActionExportAsImage_activated
548
    int width = ( int )( mComposition->printResolution() * mComposition->paperWidth() / 25.4 );
549
    int height = ( int )( mComposition-> printResolution() * mComposition->paperHeight() / 25.4 );
550
    QImage image( QSize( width, height ), QImage::Format_ARGB32 );
551
    image.setDotsPerMeterX( mComposition->printResolution() / 25.4 * 1000 );
552
    image.setDotsPerMeterY( mComposition->printResolution() / 25.4 * 1000 );
553
    image.fill( 0 );
554
    QPainter imagePainter( &image );
555
    QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
556
    QRectF targetArea( 0, 0, width, height );
557
    mComposition->render( &imagePainter, targetArea, sourceArea );
558
    imagePainter.end();
559
    p.drawImage( targetArea, image, targetArea );
560
  }
561
  else
562
  {
563
    //better in case of custom page size, but only possible with Qt>=4.4.0
564
    QRectF paperRectMM = printer.pageRect( QPrinter::Millimeter );
565
    QRectF paperRectPixel = printer.pageRect( QPrinter::DevicePixel );
566
    mComposition->render( &p, paperRectPixel, paperRectMM );
567
  }
568
  mComposition->setPlotStyle( savedPlotStyle );
569
  QApplication::restoreOverrideCursor();
570
}
571

    
572
void QgsComposer::on_mActionExportAsImage_triggered()
573
{
574
  if ( containsWMSLayer() )
575
  {
576
    showWMSPrintingWarning();
577
  }
578

    
579
  // Image size
580
  int width = ( int )( mComposition->printResolution() * mComposition->paperWidth() / 25.4 );
581
  int height = ( int )( mComposition-> printResolution() * mComposition->paperHeight() / 25.4 );
582

    
583
  int memuse = width * height * 3 / 1000000;  // pixmap + image
584
  QgsDebugMsg( QString( "Image %1 x %2" ).arg( width ).arg( height ) );
585
  QgsDebugMsg( QString( "memuse = %1" ).arg( memuse ) );
586

    
587
  if ( memuse > 200 )   // cca 4500 x 4500
588
  {
589
    int answer = QMessageBox::warning( 0, tr( "Big image" ),
590
                                       tr( "To create image %1 x %2 requires circa %3 MB of memory" )
591
                                       .arg( width ).arg( height ).arg( memuse ),
592
                                       QMessageBox::Ok,  QMessageBox::Abort );
593

    
594
    raise();
595
    if ( answer == QMessageBox::Abort ) return;
596
  }
597

    
598
  // Get file and format (stolen from qgisapp.cpp but modified significantely)
599

    
600
  //create a map to hold the QImageIO names and the filter names
601
  //the QImageIO name must be passed to the mapcanvas saveas image function
602
  typedef QMap<QString, QString> FilterMap;
603
  FilterMap myFilterMap;
604

    
605
  //find out the last used filter
606
  QSettings myQSettings;  // where we keep last used filter in persistent state
607
  QString myLastUsedFormat = myQSettings.value( "/UI/lastSaveAsImageFormat", "png" ).toString();
608
  QString myLastUsedFile = myQSettings.value( "/UI/lastSaveAsImageFile", "qgis.png" ).toString();
609
  QFileInfo file( myLastUsedFile );
610

    
611
  // get a list of supported output image types
612
  int myCounterInt = 0;
613
  QString myFilters;
614
  QString myLastUsedFilter;
615
  for ( ; myCounterInt < QImageWriter::supportedImageFormats().count(); myCounterInt++ )
616
  {
617
    QString myFormat = QString( QImageWriter::supportedImageFormats().at( myCounterInt ) );
618
    QString myFilter = tr( "%1 format (*.%2 *.%3)" )
619
                       .arg( myFormat ).arg( myFormat.toLower() ).arg( myFormat.toUpper() );
620

    
621
    if ( myCounterInt > 0 ) myFilters += ";;";
622
    myFilters += myFilter;
623
    myFilterMap[myFilter] = myFormat;
624
    if ( myFormat == myLastUsedFormat )
625
    {
626
      myLastUsedFilter = myFilter;
627
    }
628
  }
629
#ifdef QGISDEBUG
630
  QgsDebugMsg( "Available Filters Map: " );
631
  FilterMap::Iterator myIterator;
632
  for ( myIterator = myFilterMap.begin(); myIterator != myFilterMap.end(); ++myIterator )
633
  {
634
    QgsDebugMsg( QString( "%1  :  %2" ).arg( myIterator.key() ).arg( myIterator.value() ) );
635
  }
636
#endif
637

    
638
  //create a file dialog using the the filter list generated above
639
  std::auto_ptr < QFileDialog > myQFileDialog(
640
    new QFileDialog(
641
      this,
642
      tr( "Choose a file name to save the map image as" ),
643
      file.path(),
644
      myFilters
645
    )
646
  );
647

    
648
  myQFileDialog->setFileMode( QFileDialog::AnyFile );
649

    
650
  // set the filter to the last one used
651
  myQFileDialog->selectFilter( myLastUsedFilter );
652

    
653
  // set the 'Open' button to something that makes more sense
654
  myQFileDialog->setAcceptMode( QFileDialog::AcceptSave );
655

    
656
  //prompt the user for a file name
657
  QString myOutputFileNameQString;
658

    
659
  int result = myQFileDialog->exec();
660
  //raise();
661

    
662
  if ( result != QDialog::Accepted )
663
  {
664
    return;
665
  }
666

    
667
  myOutputFileNameQString = myQFileDialog->selectedFiles().last();
668
  QgsDebugMsg( myOutputFileNameQString );
669
  QString myFilterString = myQFileDialog->selectedFilter();
670
  QgsDebugMsg( QString( "Selected filter: %1" ).arg( myFilterString ) );
671
  QgsDebugMsg( QString( "Image type: %1" ).arg( myFilterMap[myFilterString] ) );
672

    
673
  // Add the file type suffix to the fileName if required
674
  if ( !myOutputFileNameQString.endsWith( myFilterMap[myFilterString] ) )
675
  {
676
    myOutputFileNameQString += "." + myFilterMap[myFilterString];
677
  }
678

    
679
  myQSettings.setValue( "/UI/lastSaveAsImageFormat", myFilterMap[myFilterString] );
680
  myQSettings.setValue( "/UI/lastSaveAsImageFile", myOutputFileNameQString );
681

    
682
  if ( myOutputFileNameQString == "" ) return;
683

    
684
  mComposition->setPlotStyle( QgsComposition::Print );
685
  mView->setScene( 0 );
686

    
687
  QImage image( QSize( width, height ), QImage::Format_ARGB32 );
688
  image.setDotsPerMeterX( mComposition->printResolution() / 25.4 * 1000 );
689
  image.setDotsPerMeterY( mComposition->printResolution() / 25.4 * 1000 );
690
  image.fill( 0 );
691
  QPainter p( &image );
692
  QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
693
  QRectF targetArea( 0, 0, width, height );
694
  mComposition->render( &p, targetArea, sourceArea );
695
  p.end();
696

    
697
  mComposition->setPlotStyle( QgsComposition::Preview );
698
  image.save( myOutputFileNameQString, myFilterMap[myFilterString].toLocal8Bit().data() );
699
  mView->setScene( mComposition );
700
}
701

    
702

    
703
void QgsComposer::on_mActionExportAsSVG_triggered()
704
{
705
  if ( containsWMSLayer() )
706
  {
707
    showWMSPrintingWarning();
708
  }
709

    
710
  QString myQSettingsLabel = "/UI/displaySVGWarning";
711
  QSettings myQSettings;
712

    
713
  bool displaySVGWarning = myQSettings.value( myQSettingsLabel, true ).toBool();
714

    
715
  if ( displaySVGWarning )
716
  {
717
    QgsMessageViewer* m = new QgsMessageViewer( this );
718
    m->setWindowTitle( tr( "SVG warning" ) );
719
    m->setCheckBoxText( tr( "Don't show this message again" ) );
720
    m->setCheckBoxState( Qt::Unchecked );
721
    m->setCheckBoxVisible( true );
722
    m->setCheckBoxQSettingsLabel( myQSettingsLabel );
723
    m->setMessageAsHtml( tr( "<p>The SVG export function in Qgis has several "
724
                             "problems due to bugs and deficiencies in the " )
725
                         + tr( "Qt4 svg code. In particular, there are problems "
726
                               "with layers not being clipped to the map "
727
                               "bounding box.</p>" )
728
                         + tr( "If you require a vector-based output file from "
729
                               "Qgis it is suggested that you try printing "
730
                               "to PostScript if the SVG output is not "
731
                               "satisfactory."
732
                               "</p>" ) );
733
    m->exec();
734
  }
735
  QString myLastUsedFile = myQSettings.value( "/UI/lastSaveAsSvgFile", "qgis.svg" ).toString();
736
  QFileInfo file( myLastUsedFile );
737
  QFileDialog *myQFileDialog = new QFileDialog( this, tr( "Choose a file name to save the map as" ),
738
      file.path(), tr( "SVG Format" ) + " (*.svg *.SVG)" );
739
  QString myFormat = "svg";
740
  myQFileDialog->selectFile( file.fileName() );
741
  myQFileDialog->setFileMode( QFileDialog::AnyFile );
742
  myQFileDialog->setAcceptMode( QFileDialog::AcceptSave );
743

    
744
  int result = myQFileDialog->exec();
745
  raise();
746
  if ( result != QDialog::Accepted ) return;
747

    
748
  QString myOutputFileNameQString = myQFileDialog->selectedFiles().first();
749
  if ( myOutputFileNameQString == "" ) return;
750

    
751

    
752
  // Add the file type suffix to the fileName if required
753
  int x = QString::compare(myOutputFileNameQString.right(3), myFormat, Qt::CaseInsensitive);
754
  if ( false != x)
755
  {
756
    myOutputFileNameQString += "." + myFormat;
757
  }
758

    
759
  myQSettings.setValue( "/UI/lastSaveAsSvgFile", myOutputFileNameQString );
760

    
761
  //mView->setScene(0);//don't redraw the scene on the display while we render
762
  mComposition->setPlotStyle( QgsComposition::Print );
763

    
764
  QSvgGenerator generator;
765
#if QT_VERSION >= 0x040500
766
  generator.setTitle( QgsProject::instance()->title() );
767
#endif
768
  generator.setFileName( myOutputFileNameQString );
769
  //width in pixel
770
  int width = ( int )( mComposition->paperWidth() * mComposition->printResolution() / 25.4 );
771
  //height in pixel
772
  int height = ( int )( mComposition->paperHeight() * mComposition->printResolution() / 25.4 );
773
  generator.setSize( QSize( width, height ) );
774
  generator.setResolution( mComposition->printResolution() ); //because the rendering is done in mm, convert the dpi
775

    
776
  QPainter p( &generator );
777

    
778
  QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
779
  QRectF targetArea( 0, 0, width, height );
780
  mComposition->render( &p, targetArea, sourceArea );
781

    
782
  p.end();
783

    
784
  mComposition->setPlotStyle( QgsComposition::Preview );
785
  //mView->setScene(mComposition->canvas()); //now that we're done, set the view to show the scene again
786
}
787

    
788
void QgsComposer::on_mActionSelectMoveItem_triggered()
789
{
790
  if ( mView )
791
  {
792
    mView->setCurrentTool( QgsComposerView::Select );
793
  }
794
}
795

    
796
void QgsComposer::on_mActionAddNewMap_triggered()
797
{
798
  if ( mView )
799
  {
800
    mView->setCurrentTool( QgsComposerView::AddMap );
801
  }
802
}
803

    
804
void QgsComposer::on_mActionAddNewLegend_triggered()
805
{
806
  if ( mView )
807
  {
808
    mView->setCurrentTool( QgsComposerView::AddLegend );
809
  }
810
}
811

    
812
void QgsComposer::on_mActionAddNewLabel_triggered()
813
{
814
  if ( mView )
815
  {
816
    mView->setCurrentTool( QgsComposerView::AddLabel );
817
  }
818
}
819

    
820
void QgsComposer::on_mActionAddNewScalebar_triggered()
821
{
822
  if ( mView )
823
  {
824
    mView->setCurrentTool( QgsComposerView::AddScalebar );
825
  }
826
}
827

    
828
void QgsComposer::on_mActionAddImage_triggered()
829
{
830
  if ( mView )
831
  {
832
    mView->setCurrentTool( QgsComposerView::AddPicture );
833
  }
834
}
835

    
836
void QgsComposer::on_mActionAddBasicShape_triggered()
837
{
838
  if ( mView )
839
  {
840
    mView->setCurrentTool( QgsComposerView::AddShape );
841
  }
842
}
843

    
844
void QgsComposer::on_mActionAddTable_triggered()
845
{
846
  if ( mView )
847
  {
848
    mView->setCurrentTool( QgsComposerView::AddTable );
849
  }
850
}
851

    
852
void QgsComposer::on_mActionAddArrow_triggered()
853
{
854
  if ( mView )
855
  {
856
    mView->setCurrentTool( QgsComposerView::AddArrow );
857
  }
858
}
859

    
860
void QgsComposer::on_mActionSaveAsTemplate_triggered()
861
{
862
  //show file dialog
863
  QSettings settings;
864
  QString lastSaveDir = settings.value( "UI/lastComposerTemplateDir", "" ).toString();
865
  QString saveFileName = QFileDialog::getSaveFileName( 0, tr( "save template" ), lastSaveDir, "*.qpt" );
866
  if ( saveFileName.isEmpty() )
867
  {
868
    return;
869
  }
870

    
871
  QFileInfo saveFileInfo( saveFileName );
872
  //check if suffix has been added
873
  if ( saveFileInfo.suffix().isEmpty() )
874
  {
875
    QString saveFileNameWithSuffix = saveFileName.append( ".qpt" );
876
    saveFileInfo = QFileInfo( saveFileNameWithSuffix );
877
  }
878
  settings.setValue( "UI/LastComposerTemplateDir", saveFileInfo.absolutePath() );
879

    
880
  QFile templateFile( saveFileName );
881
  if ( !templateFile.open( QIODevice::WriteOnly ) )
882
  {
883
    return;
884
  }
885

    
886
  QDomDocument saveDocument;
887
  writeXML( saveDocument, saveDocument );
888

    
889
  if ( templateFile.write( saveDocument.toByteArray() ) == -1 )
890
  {
891
    QMessageBox::warning( 0, tr( "Save error" ), tr( "Error, could not save file" ) );
892
  }
893
}
894

    
895
void QgsComposer::on_mActionLoadFromTemplate_triggered()
896
{
897
  QSettings settings;
898
  QString openFileDir = settings.value( "UI/lastComposerTemplateDir", "" ).toString();
899
  QString openFileString = QFileDialog::getOpenFileName( 0, tr( "Load template" ), openFileDir, "*.qpt" );
900

    
901
  if ( openFileString.isEmpty() )
902
  {
903
    return; //canceled by the user
904
  }
905

    
906
  QFileInfo openFileInfo( openFileString );
907
  settings.setValue( "UI/LastComposerTemplateDir", openFileInfo.absolutePath() );
908

    
909
  QFile templateFile( openFileString );
910
  if ( !templateFile.open( QIODevice::ReadOnly ) )
911
  {
912
    QMessageBox::warning( 0, tr( "Read error" ), tr( "Error, could not read file" ) );
913
    return;
914
  }
915

    
916
  QDomDocument templateDocument;
917
  if ( !templateDocument.setContent( &templateFile, false ) )
918
  {
919
    QMessageBox::warning( 0, tr( "Read error" ), tr( "Content of template file is not valid" ) );
920
    return;
921
  }
922

    
923
  deleteItems();
924
  readXML( templateDocument );
925
}
926

    
927
void QgsComposer::on_mActionMoveItemContent_triggered()
928
{
929
  if ( mView )
930
  {
931
    mView->setCurrentTool( QgsComposerView::MoveItemContent );
932
  }
933
}
934

    
935
void QgsComposer::on_mActionGroupItems_triggered()
936
{
937
  if ( mView )
938
  {
939
    mView->groupItems();
940
  }
941
}
942

    
943
void QgsComposer::on_mActionUngroupItems_triggered()
944
{
945
  if ( mView )
946
  {
947
    mView->ungroupItems();
948
  }
949
}
950

    
951
void QgsComposer::on_mActionRaiseItems_triggered()
952
{
953
  if ( mComposition )
954
  {
955
    mComposition->raiseSelectedItems();
956
  }
957
}
958

    
959
void QgsComposer::on_mActionLowerItems_triggered()
960
{
961
  if ( mComposition )
962
  {
963
    mComposition->lowerSelectedItems();
964
  }
965
}
966

    
967
void QgsComposer::on_mActionMoveItemsToTop_triggered()
968
{
969
  if ( mComposition )
970
  {
971
    mComposition->moveSelectedItemsToTop();
972
  }
973
}
974

    
975
void QgsComposer::on_mActionMoveItemsToBottom_triggered()
976
{
977
  if ( mComposition )
978
  {
979
    mComposition->moveSelectedItemsToBottom();
980
  }
981
}
982

    
983
void QgsComposer::on_mActionAlignLeft_triggered()
984
{
985
  if ( mComposition )
986
  {
987
    mComposition->alignSelectedItemsLeft();
988
  }
989
}
990

    
991
void QgsComposer::on_mActionAlignHCenter_triggered()
992
{
993
  if ( mComposition )
994
  {
995
    mComposition->alignSelectedItemsHCenter();
996
  }
997
}
998

    
999
void QgsComposer::on_mActionAlignRight_triggered()
1000
{
1001
  if ( mComposition )
1002
  {
1003
    mComposition->alignSelectedItemsRight();
1004
  }
1005
}
1006

    
1007
void QgsComposer::on_mActionAlignTop_triggered()
1008
{
1009
  if ( mComposition )
1010
  {
1011
    mComposition->alignSelectedItemsTop();
1012
  }
1013
}
1014

    
1015
void QgsComposer::on_mActionAlignVCenter_triggered()
1016
{
1017
  if ( mComposition )
1018
  {
1019
    mComposition->alignSelectedItemsVCenter();
1020
  }
1021
}
1022

    
1023
void QgsComposer::on_mActionAlignBottom_triggered()
1024
{
1025
  if ( mComposition )
1026
  {
1027
    mComposition->alignSelectedItemsBottom();
1028
  }
1029
}
1030

    
1031
void QgsComposer::moveEvent( QMoveEvent *e ) { saveWindowState(); }
1032

    
1033
void QgsComposer::resizeEvent( QResizeEvent *e )
1034
{
1035
  // Move size grip when window is resized
1036
  mSizeGrip->move( rect().bottomRight() - mSizeGrip->rect().bottomRight() );
1037

    
1038
  saveWindowState();
1039
}
1040

    
1041
void QgsComposer::saveWindowState()
1042
{
1043
  QSettings settings;
1044
  settings.setValue( "/Composer/geometry", saveGeometry() );
1045
  //settings.setValue("/Composer/splitterState", mSplitter->saveState());
1046
}
1047

    
1048
void QgsComposer::restoreWindowState()
1049
{
1050
  QSettings settings;
1051
  restoreGeometry( settings.value( "/Composer/geometry" ).toByteArray() );
1052
  QVariant splitterState = settings.value( "/Composer/splitterState" );
1053
  if ( splitterState != QVariant::QVariant() )
1054
  {
1055
    //mSplitter->restoreState(settings.value("/Composer/splitterState").toByteArray());
1056
  }
1057
  else
1058
  {
1059
    QList<int> defaultSize;
1060
    defaultSize << 300 << 100; // page display 300 pixels, details pane 100 pixels
1061
    //mSplitter->setSizes(defaultSize);
1062
  }
1063
}
1064

    
1065
void  QgsComposer::writeXML( QDomDocument& doc )
1066
{
1067

    
1068
  QDomNodeList nl = doc.elementsByTagName( "qgis" );
1069
  if ( nl.count() < 1 )
1070
  {
1071
    return;
1072
  }
1073
  QDomElement qgisElem = nl.at( 0 ).toElement();
1074
  if ( qgisElem.isNull() )
1075
  {
1076
    return;
1077
  }
1078

    
1079
  writeXML( qgisElem, doc );
1080
}
1081

    
1082
void QgsComposer::writeXML( QDomNode& parentNode, QDomDocument& doc )
1083
{
1084
  QDomElement composerElem = doc.createElement( "Composer" );
1085
  composerElem.setAttribute( "title", mTitle );
1086

    
1087
  //store if composer is open or closed
1088
  if ( isVisible() )
1089
  {
1090
    composerElem.setAttribute( "visible", 1 );
1091
  }
1092
  else
1093
  {
1094
    composerElem.setAttribute( "visible", 0 );
1095
  }
1096
  parentNode.appendChild( composerElem );
1097

    
1098
  //store composer items:
1099
  QMap<QgsComposerItem*, QWidget*>::const_iterator itemIt = mItemWidgetMap.constBegin();
1100
  for ( ; itemIt != mItemWidgetMap.constEnd(); ++itemIt )
1101
  {
1102
    itemIt.key()->writeXML( composerElem, doc );
1103
  }
1104

    
1105
  //store composer view
1106

    
1107
  //store composition
1108
  if ( mComposition )
1109
  {
1110
    mComposition->writeXML( composerElem, doc );
1111
  }
1112
}
1113

    
1114
void QgsComposer::readXML( const QDomDocument& doc )
1115
{
1116
  QDomNodeList composerNodeList = doc.elementsByTagName( "Composer" );
1117
  if ( composerNodeList.size() < 1 )
1118
  {
1119
    return;
1120
  }
1121
  readXML( composerNodeList.at( 0 ).toElement(), doc, true );
1122
  cleanupAfterTemplateRead();
1123
}
1124

    
1125
void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument& doc, bool fromTemplate )
1126
{
1127
  // Set title only if reading from project file
1128
  if ( !fromTemplate )
1129
  {
1130
    if ( composerElem.hasAttribute( "title" ) )
1131
    {
1132
      setTitle( composerElem.attribute( "title", tr( "Composer" ) ) );
1133
    }
1134
  }
1135

    
1136
  //delete composer view and composition
1137
  delete mView;
1138
  mView = 0;
1139
  //delete every child of mViewFrame
1140
  QObjectList viewFrameChildren = mViewFrame->children();
1141
  QObjectList::iterator it = viewFrameChildren.begin();
1142
  for ( ; it != viewFrameChildren.end(); ++it )
1143
  {
1144
    delete( *it );
1145
  }
1146
  //delete composition widget
1147
  QgsCompositionWidget* oldCompositionWidget = qobject_cast<QgsCompositionWidget *>( mCompositionOptionsFrame->children().at( 0 ) );
1148
  delete oldCompositionWidget;
1149
  delete mCompositionOptionsLayout;
1150
  mCompositionOptionsLayout = 0;
1151

    
1152
  mView = new QgsComposerView( mViewFrame );
1153
  connectSlots();
1154

    
1155
  //read composition settings
1156
  mComposition = new QgsComposition( mQgis->mapCanvas()->mapRenderer() );
1157
  QDomNodeList compositionNodeList = composerElem.elementsByTagName( "Composition" );
1158
  if ( compositionNodeList.size() > 0 )
1159
  {
1160
    QDomElement compositionElem = compositionNodeList.at( 0 ).toElement();
1161
    mComposition->readXML( compositionElem, doc );
1162
  }
1163

    
1164
  QGridLayout *l = new QGridLayout( mViewFrame );
1165
  l->setMargin( 0 );
1166
  l->addWidget( mView, 0, 0 );
1167

    
1168
  //create compositionwidget
1169
  QgsCompositionWidget* compositionWidget = new QgsCompositionWidget( mCompositionOptionsFrame, mComposition );
1170
  QObject::connect( mComposition, SIGNAL( paperSizeChanged() ), compositionWidget, SLOT( displayCompositionWidthHeight() ) );
1171
  compositionWidget->show();
1172

    
1173
  mCompositionOptionsLayout = new QGridLayout( mCompositionOptionsFrame );
1174
  mCompositionOptionsLayout->setMargin( 0 );
1175
  mCompositionOptionsLayout->addWidget( compositionWidget );
1176

    
1177
  //read and restore all the items
1178

    
1179
  //composer labels
1180
  QDomNodeList composerLabelList = composerElem.elementsByTagName( "ComposerLabel" );
1181
  for ( int i = 0; i < composerLabelList.size(); ++i )
1182
  {
1183
    QDomElement currentComposerLabelElem = composerLabelList.at( i ).toElement();
1184
    QgsComposerLabel* newLabel = new QgsComposerLabel( mComposition );
1185
    newLabel->readXML( currentComposerLabelElem, doc );
1186
    addComposerLabel( newLabel );
1187
    mComposition->addItem( newLabel );
1188
    mComposition->update();
1189
    mComposition->clearSelection();
1190
    newLabel->setSelected( true );
1191
    showItemOptions( newLabel );
1192
  }
1193

    
1194
  //composer maps
1195
  QDomNodeList composerMapList = composerElem.elementsByTagName( "ComposerMap" );
1196
  for ( int i = 0; i < composerMapList.size(); ++i )
1197
  {
1198
    QDomElement currentComposerMapElem = composerMapList.at( i ).toElement();
1199
    QgsComposerMap* newMap = new QgsComposerMap( mComposition );
1200
    newMap->readXML( currentComposerMapElem, doc );
1201
    addComposerMap( newMap );
1202
    mComposition->addItem( newMap );
1203
    mComposition->update();
1204
    mComposition->clearSelection();
1205
    newMap->setSelected( true );
1206
    showItemOptions( newMap );
1207
  }
1208

    
1209
  //composer scalebars
1210
  QDomNodeList composerScaleBarList = composerElem.elementsByTagName( "ComposerScaleBar" );
1211
  for ( int i = 0; i < composerScaleBarList.size(); ++i )
1212
  {
1213
    QDomElement currentScaleBarElem = composerScaleBarList.at( i ).toElement();
1214
    QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( mComposition );
1215
    newScaleBar->readXML( currentScaleBarElem, doc );
1216
    addComposerScaleBar( newScaleBar );
1217
    mComposition->addItem( newScaleBar );
1218
    mComposition->update();
1219
    mComposition->clearSelection();
1220
    newScaleBar->setSelected( true );
1221
    showItemOptions( newScaleBar );
1222
  }
1223

    
1224
  //composer legends
1225
  QDomNodeList composerLegendList = composerElem.elementsByTagName( "ComposerLegend" );
1226
  for ( int i = 0; i < composerLegendList.size(); ++i )
1227
  {
1228
    QDomElement currentLegendElem = composerLegendList.at( i ).toElement();
1229
    QgsComposerLegend* newLegend = new QgsComposerLegend( mComposition );
1230
    newLegend->readXML( currentLegendElem, doc );
1231
    addComposerLegend( newLegend );
1232
    mComposition->addItem( newLegend );
1233
    mComposition->update();
1234
    mComposition->clearSelection();
1235
    newLegend->setSelected( true );
1236
    showItemOptions( newLegend );
1237
  }
1238

    
1239
  //composer pictures
1240
  QDomNodeList composerPictureList = composerElem.elementsByTagName( "ComposerPicture" );
1241
  for ( int i = 0; i < composerPictureList.size(); ++i )
1242
  {
1243
    QDomElement currentPictureElem = composerPictureList.at( i ).toElement();
1244
    QgsComposerPicture* newPicture = new QgsComposerPicture( mComposition );
1245
    newPicture->readXML( currentPictureElem, doc );
1246
    addComposerPicture( newPicture );
1247
    mComposition->addItem( newPicture );
1248
    mComposition->update();
1249
    mComposition->clearSelection();
1250
    newPicture->setSelected( true );
1251
    showItemOptions( newPicture );
1252
  }
1253

    
1254
  //composer shapes
1255
  QDomNodeList composerShapeList = composerElem.elementsByTagName( "ComposerShape" );
1256
  for ( int i = 0; i < composerShapeList.size(); ++i )
1257
  {
1258
    QDomElement currentShapeElem = composerShapeList.at( i ).toElement();
1259
    QgsComposerShape* newShape = new QgsComposerShape( mComposition );
1260
    newShape->readXML( currentShapeElem, doc );
1261
    addComposerShape( newShape );
1262
    mComposition->addItem( newShape );
1263
    mComposition->update();
1264
    mComposition->clearSelection();
1265
    newShape->setSelected( true );
1266
    showItemOptions( newShape );
1267
  }
1268

    
1269
  //composer arrows
1270
  QDomNodeList composerArrowList = composerElem.elementsByTagName( "ComposerArrow" );
1271
  for ( int i = 0; i < composerArrowList.size(); ++i )
1272
  {
1273
    QDomElement currentArrowElem = composerArrowList.at( i ).toElement();
1274
    QgsComposerArrow* newArrow = new QgsComposerArrow( mComposition );
1275
    newArrow->readXML( currentArrowElem, doc );
1276
    addComposerArrow( newArrow );
1277
    mComposition->addItem( newArrow );
1278
    mComposition->update();
1279
    mComposition->clearSelection();
1280
    newArrow->setSelected( true );
1281
    showItemOptions( newArrow );
1282
  }
1283

    
1284
  //composer tables
1285
  QDomNodeList composerTableList = composerElem.elementsByTagName( "ComposerAttributeTable" );
1286
  for ( int i = 0; i < composerTableList.size(); ++i )
1287
  {
1288
    QDomElement currentTableElem = composerTableList.at( i ).toElement();
1289
    QgsComposerAttributeTable* newTable = new QgsComposerAttributeTable( mComposition );
1290
    newTable->readXML( currentTableElem, doc );
1291
    addComposerTable( newTable );
1292
    mComposition->addItem( newTable );
1293
    mComposition->update();
1294
    mComposition->clearSelection();
1295
    newTable->setSelected( true );
1296
    showItemOptions( newTable );
1297
  }
1298

    
1299
  mComposition->sortZList();
1300
  mView->setComposition( mComposition );
1301

    
1302
  setSelectionTool();
1303
}
1304

    
1305
void QgsComposer::deleteItems()
1306
{
1307
  //delete all the items
1308
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.begin();
1309
  for ( ; it != mItemWidgetMap.end(); ++it )
1310
  {
1311
    delete it.key();
1312
    delete it.value();
1313
  }
1314
  mItemWidgetMap.clear();
1315
}
1316

    
1317
void QgsComposer::addComposerArrow( QgsComposerArrow* arrow )
1318
{
1319
  if ( !arrow )
1320
  {
1321
    return;
1322
  }
1323

    
1324
  QgsComposerArrowWidget* arrowWidget = new QgsComposerArrowWidget( arrow );
1325
  mItemWidgetMap.insert( arrow, arrowWidget );
1326
}
1327

    
1328
void QgsComposer::addComposerMap( QgsComposerMap* map )
1329
{
1330
  if ( !map )
1331
  {
1332
    return;
1333
  }
1334

    
1335
  map->setMapCanvas( mapCanvas() ); //set canvas to composer map to have the possibility to draw canvas items
1336
  QgsComposerMapWidget* mapWidget = new QgsComposerMapWidget( map );
1337
  connect( this, SIGNAL( zoomLevelChanged() ), map, SLOT( renderModeUpdateCachedImage() ) );
1338
  mItemWidgetMap.insert( map, mapWidget );
1339
}
1340

    
1341
void QgsComposer::addComposerLabel( QgsComposerLabel* label )
1342
{
1343
  if ( !label )
1344
  {
1345
    return;
1346
  }
1347

    
1348
  QgsComposerLabelWidget* labelWidget = new QgsComposerLabelWidget( label );
1349
  mItemWidgetMap.insert( label, labelWidget );
1350
}
1351

    
1352
void QgsComposer::addComposerScaleBar( QgsComposerScaleBar* scalebar )
1353
{
1354
  if ( !scalebar )
1355
  {
1356
    return;
1357
  }
1358

    
1359
  QgsComposerScaleBarWidget* sbWidget = new QgsComposerScaleBarWidget( scalebar );
1360
  mItemWidgetMap.insert( scalebar, sbWidget );
1361
}
1362

    
1363
void QgsComposer::addComposerLegend( QgsComposerLegend* legend )
1364
{
1365
  if ( !legend )
1366
  {
1367
    return;
1368
  }
1369

    
1370
  QgsComposerLegendWidget* lWidget = new QgsComposerLegendWidget( legend );
1371
  if ( sender() ) //only update if created from GUI (not after XML read)
1372
  {
1373
    lWidget->updateLegend();
1374
  }
1375
  mItemWidgetMap.insert( legend, lWidget );
1376
}
1377

    
1378
void QgsComposer::addComposerPicture( QgsComposerPicture* picture )
1379
{
1380
  if ( !picture )
1381
  {
1382
    return;
1383
  }
1384

    
1385
  QgsComposerPictureWidget* pWidget = new QgsComposerPictureWidget( picture );
1386
  mItemWidgetMap.insert( picture, pWidget );
1387
}
1388

    
1389
void QgsComposer::addComposerShape( QgsComposerShape* shape )
1390
{
1391
  if ( !shape )
1392
  {
1393
    return;
1394
  }
1395
  QgsComposerShapeWidget* sWidget = new QgsComposerShapeWidget( shape );
1396
  mItemWidgetMap.insert( shape, sWidget );
1397
}
1398

    
1399
void QgsComposer::addComposerTable( QgsComposerAttributeTable* table )
1400
{
1401
  if ( !table )
1402
  {
1403
    return;
1404
  }
1405
  QgsComposerTableWidget* tWidget = new QgsComposerTableWidget( table );
1406
  mItemWidgetMap.insert( table, tWidget );
1407
}
1408

    
1409
void QgsComposer::deleteItem( QgsComposerItem* item )
1410
{
1411
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.find( item );
1412

    
1413
  if ( it == mItemWidgetMap.end() )
1414
  {
1415
    return;
1416
  }
1417

    
1418
  delete( it.key() );
1419
  delete( it.value() );
1420
  mItemWidgetMap.remove( it.key() );
1421
}
1422

    
1423
void QgsComposer::setSelectionTool()
1424
{
1425
  mActionSelectMoveItem->setChecked( true );
1426
  on_mActionSelectMoveItem_triggered();
1427
}
1428

    
1429
bool QgsComposer::containsWMSLayer() const
1430
{
1431
  QMap<QgsComposerItem*, QWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
1432
  QgsComposerItem* currentItem = 0;
1433
  QgsComposerMap* currentMap = 0;
1434

    
1435
  for ( ; item_it != mItemWidgetMap.constEnd(); ++item_it )
1436
  {
1437
    currentItem = item_it.key();
1438
    currentMap = dynamic_cast<QgsComposerMap *>( currentItem );
1439
    if ( currentMap )
1440
    {
1441
      if ( currentMap->containsWMSLayer() )
1442
      {
1443
        return true;
1444
      }
1445
    }
1446
  }
1447
  return false;
1448
}
1449

    
1450
void QgsComposer::showWMSPrintingWarning()
1451
{
1452
  QString myQSettingsLabel = "/UI/displayComposerWMSWarning";
1453
  QSettings myQSettings;
1454

    
1455
  bool displayWMSWarning = myQSettings.value( myQSettingsLabel, true ).toBool();
1456
  if ( displayWMSWarning )
1457
  {
1458
    QgsMessageViewer* m = new QgsMessageViewer( this );
1459
    m->setWindowTitle( tr( "Project contains WMS layers" ) );
1460
    m->setMessage( tr( "Some WMS servers (e.g. UMN mapserver) have a limit for the WIDTH and HEIGHT parameter. Printing layers from such servers may exceed this limit. If this is the case, the WMS layer will not be printed" ), QgsMessageOutput::MessageText );
1461
    m->setCheckBoxText( tr( "Don't show this message again" ) );
1462
    m->setCheckBoxState( Qt::Unchecked );
1463
    m->setCheckBoxVisible( true );
1464
    m->setCheckBoxQSettingsLabel( myQSettingsLabel );
1465
    m->exec();
1466
  }
1467
}
1468

    
1469
void QgsComposer::cleanupAfterTemplateRead()
1470
{
1471
  QMap<QgsComposerItem*, QWidget*>::const_iterator itemIt = mItemWidgetMap.constBegin();
1472
  for ( ; itemIt != mItemWidgetMap.constEnd(); ++itemIt )
1473
  {
1474
    //update all legends completely
1475
    QgsComposerLegend* legendItem = dynamic_cast<QgsComposerLegend *>( itemIt.key() );
1476
    if ( legendItem )
1477
    {
1478
      legendItem->updateLegend();
1479
      continue;
1480
    }
1481

    
1482
    //update composer map extent if it does not intersect the full extent of all layers
1483
    QgsComposerMap* mapItem = dynamic_cast<QgsComposerMap *>( itemIt.key() );
1484
    if ( mapItem )
1485
    {
1486
      //test if composer map extent intersects extent of all layers
1487
      bool intersects = false;
1488
      QgsRectangle composerMapExtent = mapItem->extent();
1489
      if ( mQgis )
1490
      {
1491
        QgsMapCanvas* canvas = mQgis->mapCanvas();
1492
        if ( canvas )
1493
        {
1494
          QgsRectangle mapCanvasExtent = mQgis->mapCanvas()->fullExtent();
1495
          if ( composerMapExtent.intersects( mapCanvasExtent ) )
1496
          {
1497
            intersects = true;
1498
          }
1499
        }
1500
      }
1501

    
1502
      //if not: apply current canvas extent
1503
      if ( !intersects )
1504
      {
1505
        double currentWidth = mapItem->rect().width();
1506
        double currentHeight = mapItem->rect().height();
1507
        if ( currentWidth - 0 > 0.0 ) //don't divide through zero
1508
        {
1509
          QgsRectangle canvasExtent = mapItem->mapRenderer()->extent();
1510
          //adapt min y of extent such that the size of the map item stays the same
1511
          double newCanvasExtentHeight = currentHeight / currentWidth * canvasExtent.width();
1512
          canvasExtent.setYMinimum( canvasExtent.yMaximum() - newCanvasExtentHeight );
1513
          mapItem->setNewExtent( canvasExtent );
1514
        }
1515
      }
1516
    }
1517
  }
1518
}
1519

    
1520
void QgsComposer::on_mActionPageSetup_triggered()
1521
{
1522
  if ( !mComposition )
1523
  {
1524
    return;
1525
  }
1526

    
1527
  QPageSetupDialog pageSetupDialog( &mPrinter, this );
1528
  pageSetupDialog.exec();
1529
}