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

« back to all changes in this revision

Viewing changes to src/app/composer/qgscomposer.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
                         qgscomposer.cpp  -  description
 
3
                             -------------------
 
4
    begin                : January 2005
 
5
    copyright            : (C) 2005 by Radim Blazek
 
6
    email                : blazek@itc.it
 
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 "qgsexception.h"
 
39
#include "qgsproject.h"
 
40
#include "qgsmapcanvas.h"
 
41
#include "qgsmaprenderer.h"
 
42
#include "qgsmessageviewer.h"
 
43
#include "qgscontexthelp.h"
 
44
#include "qgscursors.h"
 
45
 
 
46
#include <QCloseEvent>
 
47
#include <QDesktopWidget>
 
48
#include <QFileDialog>
 
49
#include <QFileInfo>
 
50
#include <QMatrix>
 
51
#include <QMenuBar>
 
52
#include <QMessageBox>
 
53
#include <QPainter>
 
54
 
 
55
#include <QPrinter>
 
56
#include <QPrintDialog>
 
57
#include <QSettings>
 
58
#include <QIcon>
 
59
#include <QPixmap>
 
60
#if QT_VERSION < 0x040300
 
61
#include <Q3Picture>
 
62
#else
 
63
#include <QSvgGenerator>
 
64
#endif
 
65
#include <QToolBar>
 
66
#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 )
 
73
{
 
74
  setupUi( this );
 
75
  setWindowTitle( mTitle );
 
76
  setupTheme();
 
77
  QObject::connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( close() ) );
 
78
 
 
79
  QToolButton* orderingToolButton = new QToolButton( this );
 
80
  orderingToolButton->setPopupMode( QToolButton::InstantPopup );
 
81
  orderingToolButton->setAutoRaise( true );
 
82
  orderingToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly );
 
83
 
 
84
  orderingToolButton->addAction( mActionRaiseItems );
 
85
  orderingToolButton->addAction( mActionLowerItems );
 
86
  orderingToolButton->addAction( mActionMoveItemsToTop );
 
87
  orderingToolButton->addAction( mActionMoveItemsToBottom );
 
88
  orderingToolButton->setDefaultAction( mActionRaiseItems );
 
89
  toolBar->addWidget( orderingToolButton );
 
90
 
 
91
  QToolButton* alignToolButton = new QToolButton( this );
 
92
  alignToolButton->setPopupMode( QToolButton::InstantPopup );
 
93
  alignToolButton->setAutoRaise( true );
 
94
  alignToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly );
 
95
 
 
96
  alignToolButton->addAction( mActionAlignLeft );
 
97
  alignToolButton->addAction( mActionAlignHCenter );
 
98
  alignToolButton->addAction( mActionAlignRight );
 
99
  alignToolButton->addAction( mActionAlignTop );
 
100
  alignToolButton->addAction( mActionAlignVCenter );
 
101
  alignToolButton->addAction( mActionAlignBottom );
 
102
  alignToolButton->setDefaultAction( mActionAlignLeft );
 
103
  toolBar->addWidget( alignToolButton );
 
104
 
 
105
  QActionGroup* toggleActionGroup = new QActionGroup( this );
 
106
  toggleActionGroup->addAction( mActionMoveItemContent );
 
107
  toggleActionGroup->addAction( mActionAddNewMap );
 
108
  toggleActionGroup->addAction( mActionAddNewLabel );
 
109
  toggleActionGroup->addAction( mActionAddNewLegend );
 
110
  toggleActionGroup->addAction( mActionAddNewScalebar );
 
111
  toggleActionGroup->addAction( mActionAddImage );
 
112
  toggleActionGroup->addAction( mActionSelectMoveItem );
 
113
  toggleActionGroup->addAction( mActionAddBasicShape );
 
114
  toggleActionGroup->addAction( mActionAddArrow );
 
115
  toggleActionGroup->setExclusive( true );
 
116
 
 
117
  mActionAddNewMap->setCheckable( true );
 
118
  mActionAddNewLabel->setCheckable( true );
 
119
  mActionAddNewLegend->setCheckable( true );
 
120
  mActionSelectMoveItem->setCheckable( true );
 
121
  mActionAddNewScalebar->setCheckable( true );
 
122
  mActionAddImage->setCheckable( true );
 
123
  mActionMoveItemContent->setCheckable( true );
 
124
  mActionAddBasicShape->setCheckable( true );
 
125
  mActionAddArrow->setCheckable( true );
 
126
 
 
127
#ifdef Q_WS_MAC
 
128
  QMenu *appMenu = menuBar()->addMenu( tr( "QGIS" ) );
 
129
  appMenu->addAction( QgisApp::instance()->actionAbout() );
 
130
  appMenu->addAction( QgisApp::instance()->actionOptions() );
 
131
#endif
 
132
 
 
133
  QMenu *fileMenu = menuBar()->addMenu( tr( "File" ) );
 
134
  fileMenu->addAction( mActionLoadFromTemplate );
 
135
  fileMenu->addAction( mActionSaveAsTemplate );
 
136
  fileMenu->addSeparator();
 
137
  fileMenu->addAction( mActionExportAsImage );
 
138
  fileMenu->addAction( mActionExportAsPDF );
 
139
  fileMenu->addAction( mActionExportAsSVG );
 
140
  fileMenu->addSeparator();
 
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->addSeparator();
 
164
  layoutMenu->addAction( mActionGroupItems );
 
165
  layoutMenu->addAction( mActionUngroupItems );
 
166
  layoutMenu->addAction( mActionRaiseItems );
 
167
  layoutMenu->addAction( mActionLowerItems );
 
168
  layoutMenu->addAction( mActionMoveItemsToTop );
 
169
  layoutMenu->addAction( mActionMoveItemsToBottom );
 
170
 
 
171
#ifdef Q_WS_MAC
 
172
#ifndef Q_WS_MAC64 /* assertion failure in NSMenuItem setSubmenu (Qt 4.5.0-snapshot-20080830) */
 
173
  menuBar()->addMenu( QgisApp::instance()->windowMenu() );
 
174
 
 
175
  menuBar()->addMenu( QgisApp::instance()->helpMenu() );
 
176
#endif
 
177
#endif
 
178
 
 
179
  mQgis = qgis;
 
180
  mFirstTime = true;
 
181
 
 
182
  // Create action to select this window
 
183
  mWindowAction = new QAction( windowTitle(), this );
 
184
  connect( mWindowAction, SIGNAL( triggered() ), this, SLOT( activate() ) );
 
185
 
 
186
  QgsDebugMsg( "entered." );
 
187
 
 
188
  setMouseTracking( true );
 
189
  //mSplitter->setMouseTracking(true);
 
190
  mViewFrame->setMouseTracking( true );
 
191
 
 
192
  //create composer view
 
193
  mView = new QgsComposerView( mViewFrame );
 
194
  connectSlots();
 
195
 
 
196
  mComposition  = new QgsComposition( mQgis->mapCanvas()->mapRenderer() );
 
197
  mComposition->setParent( mView );
 
198
  mView->setComposition( mComposition );
 
199
 
 
200
  QgsCompositionWidget* compositionWidget = new QgsCompositionWidget( mCompositionOptionsFrame, mComposition );
 
