mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-10 00:05:25 -04:00
370 lines
13 KiB
C++
370 lines
13 KiB
C++
/***************************************************************************
|
|
testqgscomposermultiframe.cpp
|
|
-----------------------
|
|
begin : September 2014
|
|
copyright : (C) 2014 by Nyall Dawson
|
|
email : nyall dot dawson at gmail dot com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgscomposerhtml.h"
|
|
#include "qgscomposerframe.h"
|
|
#include "qgscomposerlabel.h"
|
|
#include "qgscomposition.h"
|
|
#include "qgsmultirenderchecker.h"
|
|
#include "qgsapplication.h"
|
|
#include "qgsproject.h"
|
|
|
|
#include <QObject>
|
|
#include "qgstest.h"
|
|
|
|
class TestQgsComposerMultiFrame : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
TestQgsComposerMultiFrame();
|
|
|
|
private slots:
|
|
void initTestCase();// will be called before the first testfunction is executed.
|
|
void cleanupTestCase();// will be called after the last testfunction was executed.
|
|
void init();// will be called before each testfunction is executed.
|
|
void cleanup();// will be called after every testfunction.
|
|
void addFrame(); //test creating new frame inherits all properties of existing frame
|
|
void frameIsEmpty(); //test if frame is empty works
|
|
void addRemovePage(); //test if page is added and removed for RepeatUntilFinished mode
|
|
void undoRedo(); //test that combinations of frame/multiframe undo/redo don't crash
|
|
void undoRedoRemovedFrame(); //test that undo doesn't crash with removed frames
|
|
|
|
private:
|
|
QgsComposition *mComposition = nullptr;
|
|
QString mReport;
|
|
};
|
|
|
|
TestQgsComposerMultiFrame::TestQgsComposerMultiFrame()
|
|
: mComposition( 0 )
|
|
{
|
|
}
|
|
|
|
void TestQgsComposerMultiFrame::initTestCase()
|
|
{
|
|
QgsApplication::init();
|
|
QgsApplication::initQgis();
|
|
|
|
mComposition = new QgsComposition( QgsProject::instance() );
|
|
mComposition->setPaperSize( 297, 210 ); //A4 landscape
|
|
|
|
mReport = QStringLiteral( "<h1>Composer MultiFrame Tests</h1>\n" );
|
|
}
|
|
|
|
void TestQgsComposerMultiFrame::cleanupTestCase()
|
|
{
|
|
delete mComposition;
|
|
|
|
QString myReportFile = QDir::tempPath() + "/qgistest.html";
|
|
QFile myFile( myReportFile );
|
|
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
|
|
{
|
|
QTextStream myQTextStream( &myFile );
|
|
myQTextStream << mReport;
|
|
myFile.close();
|
|
}
|
|
|
|
QgsApplication::exitQgis();
|
|
}
|
|
|
|
void TestQgsComposerMultiFrame::init()
|
|
{
|
|
|
|
}
|
|
|
|
void TestQgsComposerMultiFrame::cleanup()
|
|
{
|
|
|
|
}
|
|
|
|
void TestQgsComposerMultiFrame::addFrame()
|
|
{
|
|
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
|
|
QgsComposerFrame *frame1 = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
|
|
htmlItem->addFrame( frame1 );
|
|
|
|
//should not be inherited
|
|
frame1->setHidePageIfEmpty( true );
|
|
|
|
//should be inherited
|
|
frame1->setHideBackgroundIfEmpty( true );
|
|
frame1->setFrameStrokeWidth( 5.0 );
|
|
frame1->setFrameJoinStyle( Qt::RoundJoin );
|
|
frame1->setFrameEnabled( true );
|
|
frame1->setFrameStrokeColor( QColor( Qt::red ) );
|
|
frame1->setBackgroundEnabled( true );
|
|
frame1->setBackgroundColor( QColor( Qt::green ) );
|
|
frame1->setBlendMode( QPainter::CompositionMode_ColorBurn );
|
|
frame1->setItemOpacity( 0.5 );
|
|
|
|
QgsComposerFrame *frame2 = htmlItem->createNewFrame( frame1, QPointF( 50, 55 ), QSizeF( 70, 120 ) );
|
|
|
|
//check frame created in correct place
|
|
QCOMPARE( frame2->rect().height(), 120.0 );
|
|
QCOMPARE( frame2->rect().width(), 70.0 );
|
|
QCOMPARE( frame2->scenePos().x(), 50.0 );
|
|
QCOMPARE( frame2->scenePos().y(), 55.0 );
|
|
|
|
//check frame properties
|
|
QCOMPARE( frame2->frameStrokeWidth(), frame1->frameStrokeWidth() );
|
|
QCOMPARE( frame2->frameStrokeColor(), frame1->frameStrokeColor() );
|
|
QCOMPARE( frame2->frameJoinStyle(), frame1->frameJoinStyle() );
|
|
QCOMPARE( frame2->hasBackground(), frame1->hasBackground() );
|
|
QCOMPARE( frame2->backgroundColor(), frame1->backgroundColor() );
|
|
QCOMPARE( frame2->blendMode(), frame1->blendMode() );
|
|
QCOMPARE( frame2->itemOpacity(), frame1->itemOpacity() );
|
|
|
|
//check non-inherited properties
|
|
QVERIFY( !frame2->hidePageIfEmpty() );
|
|
|
|
mComposition->removeMultiFrame( htmlItem );
|
|
delete htmlItem;
|
|
}
|
|
|
|
void TestQgsComposerMultiFrame::frameIsEmpty()
|
|
{
|
|
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
|
|
QgsComposerFrame *frame1 = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
|
|
QgsComposerFrame *frame2 = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
|
|
htmlItem->addFrame( frame1 );
|
|
htmlItem->addFrame( frame2 );
|
|
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
|
|
//short content, so frame 2 should be empty
|
|
htmlItem->setHtml( QStringLiteral( "<p><i>Test manual <b>html</b></i></p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
QCOMPARE( frame1->isEmpty(), false );
|
|
QCOMPARE( frame2->isEmpty(), true );
|
|
|
|
//long content, so frame 2 should not be empty
|
|
htmlItem->setHtml( QStringLiteral( "<p style=\"height: 10000px\"><i>Test manual <b>html</b></i></p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
QCOMPARE( frame1->isEmpty(), false );
|
|
QCOMPARE( frame2->isEmpty(), false );
|
|
|
|
//..and back again..
|
|
htmlItem->setHtml( QStringLiteral( "<p><i>Test manual <b>html</b></i></p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
QCOMPARE( frame1->isEmpty(), false );
|
|
QCOMPARE( frame2->isEmpty(), true );
|
|
|
|
mComposition->removeMultiFrame( htmlItem );
|
|
delete htmlItem;
|
|
}
|
|
|
|
void TestQgsComposerMultiFrame::addRemovePage()
|
|
{
|
|
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
|
|
QgsComposerFrame *frame1 = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
|
|
htmlItem->addFrame( frame1 );
|
|
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
|
|
htmlItem->setResizeMode( QgsComposerMultiFrame::RepeatUntilFinished );
|
|
|
|
//short content, so should fit in one frame
|
|
htmlItem->setHtml( QStringLiteral( "<p><i>Test manual <b>html</b></i></p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
//should be one page
|
|
QCOMPARE( htmlItem->frameCount(), 1 );
|
|
QCOMPARE( mComposition->numPages(), 1 );
|
|
|
|
//long content, so we require 3 frames
|
|
htmlItem->setHtml( QStringLiteral( "<p style=\"height: 2000px\"><i>Test manual <b>html</b></i></p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
QCOMPARE( htmlItem->frameCount(), 3 );
|
|
QCOMPARE( mComposition->numPages(), 3 );
|
|
|
|
//..and back again..
|
|
htmlItem->setHtml( QStringLiteral( "<p><i>Test manual <b>html</b></i></p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
QCOMPARE( htmlItem->frameCount(), 1 );
|
|
QCOMPARE( mComposition->numPages(), 1 );
|
|
|
|
|
|
//get a bit more complicated - add another item to page 3
|
|
QgsComposerLabel *label1 = new QgsComposerLabel( mComposition );
|
|
mComposition->addComposerLabel( label1 );
|
|
label1->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 3 );
|
|
|
|
//long content, so we require 4 pages
|
|
htmlItem->setHtml( QStringLiteral( "<p style=\"height: 3000px\"><i>Test manual <b>html</b></i></p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
QCOMPARE( htmlItem->frameCount(), 4 );
|
|
QCOMPARE( mComposition->numPages(), 4 );
|
|
|
|
//..and back again. Since there's an item on page 3, only page 4 should be removed
|
|
htmlItem->setHtml( QStringLiteral( "<p><i>Test manual <b>html</b></i></p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
QCOMPARE( htmlItem->frameCount(), 1 );
|
|
QCOMPARE( mComposition->numPages(), 3 );
|
|
|
|
mComposition->removeMultiFrame( htmlItem );
|
|
delete htmlItem;
|
|
}
|
|
|
|
void TestQgsComposerMultiFrame::undoRedo()
|
|
{
|
|
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
|
|
QgsComposerFrame *frame1 = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
|
|
htmlItem->addFrame( frame1 );
|
|
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
|
|
htmlItem->setResizeMode( QgsComposerMultiFrame::RepeatUntilFinished );
|
|
|
|
//short content, so should fit in one frame
|
|
htmlItem->setHtml( QStringLiteral( "<p>Test content</p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
//do some combinations of undo/redo commands for both the frame and multiframe
|
|
//to try to trigger a crash
|
|
frame1->beginCommand( QStringLiteral( "move" ) );
|
|
frame1->setSceneRect( QRectF( 10, 10, 20, 20 ) );
|
|
frame1->endCommand();
|
|
frame1->beginCommand( QStringLiteral( "stroke" ), QgsComposerMergeCommand::ItemStrokeWidth );
|
|
frame1->setFrameStrokeWidth( 4.0 );
|
|
frame1->endCommand();
|
|
frame1->beginCommand( QStringLiteral( "stroke" ), QgsComposerMergeCommand::ItemStrokeWidth );
|
|
frame1->setFrameStrokeWidth( 7.0 );
|
|
frame1->endCommand();
|
|
|
|
//multiframe commands
|
|
mComposition->beginMultiFrameCommand( htmlItem, QStringLiteral( "maxbreak" ) );
|
|
htmlItem->setMaxBreakDistance( 100 );
|
|
mComposition->endMultiFrameCommand();
|
|
|
|
//another frame command
|
|
frame1->beginCommand( QStringLiteral( "bgcolor" ), QgsComposerMergeCommand::ItemOpacity );
|
|
frame1->setBackgroundColor( QColor( 255, 255, 0 ) );
|
|
frame1->endCommand();
|
|
frame1->beginCommand( QStringLiteral( "bgcolor" ), QgsComposerMergeCommand::ItemOpacity );
|
|
frame1->setBackgroundColor( QColor( 255, 0, 0 ) );
|
|
frame1->endCommand();
|
|
|
|
//undo changes
|
|
|
|
//frame bg
|
|
mComposition->undoStack()->undo();
|
|
//multiframe max break
|
|
mComposition->undoStack()->undo();
|
|
//frame stroke width
|
|
mComposition->undoStack()->undo();
|
|
//frame move
|
|
mComposition->undoStack()->undo();
|
|
|
|
//check result
|
|
QCOMPARE( htmlItem->maxBreakDistance(), 10.0 );
|
|
QCOMPARE( htmlItem->frame( 0 )->frameStrokeWidth(), 0.3 );
|
|
QCOMPARE( htmlItem->frame( 0 )->pos(), QPointF( 0, 0 ) );
|
|
QCOMPARE( htmlItem->frame( 0 )->backgroundColor(), QColor( 255, 255, 255 ) );
|
|
|
|
//now redo
|
|
|
|
//frame move
|
|
mComposition->undoStack()->redo();
|
|
//frame stroke width
|
|
mComposition->undoStack()->redo();
|
|
//multiframe max break
|
|
mComposition->undoStack()->redo();
|
|
//frame bg color
|
|
mComposition->undoStack()->redo();
|
|
|
|
//check result
|
|
QCOMPARE( htmlItem->maxBreakDistance(), 100.0 );
|
|
QCOMPARE( htmlItem->frame( 0 )->frameStrokeWidth(), 7.0 );
|
|
QCOMPARE( htmlItem->frame( 0 )->pos(), QPointF( 10, 10 ) );
|
|
QCOMPARE( htmlItem->frame( 0 )->backgroundColor(), QColor( 255, 0, 0 ) );
|
|
|
|
mComposition->removeMultiFrame( htmlItem );
|
|
delete htmlItem;
|
|
}
|
|
|
|
|
|
void TestQgsComposerMultiFrame::undoRedoRemovedFrame()
|
|
{
|
|
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
|
|
QgsComposerFrame *frame1 = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
|
|
htmlItem->addFrame( frame1 );
|
|
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
|
|
htmlItem->setResizeMode( QgsComposerMultiFrame::RepeatUntilFinished );
|
|
|
|
//long content, so should require multiple frames
|
|
htmlItem->setHtml( QStringLiteral( "<p style=\"height: 2000px\">Test content</p>" ) );
|
|
htmlItem->loadHtml();
|
|
|
|
QVERIFY( htmlItem->frameCount() > 1 );
|
|
|
|
//do a command on the first frame
|
|
htmlItem->frame( 0 )->beginCommand( QStringLiteral( "stroke" ), QgsComposerMergeCommand::ItemStrokeWidth );
|
|
htmlItem->frame( 0 )->setFrameStrokeWidth( 4.0 );
|
|
htmlItem->frame( 0 )->endCommand();
|
|
//do a command on the second frame
|
|
htmlItem->frame( 1 )->beginCommand( QStringLiteral( "stroke" ), QgsComposerMergeCommand::ItemStrokeWidth );
|
|
htmlItem->frame( 1 )->setFrameStrokeWidth( 8.0 );
|
|
htmlItem->frame( 1 )->endCommand();
|
|
|
|
//do a multiframe command which removes extra frames
|
|
mComposition->beginMultiFrameCommand( htmlItem, QStringLiteral( "source" ) );
|
|
htmlItem->setHtml( QStringLiteral( "<p style=\"height: 20px\">Test content</p>" ) );
|
|
mComposition->endMultiFrameCommand();
|
|
|
|
//wipes the second frame
|
|
htmlItem->loadHtml();
|
|
|
|
QCOMPARE( htmlItem->frameCount(), 1 );
|
|
|
|
//undo changes
|
|
|
|
//multiframe command
|
|
mComposition->undoStack()->undo();
|
|
//frame 2 command
|
|
mComposition->undoStack()->undo();
|
|
//frame 1 command
|
|
mComposition->undoStack()->undo();
|
|
|
|
//check result
|
|
QVERIFY( htmlItem->frameCount() > 1 );
|
|
QCOMPARE( htmlItem->frame( 0 )->frameStrokeWidth(), 0.3 );
|
|
QCOMPARE( htmlItem->frame( 1 )->frameStrokeWidth(), 0.3 );
|
|
|
|
//now redo
|
|
|
|
//frame 1 command
|
|
mComposition->undoStack()->redo();
|
|
//frame 2 command
|
|
mComposition->undoStack()->redo();
|
|
|
|
//check result
|
|
QVERIFY( htmlItem->frameCount() > 1 );
|
|
QCOMPARE( htmlItem->frame( 0 )->frameStrokeWidth(), 4.0 );
|
|
QCOMPARE( htmlItem->frame( 1 )->frameStrokeWidth(), 8.0 );
|
|
|
|
//multiframe command
|
|
mComposition->undoStack()->redo();
|
|
QCOMPARE( htmlItem->frameCount(), 1 );
|
|
|
|
mComposition->removeMultiFrame( htmlItem );
|
|
delete htmlItem;
|
|
}
|
|
|
|
QGSTEST_MAIN( TestQgsComposerMultiFrame )
|
|
#include "testqgscomposermultiframe.moc"
|