201
  QObject::connect( mComposition, SIGNAL( paperSizeChanged() ), compositionWidget, SLOT( displayCompositionWidthHeight() ) );
 
202
  compositionWidget->show();
 
203
 
 
204
  mCompositionOptionsLayout = new QGridLayout( mCompositionOptionsFrame );
 
205
  mCompositionOptionsLayout->setMargin( 0 );
 
206
  mCompositionOptionsLayout->addWidget( compositionWidget );
 
207
 
 
208
  QGridLayout *l = new QGridLayout( mViewFrame );
 
209
  l->setMargin( 0 );
 
210
  l->addWidget( mView, 0, 0 );
 
211
 
 
212
  mCompositionNameComboBox->insertItem( 0, tr( "Map 1" ) );
 
213
 
 
214
  // Create size grip (needed by Mac OS X for QMainWindow if QStatusBar is not visible)
 
215
  mSizeGrip = new QSizeGrip( this );
 
216
  mSizeGrip->resize( mSizeGrip->sizeHint() );
 
217
  mSizeGrip->move( rect().bottomRight() - mSizeGrip->rect().bottomRight() );
 
218
 
 
219
  restoreWindowState();
 
220
  setSelectionTool();
 
221
 
 
222
  mView->setFocus();
 
223
 
 
224
  //connect with signals from QgsProject to write project files
 
225
  if ( QgsProject::instance() )
 
226
  {
 
227
    connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument& ) ), this, SLOT( writeXML( QDomDocument& ) ) );
 
228
  }
 
229
}
 
230
 
 
231
QgsComposer::~QgsComposer()
 
232
{
 
233
  deleteItems();
 
234
}
 
235
 
 
236
void QgsComposer::setupTheme()
 
237
{
 
238
  //now set all the icons - getThemeIcon will fall back to default theme if its
 
239
  //missing from active theme
 
240
  mActionQuit->setIcon( QgisApp::getThemeIcon( "/mActionFileExit.png" ) );
 
241
  mActionLoadFromTemplate->setIcon( QgisApp::getThemeIcon( "/mActionFileOpen.png" ) );
 
242
  mActionSaveAsTemplate->setIcon( QgisApp::getThemeIcon( "/mActionFileSaveAs.png" ) );
 
243
  mActionExportAsImage->setIcon( QgisApp::getThemeIcon( "/mActionSaveMapAsImage.png" ) );
 
244
  mActionExportAsSVG->setIcon( QgisApp::getThemeIcon( "/mActionSaveAsSVG.png" ) );
 
245
  mActionExportAsPDF->setIcon( QgisApp::getThemeIcon( "/mActionSaveAsPDF.png" ) );
 
246
  mActionPrint->setIcon( QgisApp::getThemeIcon( "/mActionFilePrint.png" ) );
 
247
  mActionZoomAll->setIcon( QgisApp::getThemeIcon( "/mActionZoomFullExtent.png" ) );
 
248
  mActionZoomIn->setIcon( QgisApp::getThemeIcon( "/mActionZoomIn.png" ) );
 
249
  mActionZoomOut->setIcon( QgisApp::getThemeIcon( "/mActionZoomOut.png" ) );
 
250
  mActionRefreshView->setIcon( QgisApp::getThemeIcon( "/mActionDraw.png" ) );
 
251
  mActionAddImage->setIcon( QgisApp::getThemeIcon( "/mActionAddImage.png" ) );
 
252
  mActionAddNewMap->setIcon( QgisApp::getThemeIcon( "/mActionAddMap.png" ) );
 
253
  mActionAddNewLabel->setIcon( QgisApp::getThemeIcon( "/mActionLabel.png" ) );
 
254
  mActionAddNewLegend->setIcon( QgisApp::getThemeIcon( "/mActionAddLegend.png" ) );
 
255
  mActionAddNewScalebar->setIcon( QgisApp::getThemeIcon( "/mActionScaleBar.png" ) );
 
256
  mActionAddBasicShape->setIcon( QgisApp::getThemeIcon( "/mActionAddBasicShape.png" ) );
 
257
  mActionAddArrow->setIcon( QgisApp::getThemeIcon( "/mActionAddArrow.png" ) );
 
258
  mActionSelectMoveItem->setIcon( QgisApp::getThemeIcon( "/mActionSelectPan.png" ) );
 
259
  mActionMoveItemContent->setIcon( QgisApp::getThemeIcon( "/mActionMoveItemContent.png" ) );
 
260
  mActionGroupItems->setIcon( QgisApp::getThemeIcon( "/mActionGroupItems.png" ) );
 
261
  mActionUngroupItems->setIcon( QgisApp::getThemeIcon( "/mActionUngroupItems.png" ) );
 
262
  mActionRaiseItems->setIcon( QgisApp::getThemeIcon( "/mActionRaiseItems.png" ) );
 
263
  mActionLowerItems->setIcon( QgisApp::getThemeIcon( "/mActionLowerItems.png" ) );
 
264
  mActionMoveItemsToTop->setIcon( QgisApp::getThemeIcon( "/mActionMoveItemsToTop.png" ) );
 
265
  mActionMoveItemsToBottom->setIcon( QgisApp::getThemeIcon( "/mActionMoveItemsToBottom.png" ) );
 
266
  mActionAlignLeft->setIcon( QgisApp::getThemeIcon( "/mActionAlignLeft.png" ) );
 
267
  mActionAlignHCenter->setIcon( QgisApp::getThemeIcon( "/mActionAlignHCenter.png" ) );
 
268
  mActionAlignRight->setIcon( QgisApp::getThemeIcon( "/mActionAlignRight.png" ) );
 
269
  mActionAlignTop->setIcon( QgisApp::getThemeIcon( "/mActionAlignTop.png" ) );
 
270
  mActionAlignVCenter->setIcon( QgisApp::getThemeIcon( "/mActionAlignVCenter.png" ) );
 
271
  mActionAlignBottom->setIcon( QgisApp::getThemeIcon( "/mActionAlignBottom.png" ) );
 
272
}
 
273
 
 
274
void QgsComposer::connectSlots()
 
275
{
 
276
  connect( mView, SIGNAL( selectedItemChanged( const QgsComposerItem* ) ), this, SLOT( showItemOptions( const QgsComposerItem* ) ) );
 
277
  connect( mView, SIGNAL( composerLabelAdded( QgsComposerLabel* ) ), this, SLOT( addComposerLabel( QgsComposerLabel* ) ) );
 
278
  connect( mView, SIGNAL( composerMapAdded( QgsComposerMap* ) ), this, SLOT( addComposerMap( QgsComposerMap* ) ) );
 
279
  connect( mView, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( deleteItem( QgsComposerItem* ) ) );
 
280
  connect( mView, SIGNAL( composerScaleBarAdded( QgsComposerScaleBar* ) ), this, SLOT( addComposerScaleBar( QgsComposerScaleBar* ) ) );
 
281
  connect( mView, SIGNAL( composerLegendAdded( QgsComposerLegend* ) ), this, SLOT( addComposerLegend( QgsComposerLegend* ) ) );
 
282
  connect( mView, SIGNAL( composerPictureAdded( QgsComposerPicture* ) ), this, SLOT( addComposerPicture( QgsComposerPicture* ) ) );
 
283
  connect( mView, SIGNAL( composerShapeAdded( QgsComposerShape* ) ), this, SLOT( addComposerShape( QgsComposerShape* ) ) );
 
284
  connect( mView, SIGNAL( composerArrowAdded( QgsComposerArrow* ) ), this, SLOT( addComposerArrow( QgsComposerArrow* ) ) );
 
285
  connect( mView, SIGNAL( actionFinished() ), this, SLOT( setSelectionTool() ) );
 
286
}
 
287
 
 
288
void QgsComposer::open( void )
 
289
{
 
290
  if ( mFirstTime )
 
291
  {
 
292
    //mComposition->createDefault();
 
293
    mFirstTime = false;
 
294
    show();
 
295
    zoomFull(); // zoomFull() does not work properly until we have called show()
 
296
  }
 
297
 
 
298
  else
 
299
  {
 
300
    show(); //make sure the window is displayed - with a saved project, it's possible to not have already called show()
 
301
    //is that a bug?
 
302
    activate(); //bring the composer window to the front
 
303
  }
 
304
}
 
305
 
 
306
void QgsComposer::activate()
 
307
{
 
308
  show();
 
309
  raise();
 
310
  setWindowState( windowState() & ~Qt::WindowMinimized );
 
311
  activateWindow();
 
312
}
 
313
 
 
314
#ifdef Q_WS_MAC
 
315
void QgsComposer::changeEvent( QEvent* event )
 
316
{
 
317
  QMainWindow::changeEvent( event );
 
318
  switch ( event->type() )
 
319
  {
 
320
    case QEvent::ActivationChange:
 
321
      if ( QApplication::activeWindow() == this )
 
322
      {
 
323
        mWindowAction->setChecked( true );
 
324
      }
 
325
      break;
 
326
 
 
327
    default:
 
328
      break;
 
329
  }
 
330
}
 
331
 
 
332
void QgsComposer::showEvent( QShowEvent *event )
 
333
{
 
334
  QMainWindow::showEvent( event );
 
335
  // add to menu if (re)opening window (event not due to unminimize)
 
336
  if ( !event->spontaneous() )
 
337
  {
 
338
    QgisApp::instance()->addWindow( mWindowAction );
 
339
  }
 
340
}
 
341
#endif
 
342
 
 
343
void QgsComposer::setTitle( const QString& title )
 
344
{
 
345
  mTitle = title;
 
346
  setWindowTitle( mTitle );
 
347
  if ( mWindowAction )
 
348
  {
 
349
    mWindowAction->setText( title );
 
350
  }
 
351
}
 
352
 
 
353
void QgsComposer::showCompositionOptions( QWidget *w )
 
354
{
 
355
  QWidget* currentWidget = mItemStackedWidget->currentWidget();
 
356
  mItemStackedWidget->removeWidget( currentWidget );
 
357
  mItemStackedWidget->addWidget( w );
 
358
}
 
359
 
 
360
void QgsComposer::showItemOptions( const QgsComposerItem* item )
 
361
{
 
362
  QWidget* currentWidget = mItemStackedWidget->currentWidget();
 
363
 
 
364
  if ( !item )
 
365
  {
 
366
    mItemStackedWidget->removeWidget( currentWidget );
 
367
    mItemStackedWidget->setCurrentWidget( 0 );
 
368
    return;
 
369
  }
 
370
 
 
371
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.find( const_cast<QgsComposerItem*>( item ) );
 
372
  if ( it == mItemWidgetMap.constEnd() )
 
373
  {
 
374
    return;
 
375
  }
 
376
 
 
377
  QWidget* newWidget = it.value();
 
378
 
 
379
  if ( !newWidget || newWidget == currentWidget ) //bail out if new widget does not exist or is already there
 
380
  {
 
381
    return;
 
382
  }
 
383
 
 
384
  mItemStackedWidget->removeWidget( currentWidget );
 
385
  mItemStackedWidget->addWidget( newWidget );
 
386
  mItemStackedWidget->setCurrentWidget( newWidget );
 
387
  //newWidget->show();
 
388
}
 
389
 
 
390
QgsMapCanvas *QgsComposer::mapCanvas( void )
 
391
{
 
392
  return mQgis->mapCanvas();
 
393
}
 
394
 
 
395
QgsComposerView *QgsComposer::view( void )
 
396
{
 
397
  return mView;
 
398
}
 
399
 
 
400
/*QgsComposition *QgsComposer::composition(void)
 
401
{
 
402
  return mComposition;
 
403
  }*/
 
404
 
 
405
void QgsComposer::zoomFull( void )
 
406
{
 
407
  if ( mView )
 
408
  {
 
409
    mView->fitInView( 0, 0, mComposition->paperWidth() + 1, mComposition->paperHeight() + 1, Qt::KeepAspectRatio );
 
410
  }
 
411
}
 
412
 
 
413
void QgsComposer::on_mActionZoomAll_triggered()
 
414
{
 
415
  zoomFull();
 
416
  mView->update();
 
417
  emit zoomLevelChanged();
 
418
}
 
419
 
 
420
void QgsComposer::on_mActionZoomIn_triggered()
 
421
{
 
422
  mView->scale( 2, 2 );
 
423
  mView->update();
 
424
  emit zoomLevelChanged();
 
425
}
 
426
 
 
427
void QgsComposer::on_mActionZoomOut_triggered()
 
428
{
 
429
  mView->scale( .5, .5 );
 
430
  mView->update();
 
431
  emit zoomLevelChanged();
 
432
}
 
433
 
 
434
void QgsComposer::on_mActionRefreshView_triggered()
 
435
{
 
436
  if ( !mComposition )
 
437
  {
 
438
    return;
 
439
  }
 
440
 
 
441
  //refresh preview of all composer maps
 
442
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.begin();
 
443
  for ( ; it != mItemWidgetMap.end(); ++it )
 
444
  {
 
445
    QgsComposerMap* map = dynamic_cast<QgsComposerMap*>( it.key() );
 
446
    if ( map && !map->isDrawing() )
 
447
    {
 
448
      map->cache();
 
449
      map->update();
 
450
    }
 
451
  }
 
452
 
 
453
  mComposition->update();
 
454
}
 
455
 
 
456
void QgsComposer::on_mActionExportAsPDF_triggered()
 
457
{
 
458
  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 );
 
475
 
 
476
  QPrinter printer;
 
477
 
 
478
  printer.setOutputFormat( QPrinter::PdfFormat );
 
479
  printer.setOutputFileName( myOutputFileNameQString );
 
480
  printer.setPaperSize( QSizeF( mComposition->paperWidth(), mComposition->paperHeight() ), QPrinter::Millimeter );
 
481
 
 
482
  print( printer );
 
483
}
 
484
 
 
485
void QgsComposer::on_mActionPrint_triggered()
 
486
{
 
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 );
 
501
  if ( printDialog.exec() != QDialog::Accepted )
 
502
  {
 
503
    return;
 
504
  }
 
505
 
 
506
  print( printer );
 
507
}
 
508
 
 
509
void QgsComposer::print( QPrinter &printer )
 
510
{
 
511
  if ( !mComposition )
 
512
    return;
 
513
 
 
514
  if ( containsWMSLayer() )
 
515
  {
 
516
    showWMSPrintingWarning();
 
517
  }
 
518
 
 
519
  //set resolution based on composer setting
 
520
  printer.setFullPage( true );
 
521
  printer.setColorMode( QPrinter::Color );
 
522
 
 
523
  //set user-defined resolution
 
524
  printer.setResolution( mComposition->printResolution() );
 
525
 
 
526
  QPainter p( &printer );
 
527
 
 
528
  QgsComposition::PlotStyle savedPlotStyle = mComposition->plotStyle();
 
529
  mComposition->setPlotStyle( QgsComposition::Print );
 
530
 
 
531
  QApplication::setOverrideCursor( Qt::BusyCursor );
 
532
 
 
533
  if ( mComposition->printAsRaster() )
 
534
  {
 
535
    //print out via QImage, code copied from on_mActionExportAsImage_activated
 
536
    int width = ( int )( mComposition->printResolution() * mComposition->paperWidth() / 25.4 );
 
537
    int height = ( int )( mComposition-> printResolution() * mComposition->paperHeight() / 25.4 );
 
538
    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 );
 
548
  }
 
549
  else
 
550
  {
 
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
    //better in case of custom page size, but only possible with Qt>=4.4.0
 
557
    QRectF paperRectMM = printer.pageRect( QPrinter::Millimeter );
 
558
    QRectF paperRectPixel = printer.pageRect( QPrinter::DevicePixel );
 
559
    mComposition->render( &p, paperRectPixel, paperRectMM );
 
560
#endif
 
561
  }
 
562
  mComposition->setPlotStyle( savedPlotStyle );
 
563
  QApplication::restoreOverrideCursor();
 
564
}
 
565
 
 
566
void QgsComposer::on_mActionExportAsImage_triggered()
 
567
{
 
568
  if ( containsWMSLayer() )
 
569
  {
 
570
    showWMSPrintingWarning();
 
571
  }
 
572
 
 
573
  // Image size
 
574
  int width = ( int )( mComposition->printResolution() * mComposition->paperWidth() / 25.4 );
 
575
  int height = ( int )( mComposition-> printResolution() * mComposition->paperHeight() / 25.4 );
 
576
 
 
577
  int memuse = width * height * 3 / 1000000;  // pixmap + image
 
578
  QgsDebugMsg( QString( "Image %1 x %2" ).arg( width ).arg( height ) );
 
579
  QgsDebugMsg( QString( "memuse = %1" ).arg( memuse ) );
 
580
 
 
581
  if ( memuse > 200 )   // cca 4500 x 4500
 
582
  {
 
583
    int answer = QMessageBox::warning( 0, tr( "Big image" ),
 
584
                                       tr( "To create image %1 x %2 requires circa %3 MB of memory" )
 
585
                                       .arg( width ).arg( height ).arg( memuse ),
 
586
                                       QMessageBox::Ok,  QMessageBox::Abort );
 
587
 
 
588
    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 )
 
657
  {
 
658
    return;
 
659
  }
 
660
 
 
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
  QImage image( QSize( width, height ), QImage::Format_ARGB32 );
 
682
  image.setDotsPerMeterX( mComposition->printResolution() / 25.4 * 1000 );
 
683
  image.setDotsPerMeterY( mComposition->printResolution() / 25.4 * 1000 );
 
684
  image.fill( 0 );
 
685
  QPainter p( &image );
 
686
  QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
 
687
  QRectF targetArea( 0, 0, width, height );
 
688
  mComposition->render( &p, targetArea, sourceArea );
 
689
  p.end();
 
690
 
 
691
  mComposition->setPlotStyle( QgsComposition::Preview );
 
692
  image.save( myOutputFileNameQString, myFilterMap[myFilterString].toLocal8Bit().data() );
 
693
  mView->setScene( mComposition );
 
694
}
 
695
 
 
696
 
 
697
void QgsComposer::on_mActionExportAsSVG_triggered()
 
698
{
 
699
  if ( containsWMSLayer() )
 
700
  {
 
701
    showWMSPrintingWarning();
 
702
  }
 
703
 
 
704
  QString myQSettingsLabel = "/UI/displaySVGWarning";
 
705
  QSettings myQSettings;
 
706
 
 
707
  bool displaySVGWarning = myQSettings.value( myQSettingsLabel, true ).toBool();
 
708
 
 
709
  if ( displaySVGWarning )
 
710
  {
 
711
    QgsMessageViewer* m = new QgsMessageViewer( this );
 
712
    m->setWindowTitle( tr( "SVG warning" ) );
 
713
    m->setCheckBoxText( tr( "Don't show this message again" ) );
 
714
    m->setCheckBoxState( Qt::Unchecked );
 
715
    m->setCheckBoxVisible( true );
 
716
    m->setCheckBoxQSettingsLabel( myQSettingsLabel );
 
717
    m->setMessageAsHtml( tr( "<p>The SVG export function in Qgis has several "
 
718
                             "problems due to bugs and deficiencies in the " )
 
719
                         + tr( "Qt4 svg code. In particular, there are problems "
 
720
                               "with layers not being clipped to the map "
 
721
                               "bounding box.</p>" )
 
722
                         + tr( "If you require a vector-based output file from "
 
723
                               "Qgis it is suggested that you try printing "
 
724
                               "to PostScript if the SVG output is not "
 
725
                               "satisfactory."
 
726
                               "</p>" ) );
 
727
    m->exec();
 
728
  }
 
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
 
747
  mComposition->setPlotStyle( QgsComposition::Print );
 
748
 
 
749
  QSvgGenerator generator;
 
750
#if QT_VERSION >= 0x040500
 
751
  generator.setTitle( QgsProject::instance()->title() );
 
752
#endif
 
753
  generator.setFileName( myOutputFileNameQString );
 
754
  //width in pixel
 
755
  int width = ( int )( mComposition->paperWidth() * mComposition->printResolution() / 25.4 );
 
756
  //height in pixel
 
757
  int height = ( int )( mComposition->paperHeight() * mComposition->printResolution() / 25.4 );
 
758
  generator.setSize( QSize( width, height ) );
 
759
  generator.setResolution( mComposition->printResolution() ); //because the rendering is done in mm, convert the dpi
 
760
 
 
761
  QPainter p( &generator );
 
762
 
 
763
  QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
 
764
  QRectF targetArea( 0, 0, width, height );
 
765
  mComposition->render( &p, targetArea, sourceArea );
 
766
 
 
767
  p.end();
 
768
 
 
769
  mComposition->setPlotStyle( QgsComposition::Preview );
 
770
  //mView->setScene(mComposition->canvas()); //now that we're done, set the view to show the scene again
 
771
}
 
772
 
 
773
void QgsComposer::on_mActionSelectMoveItem_triggered()
 
774
{
 
775
  if ( mView )
 
776
  {
 
777
    mView->setCurrentTool( QgsComposerView::Select );
 
778
  }
 
779
}
 
780
 
 
781
void QgsComposer::on_mActionAddNewMap_triggered()
 
782
{
 
783
  if ( mView )
 
784
  {
 
785
    mView->setCurrentTool( QgsComposerView::AddMap );
 
786
  }
 
787
}
 
788
 
 
789
void QgsComposer::on_mActionAddNewLegend_triggered()
 
790
{
 
791
  if ( mView )
 
792
  {
 
793
    mView->setCurrentTool( QgsComposerView::AddLegend );
 
794
  }
 
795
}
 
796
 
 
797
void QgsComposer::on_mActionAddNewLabel_triggered()
 
798
{
 
799
  if ( mView )
 
800
  {
 
801
    mView->setCurrentTool( QgsComposerView::AddLabel );
 
802
  }
 
803
}
 
804
 
 
805
void QgsComposer::on_mActionAddNewScalebar_triggered()
 
806
{
 
807
  if ( mView )
 
808
  {
 
809
    mView->setCurrentTool( QgsComposerView::AddScalebar );
 
810
  }
 
811
}
 
812
 
 
813
void QgsComposer::on_mActionAddImage_triggered()
 
814
{
 
815
  if ( mView )
 
816
  {
 
817
    mView->setCurrentTool( QgsComposerView::AddPicture );
 
818
  }
 
819
}
 
820
 
 
821
void QgsComposer::on_mActionAddBasicShape_triggered()
 
822
{
 
823
  if ( mView )
 
824
  {
 
825
    mView->setCurrentTool( QgsComposerView::AddShape );
 
826
  }
 
827
}
 
828
 
 
829
void QgsComposer::on_mActionAddArrow_triggered()
 
830
{
 
831
  if ( mView )
 
832
  {
 
833
    mView->setCurrentTool( QgsComposerView::AddArrow );
 
834
  }
 
835
}
 
836
 
 
837
void QgsComposer::on_mActionSaveAsTemplate_triggered()
 
838
{
 
839
  //show file dialog
 
840
  QSettings settings;
 
841
  QString lastSaveDir = settings.value( "UI/lastComposerTemplateDir", "" ).toString();
 
842
  QString saveFileName = QFileDialog::getSaveFileName( 0, tr( "save template" ), lastSaveDir, "*.qpt" );
 
843
  if ( saveFileName.isEmpty() )
 
844
  {
 
845
    return;
 
846
  }
 
847
 
 
848
  QFileInfo saveFileInfo( saveFileName );
 
849
  //check if suffix has been added
 
850
  if ( saveFileInfo.suffix().isEmpty() )
 
851
  {
 
852
    QString saveFileNameWithSuffix = saveFileName.append( ".qpt" );
 
853
    saveFileInfo = QFileInfo( saveFileNameWithSuffix );
 
854
  }
 
855
  settings.setValue( "UI/LastComposerTemplateDir", saveFileInfo.absolutePath() );
 
856
 
 
857
  QFile templateFile( saveFileName );
 
858
  if ( !templateFile.open( QIODevice::WriteOnly ) )
 
859
  {
 
860
    return;
 
861
  }
 
862
 
 
863
  QDomDocument saveDocument;
 
864
  writeXML( saveDocument, saveDocument );
 
865
 
 
866
  if ( templateFile.write( saveDocument.toByteArray() ) == -1 )
 
867
  {
 
868
    QMessageBox::warning( 0, tr( "Save error" ), tr( "Error, could not save file" ) );
 
869
  }
 
870
}
 
871
 
 
872
void QgsComposer::on_mActionLoadFromTemplate_triggered()
 
873
{
 
874
  QSettings settings;
 
875
  QString openFileDir = settings.value( "UI/lastComposerTemplateDir", "" ).toString();
 
876
  QString openFileString = QFileDialog::getOpenFileName( 0, tr( "Load template" ), openFileDir, "*.qpt" );
 
877
 
 
878
  if ( openFileString.isEmpty() )
 
879
  {
 
880
    return; //canceled by the user
 
881
  }
 
882
 
 
883
  QFileInfo openFileInfo( openFileString );
 
884
  settings.setValue( "UI/LastComposerTemplateDir", openFileInfo.absolutePath() );
 
885
 
 
886
  QFile templateFile( openFileString );
 
887
  if ( !templateFile.open( QIODevice::ReadOnly ) )
 
888
  {
 
889
    QMessageBox::warning( 0, tr( "Read error" ), tr( "Error, could not read file" ) );
 
890
    return;
 
891
  }
 
892
 
 
893
  QDomDocument templateDocument;
 
894
  if ( !templateDocument.setContent( &templateFile, false ) )
 
895
  {
 
896
    QMessageBox::warning( 0, tr( "Read error" ), tr( "Content of template file is not valid" ) );
 
897
    return;
 
898
  }
 
899
 
 
900
  deleteItems();
 
901
  readXML( templateDocument );
 
902
 
 
903
  //clean up after template read (e.g. legend and map extent)
 
904
  cleanupAfterTemplateRead();
 
905
}
 
906
 
 
907
void QgsComposer::on_mActionMoveItemContent_triggered()
 
908
{
 
909
  if ( mView )
 
910
  {
 
911
    mView->setCurrentTool( QgsComposerView::MoveItemContent );
 
912
  }
 
913
}
 
914
 
 
915
void QgsComposer::on_mActionGroupItems_triggered()
 
916
{
 
917
  if ( mView )
 
918
  {
 
919
    mView->groupItems();
 
920
  }
 
921
}
 
922
 
 
923
void QgsComposer::on_mActionUngroupItems_triggered()
 
924
{
 
925
  if ( mView )
 
926
  {
 
927
    mView->ungroupItems();
 
928
  }
 
929
}
 
930
 
 
931
void QgsComposer::on_mActionRaiseItems_triggered()
 
932
{
 
933
  if ( mComposition )
 
934
  {
 
935
    mComposition->raiseSelectedItems();
 
936
  }
 
937
}
 
938
 
 
939
void QgsComposer::on_mActionLowerItems_triggered()
 
940
{
 
941
  if ( mComposition )
 
942
  {
 
943
    mComposition->lowerSelectedItems();
 
944
  }
 
945
}
 
946
 
 
947
void QgsComposer::on_mActionMoveItemsToTop_triggered()
 
948
{
 
949
  if ( mComposition )
 
950
  {
 
951
    mComposition->moveSelectedItemsToTop();
 
952
  }
 
953
}
 
954
 
 
955
void QgsComposer::on_mActionMoveItemsToBottom_triggered()
 
956
{
 
957
  if ( mComposition )
 
958
  {
 
959
    mComposition->moveSelectedItemsToBottom();
 
960
  }
 
961
}
 
962
 
 
963
void QgsComposer::on_mActionAlignLeft_triggered()
 
964
{
 
965
  if ( mComposition )
 
966
  {
 
967
    mComposition->alignSelectedItemsLeft();
 
968
  }
 
969
}
 
970
 
 
971
void QgsComposer::on_mActionAlignHCenter_triggered()
 
972
{
 
973
  if ( mComposition )
 
974
  {
 
975
    mComposition->alignSelectedItemsHCenter();
 
976
  }
 
977
}
 
978
 
 
979
void QgsComposer::on_mActionAlignRight_triggered()
 
980
{
 
981
  if ( mComposition )
 
982
  {
 
983
    mComposition->alignSelectedItemsRight();
 
984
  }
 
985
}
 
986
 
 
987
void QgsComposer::on_mActionAlignTop_triggered()
 
988
{
 
989
  if ( mComposition )
 
990
  {
 
991
    mComposition->alignSelectedItemsTop();
 
992
  }
 
993
}
 
994
 
 
995
void QgsComposer::on_mActionAlignVCenter_triggered()
 
996
{
 
997
  if ( mComposition )
 
998
  {
 
999
    mComposition->alignSelectedItemsVCenter();
 
1000
  }
 
1001
}
 
1002
 
 
1003
void QgsComposer::on_mActionAlignBottom_triggered()
 
1004
{
 
1005
  if ( mComposition )
 
1006
  {
 
1007
    mComposition->alignSelectedItemsBottom();
 
1008
  }
 
1009
}
 
1010
 
 
1011
void QgsComposer::moveEvent( QMoveEvent *e ) { saveWindowState(); }
 
1012
 
 
1013
void QgsComposer::resizeEvent( QResizeEvent *e )
 
1014
{
 
1015
  // Move size grip when window is resized
 
1016
  mSizeGrip->move( rect().bottomRight() - mSizeGrip->rect().bottomRight() );
 
1017
 
 
1018
  saveWindowState();
 
1019
}
 
1020
 
 
1021
void QgsComposer::saveWindowState()
 
1022
{
 
1023
  QSettings settings;
 
1024
  settings.setValue( "/Composer/geometry", saveGeometry() );
 
1025
  //settings.setValue("/Composer/splitterState", mSplitter->saveState());
 
1026
}
 
1027
 
 
1028
void QgsComposer::restoreWindowState()
 
1029
{
 
1030
  QSettings settings;
 
1031
  restoreGeometry( settings.value( "/Composer/geometry" ).toByteArray() );
 
1032
  QVariant splitterState = settings.value( "/Composer/splitterState" );
 
1033
  if ( splitterState != QVariant::QVariant() )
 
1034
  {
 
1035
    //mSplitter->restoreState(settings.value("/Composer/splitterState").toByteArray());
 
1036
  }
 
1037
  else
 
1038
  {
 
1039
    QList<int> defaultSize;
 
1040
    defaultSize << 300 << 100; // page display 300 pixels, details pane 100 pixels
 
1041
    //mSplitter->setSizes(defaultSize);
 
1042
  }
 
1043
}
 
1044
 
 
1045
void  QgsComposer::writeXML( QDomDocument& doc )
 
1046
{
 
1047
 
 
1048
  QDomNodeList nl = doc.elementsByTagName( "qgis" );
 
1049
  if ( nl.count() < 1 )
 
1050
  {
 
1051
    return;
 
1052
  }
 
1053
  QDomElement qgisElem = nl.at( 0 ).toElement();
 
1054
  if ( qgisElem.isNull() )
 
1055
  {
 
1056
    return;
 
1057
  }
 
1058
 
 
1059
  writeXML( qgisElem, doc );
 
1060
}
 
1061
 
 
1062
void QgsComposer::writeXML( QDomNode& parentNode, QDomDocument& doc )
 
1063
{
 
1064
  QDomElement composerElem = doc.createElement( "Composer" );
 
1065
  composerElem.setAttribute( "title", mTitle );
 
1066
 
 
1067
  //store if composer is open or closed
 
1068
  if ( isVisible() )
 
1069
  {
 
1070
    composerElem.setAttribute( "visible", 1 );
 
1071
  }
 
1072
  else
 
1073
  {
 
1074
    composerElem.setAttribute( "visible", 0 );
 
1075
  }
 
1076
  parentNode.appendChild( composerElem );
 
1077
 
 
1078
  //store composer items:
 
1079
  QMap<QgsComposerItem*, QWidget*>::const_iterator itemIt = mItemWidgetMap.constBegin();
 
1080
  for ( ; itemIt != mItemWidgetMap.constEnd(); ++itemIt )
 
1081
  {
 
1082
    itemIt.key()->writeXML( composerElem, doc );
 
1083
  }
 
1084
 
 
1085
  //store composer view
 
1086
 
 
1087
  //store composition
 
1088
  if ( mComposition )
 
1089
  {
 
1090
    mComposition->writeXML( composerElem, doc );
 
1091
  }
 
1092
}
 
1093
 
 
1094
void QgsComposer::readXML( const QDomDocument& doc )
 
1095
{
 
1096
  QDomNodeList composerNodeList = doc.elementsByTagName( "Composer" );
 
1097
  if ( composerNodeList.size() < 1 )
 
1098
  {
 
1099
    return;
 
1100
  }
 
1101
  readXML( composerNodeList.at( 0 ).toElement(), doc, true );
 
1102
}
 
1103
 
 
1104
void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument& doc, bool fromTemplate )
 
1105
{
 
1106
  // Set title only if reading from project file
 
1107
  if ( !fromTemplate )
 
1108
  {
 
1109
    if ( composerElem.hasAttribute( "title" ) )
 
1110
    {
 
1111
      setTitle( composerElem.attribute( "title", tr( "Composer" ) ) );
 
1112
    }
 
1113
  }
 
1114
 
 
1115
  //delete composer view and composition
 
1116
  delete mView;
 
1117
  mView = 0;
 
1118
  //delete every child of mViewFrame
 
1119
  QObjectList viewFrameChildren = mViewFrame->children();
 
1120
  QObjectList::iterator it = viewFrameChildren.begin();
 
1121
  for ( ; it != viewFrameChildren.end(); ++it )
 
1122
  {
 
1123
    delete( *it );
 
1124
  }
 
1125
  //delete composition widget
 
1126
  QgsCompositionWidget* oldCompositionWidget = qobject_cast<QgsCompositionWidget *>( mCompositionOptionsFrame->children().at( 0 ) );
 
1127
  delete oldCompositionWidget;
 
1128
  delete mCompositionOptionsLayout;
 
1129
  mCompositionOptionsLayout = 0;
 
1130
 
 
1131
  mView = new QgsComposerView( mViewFrame );
 
1132
  connectSlots();
 
1133
 
 
1134
  //read composition settings
 
1135
  mComposition = new QgsComposition( mQgis->mapCanvas()->mapRenderer() );
 
1136
  QDomNodeList compositionNodeList = composerElem.elementsByTagName( "Composition" );
 
1137
  if ( compositionNodeList.size() > 0 )
 
1138
  {
 
1139
    QDomElement compositionElem = compositionNodeList.at( 0 ).toElement();
 
1140
    mComposition->readXML( compositionElem, doc );
 
1141
  }
 
1142
 
 
1143
  QGridLayout *l = new QGridLayout( mViewFrame );
 
1144
  l->setMargin( 0 );
 
1145
  l->addWidget( mView, 0, 0 );
 
1146
 
 
1147
  //create compositionwidget
 
1148
  QgsCompositionWidget* compositionWidget = new QgsCompositionWidget( mCompositionOptionsFrame, mComposition );
 
1149
  QObject::connect( mComposition, SIGNAL( paperSizeChanged() ), compositionWidget, SLOT( displayCompositionWidthHeight() ) );
 
1150
  compositionWidget->show();
 
1151
 
 
1152
  mCompositionOptionsLayout = new QGridLayout( mCompositionOptionsFrame );
 
1153
  mCompositionOptionsLayout->setMargin( 0 );
 
1154
  mCompositionOptionsLayout->addWidget( compositionWidget );
 
1155
 
 
1156
  //read and restore all the items
 
1157
 
 
1158
  //composer labels
 
1159
  QDomNodeList composerLabelList = composerElem.elementsByTagName( "ComposerLabel" );
 
1160
  for ( int i = 0; i < composerLabelList.size(); ++i )
 
1161
  {
 
1162
    QDomElement currentComposerLabelElem = composerLabelList.at( i ).toElement();
 
1163
    QgsComposerLabel* newLabel = new QgsComposerLabel( mComposition );
 
1164
    newLabel->readXML( currentComposerLabelElem, doc );
 
1165
    addComposerLabel( newLabel );
 
1166
    mComposition->addItem( newLabel );
 
1167
    mComposition->update();
 
1168
    mComposition->clearSelection();
 
1169
    newLabel->setSelected( true );
 
1170
    showItemOptions( newLabel );
 
1171
  }
 
1172
 
 
1173
  //composer maps
 
1174
  QDomNodeList composerMapList = composerElem.elementsByTagName( "ComposerMap" );
 
1175
  for ( int i = 0; i < composerMapList.size(); ++i )
 
1176
  {
 
1177
    QDomElement currentComposerMapElem = composerMapList.at( i ).toElement();
 
1178
    QgsComposerMap* newMap = new QgsComposerMap( mComposition );
 
1179
    newMap->readXML( currentComposerMapElem, doc );
 
1180
    addComposerMap( newMap );
 
1181
    mComposition->addItem( newMap );
 
1182
    mComposition->update();
 
1183
    mComposition->clearSelection();
 
1184
    newMap->setSelected( true );
 
1185
    showItemOptions( newMap );
 
1186
  }
 
1187
 
 
1188
  //composer scalebars
 
1189
  QDomNodeList composerScaleBarList = composerElem.elementsByTagName( "ComposerScaleBar" );
 
1190
  for ( int i = 0; i < composerScaleBarList.size(); ++i )
 
1191
  {
 
1192
    QDomElement currentScaleBarElem = composerScaleBarList.at( i ).toElement();
 
1193
    QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( mComposition );
 
1194
    newScaleBar->readXML( currentScaleBarElem, doc );
 
1195
    addComposerScaleBar( newScaleBar );
 
1196
    mComposition->addItem( newScaleBar );
 
1197
    mComposition->update();
 
1198
    mComposition->clearSelection();
 
1199
    newScaleBar->setSelected( true );
 
1200
    showItemOptions( newScaleBar );
 
1201
  }
 
1202
 
 
1203
  //composer legends
 
1204
  QDomNodeList composerLegendList = composerElem.elementsByTagName( "ComposerLegend" );
 
1205
  for ( int i = 0; i < composerLegendList.size(); ++i )
 
1206
  {
 
1207
    QDomElement currentLegendElem = composerLegendList.at( i ).toElement();
 
1208
    QgsComposerLegend* newLegend = new QgsComposerLegend( mComposition );
 
1209
    newLegend->readXML( currentLegendElem, doc );
 
1210
    addComposerLegend( newLegend );
 
1211
    mComposition->addItem( newLegend );
 
1212
    mComposition->update();
 
1213
    mComposition->clearSelection();
 
1214
    newLegend->setSelected( true );
 
1215
    showItemOptions( newLegend );
 
1216
  }
 
1217
 
 
1218
  //composer pictures
 
1219
  QDomNodeList composerPictureList = composerElem.elementsByTagName( "ComposerPicture" );
 
1220
  for ( int i = 0; i < composerPictureList.size(); ++i )
 
1221
  {
 
1222
    QDomElement currentPictureElem = composerPictureList.at( i ).toElement();
 
1223
    QgsComposerPicture* newPicture = new QgsComposerPicture( mComposition );
 
1224
    newPicture->readXML( currentPictureElem, doc );
 
1225
    addComposerPicture( newPicture );
 
1226
    mComposition->addItem( newPicture );
 
1227
    mComposition->update();
 
1228
    mComposition->clearSelection();
 
1229
    newPicture->setSelected( true );
 
1230
    showItemOptions( newPicture );
 
1231
  }
 
1232
 
 
1233
  //composer shapes
 
1234
  QDomNodeList composerShapeList = composerElem.elementsByTagName( "ComposerShape" );
 
1235
  for ( int i = 0; i < composerShapeList.size(); ++i )
 
1236
  {
 
1237
    QDomElement currentShapeElem = composerShapeList.at( i ).toElement();
 
1238
    QgsComposerShape* newShape = new QgsComposerShape( mComposition );
 
1239
    newShape->readXML( currentShapeElem, doc );
 
1240
    addComposerShape( newShape );
 
1241
    mComposition->addItem( newShape );
 
1242
    mComposition->update();
 
1243
    mComposition->clearSelection();
 
1244
    newShape->setSelected( true );
 
1245
    showItemOptions( newShape );
 
1246
  }
 
1247
 
 
1248
  //composer arrows
 
1249
  QDomNodeList composerArrowList = composerElem.elementsByTagName( "ComposerArrow" );
 
1250
  for ( int i = 0; i < composerArrowList.size(); ++i )
 
1251
  {
 
1252
    QDomElement currentArrowElem = composerArrowList.at( i ).toElement();
 
1253
    QgsComposerArrow* newArrow = new QgsComposerArrow( mComposition );
 
1254
    newArrow->readXML( currentArrowElem, doc );
 
1255
    addComposerArrow( newArrow );
 
1256
    mComposition->addItem( newArrow );
 
1257
    mComposition->update();
 
1258
    mComposition->clearSelection();
 
1259
    newArrow->setSelected( true );
 
1260
    showItemOptions( newArrow );
 
1261
  }
 
1262
 
 
1263
  mComposition->sortZList();
 
1264
  mView->setComposition( mComposition );
 
1265
 
 
1266
  setSelectionTool();
 
1267
}
 
1268
 
 
1269
void QgsComposer::deleteItems()
 
1270
{
 
1271
  //delete all the items
 
1272
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.begin();
 
1273
  for ( ; it != mItemWidgetMap.end(); ++it )
 
1274
  {
 
1275
    delete it.key();
 
1276
    delete it.value();
 
1277
  }
 
1278
  mItemWidgetMap.clear();
 
1279
}
 
1280
 
 
1281
void QgsComposer::addComposerArrow( QgsComposerArrow* arrow )
 
1282
{
 
1283
  if ( !arrow )
 
1284
  {
 
1285
    return;
 
1286
  }
 
1287
 
 
1288
  QgsComposerArrowWidget* arrowWidget = new QgsComposerArrowWidget( arrow );
 
1289
  mItemWidgetMap.insert( arrow, arrowWidget );
 
1290
}
 
1291
 
 
1292
void QgsComposer::addComposerMap( QgsComposerMap* map )
 
1293
{
 
1294
  if ( !map )
 
1295
  {
 
1296
    return;
 
1297
  }
 
1298
 
 
1299
  QgsComposerMapWidget* mapWidget = new QgsComposerMapWidget( map );
 
1300
  connect( this, SIGNAL( zoomLevelChanged() ), map, SLOT( renderModeUpdateCachedImage() ) );
 
1301
  mItemWidgetMap.insert( map, mapWidget );
 
1302
}
 
1303
 
 
1304
void QgsComposer::addComposerLabel( QgsComposerLabel* label )
 
1305
{
 
1306
  if ( !label )
 
1307
  {
 
1308
    return;
 
1309
  }
 
1310
 
 
1311
  QgsComposerLabelWidget* labelWidget = new QgsComposerLabelWidget( label );
 
1312
  mItemWidgetMap.insert( label, labelWidget );
 
1313
}
 
1314
 
 
1315
void QgsComposer::addComposerScaleBar( QgsComposerScaleBar* scalebar )
 
1316
{
 
1317
  if ( !scalebar )
 
1318
  {
 
1319
    return;
 
1320
  }
 
1321
 
 
1322
  QgsComposerScaleBarWidget* sbWidget = new QgsComposerScaleBarWidget( scalebar );
 
1323
  mItemWidgetMap.insert( scalebar, sbWidget );
 
1324
}
 
1325
 
 
1326
void QgsComposer::addComposerLegend( QgsComposerLegend* legend )
 
1327
{
 
1328
  if ( !legend )
 
1329
  {
 
1330
    return;
 
1331
  }
 
1332
 
 
1333
  QgsComposerLegendWidget* lWidget = new QgsComposerLegendWidget( legend );
 
1334
  mItemWidgetMap.insert( legend, lWidget );
 
1335
}
 
1336
 
 
1337
void QgsComposer::addComposerPicture( QgsComposerPicture* picture )
 
1338
{
 
1339
  if ( !picture )
 
1340
  {
 
1341
    return;
 
1342
  }
 
1343
 
 
1344
  QgsComposerPictureWidget* pWidget = new QgsComposerPictureWidget( picture );
 
1345
  mItemWidgetMap.insert( picture, pWidget );
 
1346
}
 
1347
 
 
1348
void QgsComposer::addComposerShape( QgsComposerShape* shape )
 
1349
{
 
1350
  if ( !shape )
 
1351
  {
 
1352
    return;
 
1353
  }
 
1354
  QgsComposerShapeWidget* sWidget = new QgsComposerShapeWidget( shape );
 
1355
  mItemWidgetMap.insert( shape, sWidget );
 
1356
}
 
1357
 
 
1358
void QgsComposer::deleteItem( QgsComposerItem* item )
 
1359
{
 
1360
  QMap<QgsComposerItem*, QWidget*>::iterator it = mItemWidgetMap.find( item );
 
1361
 
 
1362
  if ( it == mItemWidgetMap.end() )
 
1363
  {
 
1364
    return;
 
1365
  }
 
1366
 
 
1367
  delete( it.key() );
 
1368
  delete( it.value() );
 
1369
  mItemWidgetMap.remove( it.key() );
 
1370
}
 
1371
 
 
1372
void QgsComposer::setSelectionTool()
 
1373
{
 
1374
  mActionSelectMoveItem->setChecked( true );
 
1375
  on_mActionSelectMoveItem_triggered();
 
1376
}
 
1377
 
 
1378
bool QgsComposer::containsWMSLayer() const
 
1379
{
 
1380
  QMap<QgsComposerItem*, QWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
 
1381
  QgsComposerItem* currentItem = 0;
 
1382
  QgsComposerMap* currentMap = 0;
 
1383
 
 
1384
  for ( ; item_it != mItemWidgetMap.constEnd(); ++item_it )
 
1385
  {
 
1386
    currentItem = item_it.key();
 
1387
    currentMap = dynamic_cast<QgsComposerMap *>( currentItem );
 
1388
    if ( currentMap )
 
1389
    {
 
1390
      if ( currentMap->containsWMSLayer() )
 
1391
      {
 
1392
        return true;
 
1393
      }
 
1394
    }
 
1395
  }
 
1396
  return false;
 
1397
}
 
1398
 
 
1399
void QgsComposer::showWMSPrintingWarning()
 
1400
{
 
1401
  QString myQSettingsLabel = "/UI/displayComposerWMSWarning";
 
1402
  QSettings myQSettings;
 
1403
 
 
1404
  bool displayWMSWarning = myQSettings.value( myQSettingsLabel, true ).toBool();
 
1405
  if ( displayWMSWarning )
 
1406
  {
 
1407
    QgsMessageViewer* m = new QgsMessageViewer( this );
 
1408
    m->setWindowTitle( tr( "Project contains WMS layers" ) );
 
1409
    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 );
 
1410
    m->setCheckBoxText( tr( "Don't show this message again" ) );
 
1411
    m->setCheckBoxState( Qt::Unchecked );
 
1412
    m->setCheckBoxVisible( true );
 
1413
    m->setCheckBoxQSettingsLabel( myQSettingsLabel );
 
1414
    m->exec();
 
1415
  }
 
1416
}
 
1417
 
 
1418
void QgsComposer::cleanupAfterTemplateRead()
 
1419
{
 
1420
  QMap<QgsComposerItem*, QWidget*>::const_iterator itemIt = mItemWidgetMap.constBegin();
 
1421
  for ( ; itemIt != mItemWidgetMap.constEnd(); ++itemIt )
 
1422
  {
 
1423
    //update all legends completely
 
1424
    QgsComposerLegend* legendItem = dynamic_cast<QgsComposerLegend *>( itemIt.key() );
 
1425
    if ( legendItem )
 
1426
    {
 
1427
      legendItem->updateLegend();
 
1428
      continue;
 
1429
    }
 
1430
 
 
1431
    //update composer map extent if it does not intersect the full extent of all layers
 
1432
    QgsComposerMap* mapItem = dynamic_cast<QgsComposerMap *>( itemIt.key() );
 
1433
    if ( mapItem )
 
1434
    {
 
1435
      //test if composer map extent intersects extent of all layers
 
1436
      bool intersects = false;
 
1437
      QgsRectangle composerMapExtent = mapItem->extent();
 
1438
      if ( mQgis )
 
1439
      {
 
1440
        QgsMapCanvas* canvas = mQgis->mapCanvas();
 
1441
        if ( canvas )
 
1442
        {
 
1443
          QgsRectangle mapCanvasExtent = mQgis->mapCanvas()->fullExtent();
 
1444
          if ( composerMapExtent.intersects( mapCanvasExtent ) )
 
1445
          {
 
1446
            intersects = true;
 
1447
          }
 
1448
        }
 
1449
      }
 
1450
 
 
1451
      //if not: apply current canvas extent
 
1452
      if ( !intersects )
 
1453
      {
 
1454
        double currentWidth = mapItem->rect().width();
 
1455
        double currentHeight = mapItem->rect().height();
 
1456
        if ( currentWidth - 0 > 0.0 ) //don't divide through zero
 
1457
        {
 
1458
          QgsRectangle canvasExtent = mapItem->mapRenderer()->extent();
 
1459
          //adapt min y of extent such that the size of the map item stays the same
 
1460
          double newCanvasExtentHeight = currentHeight / currentWidth * canvasExtent.width();
 
1461
          canvasExtent.setYMinimum( canvasExtent.yMaximum() - newCanvasExtentHeight );
 
1462
          mapItem->setNewExtent( canvasExtent );
 
1463
        }
 
1464
      }
 
1465
    }
 
1466
  }
 
1467
}
 
1468
 
 
1469