Share Model merge; Merge initializers; undo/redo descs (#65)

- use "shared" pointer between Model and undo/redo instances
- adds missing initializers to Merge and Text classes
- adds checkpoints for mouse resize, barcode, and image reset.
- renames the position dialog checkpoint from Move -> Position to differentiate it from a mouse move.
- adds the Undo/Redo action descriptions to the menu items.
- adds unit tests for the Merge and Model change, and for ColorNode, RawText and TextNode.
This commit is contained in:
gitlost
2019-07-20 19:41:01 +01:00
committed by Jim Evins
parent f03aa0db3d
commit 6ab3a12b92
19 changed files with 1440 additions and 20 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ namespace glabels
///
/// Constructor
///
Merge::Merge( const Merge* merge ) : mSource(merge->mSource)
Merge::Merge( const Merge* merge ) : mId(merge->mId), mSource(merge->mSource)
{
foreach ( Record* record, merge->mRecordList )
{
+1 -1
View File
@@ -45,7 +45,7 @@ namespace glabels
Text::Text( const Text* merge )
: Merge( merge ),
mDelimeter(merge->mDelimeter), mLine1HasKeys(merge->mLine1HasKeys),
mNFieldsMax(merge->mNFieldsMax)
mKeys(merge->mKeys), mNFieldsMax(merge->mNFieldsMax)
{
}
+1
View File
@@ -661,6 +661,7 @@ namespace glabels
break;
case ArrowResize:
mUndoRedoModel->checkpoint( tr("Resize") );
handleResizeMotion( xWorld, yWorld );
break;
+43 -5
View File
@@ -62,7 +62,7 @@ namespace glabels
///
/// Constructor
///
MainWindow::MainWindow() : mModel(nullptr)
MainWindow::MainWindow() : mModel(nullptr), mUndoRedoModel(nullptr)
{
setWindowIcon( Icons::Glabels() );
@@ -194,7 +194,15 @@ namespace glabels
///
MainWindow::~MainWindow()
{
// empty
if ( mUndoRedoModel )
{
delete mUndoRedoModel;
}
if ( mModel )
{
delete mModel->merge(); // Ownership of final Merge instance is ours
delete mModel;
}
}
@@ -212,7 +220,7 @@ namespace glabels
///
void MainWindow::setModel( model::Model* model )
{
mModel = model;
mModel = model; // Ownership passes to us
mUndoRedoModel = new UndoRedoModel( mModel );
mPropertiesView->setModel( mModel, mUndoRedoModel );
@@ -882,8 +890,38 @@ namespace glabels
fileExitAction->setEnabled( true );
// Edit actions
editUndoAction->setEnabled( hasModel && mUndoRedoModel->canUndo() );
editRedoAction->setEnabled( hasModel && mUndoRedoModel->canRedo() );
if ( hasModel )
{
if ( mUndoRedoModel->canUndo() )
{
editUndoAction->setEnabled( true );
/* Translators: %1 is the action description to undo. */
editUndoAction->setText( QString( tr("Undo %1") ).arg( mUndoRedoModel->undoDescription() ) );
}
else
{
editUndoAction->setEnabled( false );
editUndoAction->setText( tr("Undo") );
}
if ( mUndoRedoModel->canRedo() )
{
editRedoAction->setEnabled( true );
/* Translators: %1 is the action description to redo. */
editRedoAction->setText( QString( tr("Redo %1") ).arg( mUndoRedoModel->redoDescription() ) );
}
else
{
editRedoAction->setEnabled( false );
editRedoAction->setText( tr("Redo") );
}
}
else
{
editUndoAction->setEnabled( false );
editUndoAction->setText( tr("Undo") );
editRedoAction->setEnabled( false );
editRedoAction->setText( tr("Redo") );
}
editCutAction->setEnabled( isEditorPage && hasSelection );
editCopyAction->setEnabled( isEditorPage && hasSelection );
editPasteAction->setEnabled( isEditorPage && canPaste );
+5 -1
View File
@@ -631,7 +631,7 @@ namespace glabels
{
mBlocked = true;
mUndoRedoModel->checkpoint( tr("Move") );
mUndoRedoModel->checkpoint( tr("Position") );
model::Distance x = model::Distance(posXSpin->value(), mUnits);
model::Distance y = model::Distance(posYSpin->value(), mUnits);
@@ -744,6 +744,8 @@ namespace glabels
{
mBlocked = true;
mUndoRedoModel->checkpoint( tr("Barcode") );
barcode::Style bcStyle = barcodeStyleButton->bcStyle();
barcodeShowTextCheck->setEnabled( bcStyle.textOptional() );
@@ -778,6 +780,8 @@ namespace glabels
void ObjectEditor::onResetImageSize()
{
mUndoRedoModel->checkpoint( tr("Reset") );
mObject->setSize( mObject->naturalSize() );
}
+15 -8
View File
@@ -61,12 +61,19 @@ namespace glabels
}
Model::Model( merge::Merge* merge )
: mUntitledInstance(0), mModified(true), mRotate(false)
{
mMerge = merge; // Shared
}
///
/// Destructor.
///
Model::~Model()
{
delete mMerge;
// Final instance of mMerge to be deleted by Model owner
}
@@ -75,7 +82,13 @@ namespace glabels
///
Model* Model::save() const
{
auto* savedModel = new Model;
auto* savedModel = new Model( mMerge ); // mMerge shared between models
if ( mFileName.isEmpty() && mUntitledInstance == 0 )
{
qDebug() << "Model::save: Warning: called before mUntitledInstance has been initialized: untitled names will differ";
}
savedModel->restore( this );
return savedModel;
@@ -112,18 +125,12 @@ namespace glabels
connect( object, SIGNAL(moved()), this, SLOT(onObjectMoved()) );
}
delete mMerge;
mMerge = savedModel->mMerge->clone();
// Emit signals based on potential changes
emit changed();
emit selectionChanged();
emit modifiedChanged();
emit nameChanged();
emit sizeChanged();
emit mergeChanged();
emit mergeSourceChanged();
emit mergeSelectionChanged();
}
+1
View File
@@ -57,6 +57,7 @@ namespace glabels
/////////////////////////////////
public:
Model();
Model( merge::Merge* merge );
~Model();
+40
View File
@@ -24,4 +24,44 @@ if (Qt5Test_FOUND)
target_link_libraries (TestXmlLabel Model Qt5::Test)
add_test (NAME XmlLabel COMMAND TestXmlLabel)
#=======================================
# Test ColorNode class
#=======================================
qt5_wrap_cpp (TestColorNode_moc_sources TestColorNode.h)
add_executable (TestColorNode TestColorNode.cpp ${TestColorNode_moc_sources})
target_link_libraries (TestColorNode Model Qt5::Test)
add_test (NAME ColorNode COMMAND TestColorNode)
#=======================================
# Test Merge classes
#=======================================
qt5_wrap_cpp (TestMerge_moc_sources TestMerge.h)
add_executable (TestMerge TestMerge.cpp ${TestMerge_moc_sources})
target_link_libraries (TestMerge Model Qt5::Test)
add_test (NAME Merge COMMAND TestMerge)
#=======================================
# Test Model class
#=======================================
qt5_wrap_cpp (TestModel_moc_sources TestModel.h)
add_executable (TestModel TestModel.cpp ${TestModel_moc_sources})
target_link_libraries (TestModel Model Qt5::Test)
add_test (NAME Model COMMAND TestModel)
#=======================================
# Test RawText class
#=======================================
qt5_wrap_cpp (TestRawText_moc_sources TestRawText.h)
add_executable (TestRawText TestRawText.cpp ${TestRawText_moc_sources})
target_link_libraries (TestRawText Model Qt5::Test)
add_test (NAME RawText COMMAND TestRawText)
#=======================================
# Test TextNode class
#=======================================
qt5_wrap_cpp (TestTextNode_moc_sources TestTextNode.h)
add_executable (TestTextNode TestTextNode.cpp ${TestTextNode_moc_sources})
target_link_libraries (TestTextNode Model Qt5::Test)
add_test (NAME TextNode COMMAND TestTextNode)
endif (Qt5Test_FOUND)
+129
View File
@@ -0,0 +1,129 @@
/* TestColorNode.cpp
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TestColorNode.h"
#include "model/ColorNode.h"
#include "merge/Record.h"
#include <QtDebug>
QTEST_MAIN(TestColorNode)
using namespace glabels::model;
using namespace glabels::merge;
void TestColorNode::colorNode()
{
uint32_t rgbaBlackTransparent = 0;
uint32_t rgbaWhite = 0xFFFFFFFF;
uint32_t rgbaRed = 0xFF0000FF; // ColorNode uses RGBA. QColor set alpha to opaque 0xFF by default
uint32_t qRgbaRed = 0xFFFF0000; // QColor uses ARGB, ie alpha at top
uint32_t qRgbaGreen80 = 0x8000FF00;
QColor blackTransparent = QColor::fromRgba( rgbaBlackTransparent );
QColor white = QColor::fromRgba( rgbaWhite );
QColor red = QColor::fromRgba( qRgbaRed );
QColor green80 = QColor::fromRgba( qRgbaGreen80 );
Record record;
ColorNode colorNode;
QVERIFY( !colorNode.isField() );
QCOMPARE( colorNode.color(), blackTransparent );
QCOMPARE( colorNode.key(), QString( "" ) );
QCOMPARE( colorNode.rgba(), rgbaBlackTransparent );
QCOMPARE( colorNode.color( nullptr ), blackTransparent );
QCOMPARE( colorNode.color( &record ), blackTransparent );
colorNode.setField( true );
QVERIFY( colorNode.isField() );
colorNode.setField( false );
QVERIFY( !colorNode.isField() );
colorNode.setColor( white );
QCOMPARE( colorNode.color(), white );
QCOMPARE( colorNode.rgba(), rgbaWhite );
QCOMPARE( colorNode.color( nullptr ), white );
QCOMPARE( colorNode.color( &record ), white );
colorNode.setKey( "key1" );
QCOMPARE( colorNode.key(), QString( "key1" ) );
///
/// Constructors
///
ColorNode colorNode2( true, white, QString( "key2" ) );
QVERIFY( colorNode2.isField() );
QCOMPARE( colorNode2.key(), QString( "key2" ) );
QCOMPARE( colorNode2.color(), white );
QVERIFY( colorNode2 != colorNode );
colorNode.setField( true );
QVERIFY( colorNode2 != colorNode );
colorNode.setKey( "key2" );
QVERIFY( colorNode2 == colorNode );
ColorNode colorNode3( red );
QVERIFY( !colorNode3.isField() );
QCOMPARE( colorNode3.key(), QString( "" ) );
QCOMPARE( colorNode3.color(), red );
QCOMPARE( colorNode3.rgba(), rgbaRed );
QVERIFY( colorNode3 != colorNode );
colorNode.setField( false );
QVERIFY( colorNode3 != colorNode );
colorNode.setKey( "" );
QVERIFY( colorNode3 != colorNode );
colorNode.setColor( red );
QVERIFY( colorNode3 == colorNode );
colorNode = ColorNode( QString( "key1" ) );
QVERIFY( colorNode.isField() ); // Defaults to true if given key only
QCOMPARE( colorNode.key(), QString( "key1" ) );
QCOMPARE( colorNode.color(), blackTransparent );
QCOMPARE( colorNode.color( &record ), blackTransparent );
///
/// Record
///
record["key1"] = "white";
QCOMPARE( colorNode.color( &record ), white );
record["key1"] = "red";
QCOMPARE( colorNode.color( &record ), red );
record["key1"] = "#FF0000";
QCOMPARE( colorNode.color( &record ), red );
record["key1"] = "#FFFF0000"; // ARGB
QCOMPARE( colorNode.color( &record ), red );
record["key1"] = "#8000FF00";
QCOMPARE( colorNode.color( &record ), green80 );
colorNode.setKey( "key2" );
QCOMPARE( colorNode.color( &record ), blackTransparent );
record["key2"] = "#8000FF00";
QCOMPARE( colorNode.color( &record ), green80 );
}
+30
View File
@@ -0,0 +1,30 @@
/* TestColorNode.h
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtTest/QtTest>
class TestColorNode : public QObject
{
Q_OBJECT
private slots:
void colorNode();
};
+347
View File
@@ -0,0 +1,347 @@
/* TestMerge.cpp
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TestMerge.h"
#include "merge/Factory.h"
#include "merge/None.h"
#include "merge/TextCsv.h"
#include "merge/TextCsvKeys.h"
#include "merge/TextTsv.h"
#include "merge/TextTsvKeys.h"
#include "merge/TextColon.h"
#include "merge/TextColonKeys.h"
#include "merge/TextSemicolon.h"
#include "merge/TextSemicolonKeys.h"
#include "merge/Record.h"
#include <QtDebug>
QTEST_MAIN(TestMerge)
Q_DECLARE_METATYPE(glabels::merge::Factory::SourceType)
using namespace glabels::merge;
void TestMerge::initTestCase()
{
Factory::init();
}
void TestMerge::factory_data()
{
QTest::addColumn<QString>( "id" );
QTest::addColumn<QString>( "name" );
QTest::addColumn<Factory::SourceType>( "type" );
QTest::addColumn<int>( "index" );
int index = 0;
QTest::newRow( "None" ) << None::id() << "None" << Factory::NONE << index++;
QTest::newRow( "TextCsv" ) << TextCsv::id() << "Text: Comma Separated Values (CSV)" << Factory::FILE << index++;
QTest::newRow( "TextCsvKeys" ) << TextCsvKeys::id() << "Text: Comma Separated Values (CSV), keys on line 1" << Factory::FILE << index++;
QTest::newRow( "TextTsv" ) << TextTsv::id() << "Text: Tab Separated Values (TSV)" << Factory::FILE << index++;
QTest::newRow( "TextTsvKeys" ) << TextTsvKeys::id() << "Text: Tab Separated Values (TSV), keys on line 1" << Factory::FILE << index++;
QTest::newRow( "TextColon" ) << TextColon::id() << "Text: Colon Separated Values" << Factory::FILE << index++;
QTest::newRow( "TextColonKeys" ) << TextColonKeys::id() << "Text: Colon Separated Values, keys on line 1" << Factory::FILE << index++;
QTest::newRow( "TextSemicolon" ) << TextSemicolon::id() << "Text: Semicolon Separated Values" << Factory::FILE << index++;
QTest::newRow( "TextSemicolonKeys" ) << TextSemicolonKeys::id() << "Text: Semicolon Separated Values, keys on line 1" << Factory::FILE << index++;
}
void TestMerge::factory()
{
QFETCH( QString, id );
QFETCH( QString, name );
QFETCH( Factory::SourceType, type );
QFETCH( int, index );
QVERIFY( Factory::nameList().contains( name ) );
QString outName = Factory::idToName( id );
QCOMPARE( outName, name );
QString outId = Factory::nameToId( name );
QCOMPARE( outId, id );
Factory::SourceType outType = Factory::idToType( id );
QCOMPARE( outType, type );
outId = Factory::indexToId( index );
QCOMPARE( outId, id );
Merge* merge = Factory::createMerge( id );
QVERIFY( merge );
QCOMPARE( merge->id(), id );
Merge* cloneMerge = merge->clone();
QCOMPARE( cloneMerge->id(), merge->id() );
delete cloneMerge;
delete merge;
}
void TestMerge::factoryNotRegistered()
{
QString id( "unregistered" );
Merge* merge = Factory::createMerge( id );
QVERIFY( merge );
QVERIFY( merge->id() != id );
QCOMPARE( merge->id(), None::id() );
delete merge;
}
void TestMerge::text_data()
{
QTest::addColumn<QString>( "id" );
QTest::addColumn<bool>( "keyed" );
QTest::addColumn<char>( "delim" );
QTest::newRow( "TextCsv" ) << TextCsv::id() << false << ',';
QTest::newRow( "TextCsvKeys" ) << TextCsvKeys::id() << true << ',';
QTest::newRow( "TextTsv" ) << TextTsv::id() << false << '\t';
QTest::newRow( "TextTsvKeys" ) << TextTsvKeys::id() << true << '\t';
QTest::newRow( "TextColon" ) << TextColon::id() << false << ':';
QTest::newRow( "TextColonKeys" ) << TextColonKeys::id() << true << ':';
QTest::newRow( "TextSemicolon" ) << TextSemicolon::id() << false << ';';
QTest::newRow( "TextSemicolonKeys" ) << TextSemicolonKeys::id() << true << ';';
}
void TestMerge::text()
{
QFETCH( QString, id );
QFETCH( bool, keyed );
QFETCH( char, delim );
QTemporaryFile file;
file.open();
if ( keyed )
{
file.write( "header1" );
file.putChar( delim );
file.write( "\"header 2\"" );
file.putChar( delim );
file.write( "header3\r\n" );
}
file.write( " val11" ); // Leading spaces in SIMPLE entry
file.putChar( delim );
file.write( "\"\"\"val 12\"\"\"" ); // 2DQUOTE at beginning and end of DQUOTE entry
file.putChar( delim );
file.write( " \"val 13\"\n" ); // Leading spaces before DQUOTE entry, end line with LF only
file.write( "\" val21\"\"\"" ); // Leading spaces within DQUOTE entry, 2DQUOTE at end
file.putChar( delim );
file.write( "\"\"\"val 22\"" ); // 2DQUOTE at beginning of DQUOTE entry
file.putChar( delim );
file.write( "\r\n" ); // Last field blank
file.write( "\"\"\"\"\"\"" ); // 2 2DQUOTES alone in DQUOTE entry
file.putChar( delim );
file.write( "val \"32" ); // DQUOTE in SIMPLE entry
file.putChar( delim );
file.write( "val \"\\\"33\r\n" ); // DQUOTE backslashed-DQUOTE in SIMPLE entry
file.putChar( delim ); file.putChar( delim ); // All fields blank
file.write( "\r\n" );
file.write( "val\\n \\t \\r \\\\ \\x51" ); // Backslashed-n/-t/-r/-backslash/-x in SIMPLE entry
file.putChar( delim );
file.write( "\"val\\n \\t \\r \\\\ \\x52\"" ); // Backslashed-n/-t/-r/-backslash/-x in QUOTE entry
file.write( "\r\n" ); // No last delim
file.write( "\"val \"\"61\"" ); // 2DQUOTE in middle of DQUOTE entry
file.putChar( delim );
file.write( "\"val\"\"" ); file.putChar( delim ); file.write( "\r\n\\\"\u2019\\\\52\"" ); // 2DQUOTE delim CRLF backslashed-DQUOTE U+2019 backslashed-backslash
file.putChar( delim );
file.write( "\"val63\"" ); // End without CRLF
file.close();
Merge* merge = Factory::createMerge( id );
QCOMPARE( merge->id(), id );
merge->setSource( file.fileName() );
QCOMPARE( merge->source(), file.fileName() );
const QList<Record*>& recordList = merge->recordList();
QCOMPARE( recordList.size(), 6 );
//
// Records
//
const char* h1 = keyed ? "header1" : "1";
const char* h2 = keyed ? "header 2" : "2";
const char* h3 = keyed ? "header3" : "3";
const Record* record;
record = recordList[0];
QVERIFY( record->contains( h1 ) );
QCOMPARE( record->value( h1 ), QString( " val11" ) );
QVERIFY( record->contains( h2 ) );
QCOMPARE( record->value( h2 ), QString( "\"val 12\"" ) );
QVERIFY( record->contains( h3 ) );
QCOMPARE( record->value( h3 ), QString( " \"val 13\"" ) ); // NOTE: Treats as unquoted due to leading spaces
record = recordList[1];
QVERIFY( record->contains( h1 ) );
QCOMPARE( record->value( h1 ), QString( " val21\"" ) );
QVERIFY( record->contains( h2 ) );
QCOMPARE( record->value( h2 ), QString( "\"val 22" ) );
QVERIFY( record->contains( h3 ) );
QCOMPARE( record->value( h3 ), QString( "" ) );
record = recordList[2];
QVERIFY( record->contains( h1 ) );
QCOMPARE( record->value( h1 ), QString( "\"\"" ) );
QVERIFY( record->contains( h2 ) );
QCOMPARE( record->value( h2 ), QString( "val \"32" ) );
QVERIFY( record->contains( h3 ) );
QCOMPARE( record->value( h3 ), QString( "val \"\"33" ) );
record = recordList[3];
QVERIFY( record->contains( h1 ) );
QCOMPARE( record->value( h1 ), QString( "" ) );
QVERIFY( record->contains( h2 ) );
QCOMPARE( record->value( h2 ), QString( "" ) );
QVERIFY( record->contains( h3 ) );
QCOMPARE( record->value( h3 ), QString( "" ) );
record = recordList[4];
QVERIFY( record->contains( h1 ) );
QCOMPARE( record->value( h1 ), QString( "val\n \t r \\ x51" ) );
QVERIFY( record->contains( h2 ) );
QCOMPARE( record->value( h2 ), QString( "val\n \t r \\ x52" ) );
QVERIFY( !record->contains( h3 ) );
record = recordList[5];
QVERIFY( record->contains( h1 ) );
QCOMPARE( record->value( h1 ), QString( "val \"61" ) );
QVERIFY( record->contains( h2 ) );
QCOMPARE( record->value( h2 ), QString( "val\"" ).append( delim ).append( "\n\"\u2019\\52" ) ); // NOTE: CR missing (QIODevice::Text strips all CRs from stream)
QVERIFY( record->contains( h3 ) );
QCOMPARE( record->value( h3 ), QString( "val63" ) );
//
// Selection
//
QCOMPARE( merge->nSelectedRecords(), 6 ); // Initially all selected
merge->unselectAll();
QCOMPARE( merge->nSelectedRecords(), 0 );
record = recordList[1];
merge->select( (Record*)record );
QCOMPARE( merge->nSelectedRecords(), 1 );
QCOMPARE( merge->selectedRecords().size(), 1 );
QCOMPARE( merge->selectedRecords().first(), record ); // Pointers same
merge->unselect( (Record*)record );
QCOMPARE( merge->nSelectedRecords(), 0 );
QCOMPARE( merge->selectedRecords().size(), 0 );
merge->setSelected( 0 );
merge->setSelected( 3 );
QCOMPARE( merge->nSelectedRecords(), 2 );
QCOMPARE( merge->selectedRecords().size(), 2 );
QCOMPARE( merge->selectedRecords().first(), recordList[0] );
QCOMPARE( merge->selectedRecords().last(), recordList[3] );
merge->setSelected( 0, false );
QCOMPARE( merge->nSelectedRecords(), 1 );
QCOMPARE( merge->selectedRecords().size(), 1 );
//
// Keys
//
QStringList keys = merge->keys();
QCOMPARE( keys.size(), 3 );
QCOMPARE( keys[0], QString( h1 ) );
QCOMPARE( keys[1], QString( h2 ) );
QCOMPARE( keys[2], QString( h3 ) );
QCOMPARE( merge->primaryKey(), QString( h1 ) );
//
// Clone
//
merge->unselectAll();
merge->setSelected( 0 );
QCOMPARE( merge->nSelectedRecords(), 1 );
Merge* cloneMerge = merge->clone();
QCOMPARE( cloneMerge->id(), merge->id() );
QCOMPARE( cloneMerge->source(), merge->source() );
QCOMPARE( cloneMerge->recordList().size(), merge->recordList().size() );
QCOMPARE( *(cloneMerge->recordList()[0]), *(merge->recordList()[0]) ); // Pointers different
QCOMPARE( *(cloneMerge->recordList()[1]), *(merge->recordList()[1]) );
QCOMPARE( *(cloneMerge->recordList()[2]), *(merge->recordList()[2]) );
QCOMPARE( *(cloneMerge->recordList()[3]), *(merge->recordList()[3]) );
QCOMPARE( *(cloneMerge->recordList()[4]), *(merge->recordList()[4]) );
QCOMPARE( *(cloneMerge->recordList()[5]), *(merge->recordList()[5]) );
QCOMPARE( cloneMerge->nSelectedRecords(), merge->nSelectedRecords() );
QCOMPARE( cloneMerge->selectedRecords().size(), merge->selectedRecords().size() );
QCOMPARE( *(cloneMerge->selectedRecords()[0]), *(merge->selectedRecords()[0]) );
QCOMPARE( cloneMerge->keys(), merge->keys() );
QCOMPARE( cloneMerge->primaryKey(), merge->primaryKey() );
delete cloneMerge;
delete merge;
}
void TestMerge::none()
{
None none;
QCOMPARE( none.id(), QString( "None" ) );
None* cloneNone = none.clone();
QCOMPARE( cloneNone->id(), none.id() );
QCOMPARE( cloneNone->keys(), none.keys() );
QCOMPARE( cloneNone->primaryKey(), none.primaryKey() );
delete cloneNone;
}
void TestMerge::record()
{
Record record;
QCOMPARE( record.isSelected(), true );
record.setSelected( false );
QCOMPARE( record.isSelected(), false );
record.setSelected( true );
QCOMPARE( record.isSelected(), true );
record["key"] = "val";
QVERIFY( record.contains( "key" ) );
QCOMPARE( record["key"], QString( "val" ) );
Record* cloneRecord = record.clone();
QCOMPARE( cloneRecord->isSelected(), true );
QVERIFY( cloneRecord->contains( "key" ) );
QCOMPARE( cloneRecord->value( "key" ), QString( "val" ) );
delete cloneRecord;
record.setSelected( false );
Record record2( &record );
QCOMPARE( record2.isSelected(), false );
QVERIFY( record2.contains( "key" ) );
QCOMPARE( record2["key"], QString( "val" ) );
}
+37
View File
@@ -0,0 +1,37 @@
/* TestMerge.h
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtTest/QtTest>
class TestMerge : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void factory_data();
void factory();
void factoryNotRegistered();
void text_data();
void text();
void none();
void record();
};
+475
View File
@@ -0,0 +1,475 @@
/* TestModel.cpp
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TestModel.h"
#include "model/Model.h"
#include "model/ModelBoxObject.h"
#include "model/ModelEllipseObject.h"
#include "model/ModelLineObject.h"
#include "model/ModelTextObject.h"
#include "model/FrameRect.h"
#include "model/FrameContinuous.h"
#include "model/Region.h"
#include "model/Settings.h"
#include "merge/Factory.h"
#include "merge/Merge.h"
#include "merge/None.h"
#include "merge/TextCsv.h"
#include "merge/TextCsvKeys.h"
#include <QtDebug>
QTEST_MAIN(TestModel)
using namespace glabels::model;
using namespace glabels::merge;
void TestModel::initTestCase()
{
Factory::init();
Settings::init();
}
void TestModel::model()
{
Model model;
QVERIFY( model.isModified() );
model.clearModified();
QVERIFY( !model.isModified() );
QVERIFY( model.shortName().contains( QRegExp( "^Untitled[1-9][0-9]*$" ) ) );
model.setFileName( "dir/file1.ext" );
QCOMPARE( model.fileName(), QString( "dir/file1.ext" ) );
QCOMPARE( model.shortName(), QString( "file1" ) );
QVERIFY( !model.isModified() );
QCOMPARE( model.w(), Distance( 0 ) );
QCOMPARE( model.h(), Distance( 0 ) );
Template tmplate( "Test Brand", "part", "desc", "testPaperId", 100, 400 );
FrameRect* frame = new FrameRect( 100, 200, 5, 0, 0, "rect1" );
QVERIFY( frame->w() != frame->h() );
tmplate.addFrame( frame );
model.setTmplate( &tmplate ); // Copies
QCOMPARE( model.tmplate()->brand(), QString( "Test Brand" ) );
QCOMPARE( model.tmplate()->part(), QString( "part" ) );
QCOMPARE( model.tmplate()->description(), QString( "desc" ) );
QCOMPARE( model.tmplate()->paperId(), QString( "testPaperId" ) );
QCOMPARE( model.tmplate()->pageWidth(), Distance( 100 ) );
QCOMPARE( model.tmplate()->pageHeight(), Distance( 400 ) );
QVERIFY( model.isModified() );
QVERIFY( model.frame()->id() == frame->id() );
QCOMPARE( model.w(), Distance( 100 ) );
QCOMPARE( model.h(), Distance( 200 ) );
QCOMPARE( model.w(), frame->w() );
QCOMPARE( model.h(), frame->h() );
model.clearModified();
QVERIFY( !model.isModified() );
QVERIFY( !model.rotate() );
model.setRotate( false );
QVERIFY( !model.rotate() );
QVERIFY( !model.isModified() );
model.setRotate( true );
QVERIFY( model.rotate() );
QVERIFY( model.isModified() );
QCOMPARE( model.w(), frame->h() );
QCOMPARE( model.h(), frame->w() );
model.setRotate( false );
QVERIFY( !model.rotate() );
model.clearModified();
QVERIFY( !model.isModified() );
model.setH( 300 ); // Default does nothing
QCOMPARE( model.h(), Distance( 200 ) );
QVERIFY( model.isModified() ); // Set anyway
// Continuous frame implements setH()
Template tmplate2( "Test Brand2", "part2", "desc2", "testPaperId2", 100, 400 );
FrameContinuous* frame2 = new FrameContinuous( 100, 0, 500, 200, "continuous1" );
QCOMPARE( frame2->h(), Distance( 200 ) );
tmplate2.addFrame( frame2 );
model.setTmplate( &tmplate2 );
QVERIFY( model.frame()->id() == frame2->id() );
QCOMPARE( model.w(), Distance( 100 ) );
QCOMPARE( model.h(), Distance( 200 ) );
QCOMPARE( model.w(), frame2->w() );
QCOMPARE( model.h(), frame2->h() );
model.clearModified();
QVERIFY( !model.isModified() );
model.setH( 300 );
QCOMPARE( model.h(), Distance( 300 ) );
QVERIFY( model.isModified() );
//
// Objects
//
ColorNode black( Qt::black );
ModelObject* ellipse = new ModelEllipseObject( 1, 0, 100, 100, false, 1, black, black );
ModelObject* box = new ModelBoxObject( 1, 100, 100, 100, false, 1, black, black );
ModelObject* line = new ModelLineObject( 1, 200, 99 /*dx*/, 1 /*dy*/, 1.0, black );
ModelObject* text = new ModelTextObject( 1, 201, 100, 30, false, "", "Sans", 10, QFont::Normal, false, false, black, Qt::AlignLeft, Qt::AlignTop, QTextOption::WordWrap, 1, false );
model.clearModified();
QVERIFY( !model.isModified() );
model.addObject( ellipse );
QVERIFY( model.isModified() );
model.addObject( box );
model.addObject( line );
model.addObject( text );
QCOMPARE( model.objectList().size(), 4 );
ModelObject* line2 = new ModelLineObject( 1, 231, 100 /*dx*/, 1 /*dy*/, 1.0, black );
model.addObject( line2 );
QCOMPARE( model.objectList().size(), 5 );
model.clearModified();
QVERIFY( !model.isModified() );
model.deleteObject( line2 );
QCOMPARE( model.objectList().size(), 4 );
QVERIFY( model.isModified() );
ModelObject* object;
object = model.objectAt( 1 /*scale*/, 1, 200 );
QVERIFY( object );
QVERIFY( dynamic_cast<ModelLineObject*>(object) );
QCOMPARE( object->id(), line->id() );
object = model.objectAt( 1 /*scale*/, 100, 150 );
QVERIFY( object );
QVERIFY( dynamic_cast<ModelBoxObject*>(object) );
QCOMPARE( object->id(), box->id() );
object = model.objectAt( 1 /*scale*/, 50, 0 );
QVERIFY( object );
QVERIFY( dynamic_cast<ModelEllipseObject*>(object) );
QCOMPARE( object->id(), ellipse->id() );
object = model.objectAt( 1 /*scale*/, 1 + 3, 201 + 3 ); // Allow for text offset
QVERIFY( object );
QVERIFY( dynamic_cast<ModelTextObject*>(object) );
QCOMPARE( object->id(), text->id() );
//
// Selection
//
QVERIFY( model.isSelectionEmpty() );
QVERIFY( !model.isSelectionAtomic() );
QVERIFY( model.getSelection().isEmpty() );
QVERIFY( !model.getFirstSelectedObject() );
QVERIFY( !model.canSelectionText() );
QVERIFY( !model.canSelectionFill() );
QVERIFY( !model.canSelectionLineColor() );
QVERIFY( !model.canSelectionLineWidth() );
model.selectAll();
QVERIFY( !model.isSelectionEmpty() );
QVERIFY( !model.isSelectionAtomic() );
QVERIFY( !model.getSelection().isEmpty() );
QCOMPARE( model.getSelection().size(), 4 );
QCOMPARE( model.getSelection().first()->id(), ellipse->id() );
QCOMPARE( model.getSelection().at(1)->id(), box->id() );
QCOMPARE( model.getSelection().at(2)->id(), line->id() );
QCOMPARE( model.getSelection().at(3)->id(), text->id() );
QVERIFY( model.getFirstSelectedObject() );
QCOMPARE( model.getFirstSelectedObject()->id(), ellipse->id() );
QVERIFY( model.canSelectionText() );
QVERIFY( model.canSelectionFill() );
QVERIFY( model.canSelectionLineColor() );
QVERIFY( model.canSelectionLineWidth() );
model.unselectAll();
QVERIFY( model.isSelectionEmpty() );
QVERIFY( !model.isSelectionAtomic() );
QVERIFY( model.getSelection().isEmpty() );
QVERIFY( !model.getFirstSelectedObject() );
model.selectObject( text );
QVERIFY( !model.isSelectionEmpty() );
QVERIFY( model.isSelectionAtomic() );
QCOMPARE( model.getSelection().size(), 1 );
QCOMPARE( model.getFirstSelectedObject()->id(), text->id() );
QVERIFY( model.canSelectionText() );
QVERIFY( !model.canSelectionFill() );
QVERIFY( !model.canSelectionLineColor() );
QVERIFY( !model.canSelectionLineWidth() );
model.unselectObject( text );
QVERIFY( model.isSelectionEmpty() );
model.selectObject( line );
QVERIFY( !model.isSelectionEmpty() );
QVERIFY( model.isSelectionAtomic() );
QCOMPARE( model.getSelection().size(), 1 );
QCOMPARE( model.getFirstSelectedObject()->id(), line->id() );
QVERIFY( !model.canSelectionText() );
QVERIFY( !model.canSelectionFill() );
QVERIFY( model.canSelectionLineColor() );
QVERIFY( model.canSelectionLineWidth() );
model.unselectAll();
QVERIFY( model.isSelectionEmpty() );
double margin = 0.5; // Allow 0.5pt margin
Region region( 1 - margin, 302 - margin, 101 + margin /*x2*/, 302 + margin /*y2*/ ); // Outside all objects
model.selectRegion( region );
QVERIFY( model.getSelection().isEmpty() );
QVERIFY( model.isSelectionEmpty() );
region.setY1( 0 - margin ); // Ellipse
region.setY2( 100 + margin );
model.selectRegion( region );
QVERIFY( !model.isSelectionEmpty() );
QVERIFY( model.isSelectionAtomic() );
QCOMPARE( model.getSelection().size(), 1 );
QCOMPARE( model.getFirstSelectedObject()->id(), ellipse->id() );
QVERIFY( !model.canSelectionText() );
QVERIFY( model.canSelectionFill() );
QVERIFY( model.canSelectionLineColor() );
QVERIFY( model.canSelectionLineWidth() );
region.setY1( 200 - margin ); // Line
region.setY2( 201 + margin );
model.selectRegion( region );
QVERIFY( !model.isSelectionEmpty() );
QVERIFY( !model.isSelectionAtomic() ); // Accumulative
QCOMPARE( model.getSelection().size(), 2 );
QCOMPARE( model.getSelection().at(0)->id(), ellipse->id() );
QCOMPARE( model.getSelection().at(1)->id(), line->id() );
model.unselectObject( ellipse );
QVERIFY( !model.isSelectionEmpty() );
QVERIFY( model.isSelectionAtomic() );
QCOMPARE( model.getSelection().size(), 1 );
QCOMPARE( model.getFirstSelectedObject()->id(), line->id() );
model.unselectAll();
QVERIFY( model.isSelectionEmpty() );
// TODO: Operations on selections etc
}
void TestModel::saveRestore()
{
Model* model = new Model;
QVERIFY( model->isModified() );
model->clearModified();
QVERIFY( !model->isModified() );
//
// Set template/frame
//
Template tmplate( "Test Brand", "part", "desc", "testPaperId", 110, 410 );
FrameRect* frame = new FrameRect( 120, 220, 5, 0, 0, "rect1" );
tmplate.addFrame( frame );
model->setTmplate( &tmplate ); // Copies
QCOMPARE( model->tmplate()->brand(), QString( "Test Brand" ) );
QVERIFY( model->isModified() );
model->clearModified();
QVERIFY( !model->isModified() );
//
// Set merge
//
Merge* merge = Factory::createMerge( TextCsvKeys::id() );
QCOMPARE( merge->id(), TextCsvKeys::id() );
model->setMerge( merge );
QCOMPARE( model->merge(), merge );
QVERIFY( model->isModified() );
model->clearModified();
QVERIFY( !model->isModified() );
QTemporaryFile csv;
csv.open();
csv.write( "id,text\n1,text1\n2,text2\n3,text3\n" );
csv.close();
merge->setSource( csv.fileName() );
QCOMPARE( merge->source(), csv.fileName() );
QCOMPARE( merge->recordList().size(), 3 );
QVERIFY( model->isModified() );
model->clearModified();
QVERIFY( !model->isModified() );
//
// Add some objects
//
ColorNode black( Qt::black );
ModelObject* object1 = new ModelLineObject( 1, 1, 90, 80, 1.0, black );
model->addObject( object1 );
QVERIFY( model->isModified() );
QCOMPARE( model->objectList().size(), 1 );
QCOMPARE( model->objectList().first(), object1 );
model->clearModified();
QVERIFY( !model->isModified() );
ModelObject* object2 = new ModelTextObject( 2, 2, 70, 30, false, "", "Sans", 10, QFont::Normal, false, false, black, Qt::AlignLeft, Qt::AlignTop, QTextOption::WordWrap, 1, false );
model->addObject( object2 );
QVERIFY( model->isModified() );
QCOMPARE( model->objectList().size(), 2 );
QCOMPARE( model->objectList().last(), object2 );
QString modelShortName = model->shortName(); // If no fileName set then model expects to have have this called before being saved/restored (otherwise get differing untitled names)
//
// Test
//
Model* saved = model->save();
QVERIFY( saved->isModified() );
QCOMPARE( saved->merge(), model->merge() ); // Shared
QCOMPARE( saved->isModified(), model->isModified() );
QCOMPARE( saved->shortName(), modelShortName );
QCOMPARE( saved->shortName(), model->shortName() );
QCOMPARE( saved->fileName(), model->fileName() );
QCOMPARE( saved->rotate(), model->rotate() );
QCOMPARE( saved->objectList().size(), model->objectList().size() );
QVERIFY( saved->objectList().at(0) != object1 ); // Objects copied
QVERIFY( saved->objectList().at(1) != object2 ); // Objects copied
QCOMPARE( saved->objectList().at(0)->x0(), model->objectList().at(0)->x0() );
QCOMPARE( saved->objectList().at(0)->y0(), model->objectList().at(0)->y0() );
QCOMPARE( saved->objectList().at(1)->x0(), model->objectList().at(1)->x0() );
QCOMPARE( saved->objectList().at(1)->y0(), model->objectList().at(1)->y0() );
// Modify original
Template tmplate2( "Test Brand2", "part2", "desc2", "testPaperId2", 230, 630 );
FrameRect* frame2 = new FrameRect( 240, 340, 5, 0, 0, "rect2" );
tmplate2.addFrame( frame2 );
model->setTmplate( &tmplate2 );
QCOMPARE( model->tmplate()->brand(), QString( "Test Brand2" ) );
QCOMPARE( model->w(), Distance( 240 ) );
QCOMPARE( model->h(), Distance( 340 ) );
model->setFileName( "dir/file1.ext" );
QCOMPARE( model->shortName(), QString( "file1" ) );
model->setRotate( true );
QVERIFY( model->rotate() );
QCOMPARE( model->w(), Distance( 340 ) );
QCOMPARE( model->h(), Distance( 240 ) );
model->deleteObject( model->objectList().first() );
QCOMPARE( model->objectList().size(), 1 );
QCOMPARE( model->objectList().first(), object2 );
model->objectList().first()->setY0( model->objectList().first()->y0() + 1 );
Merge* merge2 = Factory::createMerge( TextCsv::id() );
QCOMPARE( merge2->id(), TextCsv::id() );
QTemporaryFile csv2; csv2.open(); csv2.write( "21,text21\n22,text22\n23,text23\n24,text24\n" ); csv2.close();
merge2->setSource( csv2.fileName() );
QCOMPARE( merge2->source(), csv2.fileName() );
QCOMPARE( merge2->recordList().size(), 4 );
model->setMerge( merge2 ); // Deletes original so saved->merge() now invalid
QCOMPARE( model->merge(), merge2 );
Model* modified = model->save();
QCOMPARE( modified->merge(), merge2 ); // Shared
// Verify differences
QVERIFY( model->shortName() != modelShortName );
QVERIFY( model->shortName() != saved->shortName() );
QVERIFY( model->fileName() != saved->fileName() );
QVERIFY( model->tmplate()->brand() != saved->tmplate()->brand() );
QVERIFY( model->rotate() != saved->rotate() );
QVERIFY( model->w() != saved->w() );
QVERIFY( model->h() != saved->h() );
QVERIFY( model->objectList().size() != saved->objectList().size() );
QVERIFY( model->objectList().at(0)->x0() != saved->objectList().at(0)->x0() );
QVERIFY( model->objectList().at(0)->y0() != saved->objectList().at(0)->y0() );
QCOMPARE( model->objectList().at(0)->x0(), saved->objectList().at(1)->x0() ); // Unchanged
QVERIFY( model->objectList().at(0)->y0() != saved->objectList().at(1)->y0() );
// Restore
model->restore( saved );
QCOMPARE( model->shortName(), modelShortName );
QCOMPARE( model->shortName(), saved->shortName() );
QCOMPARE( model->fileName(), saved->fileName() );
QCOMPARE( model->tmplate()->brand(), saved->tmplate()->brand() );
QCOMPARE( model->rotate(), saved->rotate() );
QCOMPARE( model->w(), saved->w() );
QCOMPARE( model->h(), saved->h() );
QCOMPARE( model->objectList().size(), saved->objectList().size() );
QCOMPARE( model->objectList().size(), 2 );
QCOMPARE( model->objectList().at(0)->x0(), saved->objectList().at(0)->x0() );
QCOMPARE( model->objectList().at(0)->y0(), saved->objectList().at(0)->y0() );
QCOMPARE( model->objectList().at(1)->x0(), saved->objectList().at(1)->x0() );
QCOMPARE( model->objectList().at(1)->y0(), saved->objectList().at(1)->y0() );
QCOMPARE( model->merge(), merge2 ); // Unchanged
QVERIFY( model->merge() != saved->merge() ); // NOTE saved->merge() now points to deleted object
// Unrestore
model->restore( modified );
QVERIFY( model->shortName() != modelShortName );
QVERIFY( model->shortName() != saved->shortName() );
QVERIFY( model->fileName() != saved->fileName() );
QVERIFY( model->tmplate()->brand() != saved->tmplate()->brand() );
QVERIFY( model->rotate() != saved->rotate() );
QVERIFY( model->w() != saved->w() );
QVERIFY( model->h() != saved->h() );
QCOMPARE( model->objectList().size(), 1 );
QVERIFY( model->objectList().size() != saved->objectList().size() );
QVERIFY( model->objectList().at(0)->x0() != saved->objectList().at(0)->x0() );
QVERIFY( model->objectList().at(0)->y0() != saved->objectList().at(0)->y0() );
QCOMPARE( model->merge(), merge2 ); // Same
QCOMPARE( model->shortName(), modified->shortName() );
QCOMPARE( model->fileName(), modified->fileName() );
QCOMPARE( model->tmplate()->brand(), modified->tmplate()->brand() );
QCOMPARE( model->rotate(), modified->rotate() );
QCOMPARE( model->w(), modified->w() );
QCOMPARE( model->h(), modified->h() );
QCOMPARE( model->objectList().size(), modified->objectList().size() );
QCOMPARE( model->objectList().at(0)->x0(), modified->objectList().at(0)->x0() );
QCOMPARE( model->objectList().at(0)->y0(), modified->objectList().at(0)->y0() );
delete model->merge(); // Final instance owned by us
delete model;
delete saved;
delete modified;
}
+32
View File
@@ -0,0 +1,32 @@
/* TestModel.h
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtTest/QtTest>
class TestModel : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void model();
void saveRestore();
};
+94
View File
@@ -0,0 +1,94 @@
/* TestRawText.cpp
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TestRawText.h"
#include "model/RawText.h"
#include "merge/Record.h"
#include <QtDebug>
QTEST_MAIN(TestRawText)
using namespace glabels::model;
using namespace glabels::merge;
void TestRawText::rawText()
{
RawText rawText;
Record record;
QVERIFY( rawText.isEmpty() );
QVERIFY( !rawText.hasPlaceHolders() );
QCOMPARE( rawText.toString(), QString( "" ) );
QCOMPARE( rawText.toStdString(), std::string( "" ) );
QCOMPARE( rawText.expand( &record ), QString( "" ) );
rawText = "text";
QVERIFY( !rawText.isEmpty() );
QVERIFY( !rawText.hasPlaceHolders() );
QCOMPARE( rawText.toString(), QString( "text" ) );
QCOMPARE( rawText.toStdString(), std::string( "text" ) );
QCOMPARE( rawText.expand( &record ), QString( "text" ) );
RawText rawText2( "text" );
QVERIFY( !rawText2.isEmpty() );
QVERIFY( !rawText2.hasPlaceHolders() );
QCOMPARE( rawText2.toString(), QString( "text" ) );
rawText = "${key1}";
QVERIFY( !rawText.isEmpty() );
QVERIFY( rawText.hasPlaceHolders() );
QCOMPARE( rawText.toString(), QString( "${key1}" ) );
QCOMPARE( rawText.toStdString(), std::string( "${key1}" ) );
QCOMPARE( rawText.expand( &record ), QString( "" ) );
///
/// Record
///
record["key1"] = "val1";
QCOMPARE( rawText.expand( &record ), QString( "val1" ) );
rawText = "${key1}${key2}";
QVERIFY( rawText.hasPlaceHolders() );
QCOMPARE( rawText.expand( &record ), QString( "val1" ) );
record["key2"] = "val2";
QCOMPARE( rawText.expand( &record ), QString( "val1val2" ) );
rawText = "${key1}text${key2}";
QVERIFY( rawText.hasPlaceHolders() );
QCOMPARE( rawText.expand( &record ), QString( "val1textval2" ) );
rawText = "text1${key1}text2${key2}text3";
QVERIFY( rawText.hasPlaceHolders() );
QCOMPARE( rawText.expand( &record ), QString( "text1val1text2val2text3" ) );
rawText = "${key1}text${key2}${key3}";
QVERIFY( rawText.hasPlaceHolders() );
QCOMPARE( rawText.expand( &record ), QString( "val1textval2" ) );
rawText = "${key2}${key3}${key1}";
QVERIFY( rawText.hasPlaceHolders() );
QCOMPARE( rawText.expand( &record ), QString( "val2val1" ) );
}
+30
View File
@@ -0,0 +1,30 @@
/* TestRawText.h
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtTest/QtTest>
class TestRawText : public QObject
{
Q_OBJECT
private slots:
void rawText();
};
+105
View File
@@ -0,0 +1,105 @@
/* TestTextNode.cpp
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TestTextNode.h"
#include "model/TextNode.h"
#include "merge/Record.h"
#include <QtDebug>
QTEST_MAIN(TestTextNode)
using namespace glabels::model;
using namespace glabels::merge;
void TestTextNode::textNode()
{
Record record;
TextNode textNode;
QVERIFY( !textNode.isField() );
QCOMPARE( textNode.data(), QString( "" ) );
QVERIFY( textNode == TextNode() );
QVERIFY( !(textNode != TextNode()) );
QCOMPARE( textNode.text( nullptr ), QString( "" ) );
QCOMPARE( textNode.text( &record ), QString( "" ) );
QVERIFY( !textNode.isEmptyField( nullptr ) );
QVERIFY( !textNode.isEmptyField( &record ) );
textNode.setField( true );
QVERIFY( textNode.isField() );
QCOMPARE( textNode.text( &record ), QString( "" ) );
QVERIFY( !textNode.isEmptyField( nullptr ) );
QVERIFY( !textNode.isEmptyField( &record ) );
textNode.setField( false );
QVERIFY( !textNode.isField() );
textNode.setData( QString( "data1" ) );
QCOMPARE( textNode.data(), QString( "data1" ) );
QCOMPARE( textNode.text( nullptr ), QString( "data1" ) );
QCOMPARE( textNode.text( &record ), QString( "data1" ) );
QVERIFY( !textNode.isEmptyField( nullptr ) );
QVERIFY( !textNode.isEmptyField( &record ) );
textNode.setField( true );
QCOMPARE( textNode.text( nullptr ), QString( "${data1}" ) );
QCOMPARE( textNode.text( &record ), QString( "" ) );
QVERIFY( !textNode.isEmptyField( nullptr ) );
QVERIFY( !textNode.isEmptyField( &record ) );
///
/// Constructors
///
TextNode textNode2( true, "data2" );
QVERIFY( textNode2.isField() );
QCOMPARE( textNode2.data(), QString( "data2" ) );
textNode.setField( false );
QVERIFY( !(textNode2 == textNode) );
QVERIFY( textNode2 != textNode );
textNode.setField( true );
QVERIFY( !(textNode2 == textNode) );
QVERIFY( textNode2 != textNode );
textNode.setData( QString( "data2" ) );
QVERIFY( textNode2 == textNode );
QVERIFY( !(textNode2 != textNode) );
///
/// Record
///
record["key1"] = "";
QCOMPARE( textNode.text( &record ), QString( "" ) );
QVERIFY( !textNode.isEmptyField( nullptr ) );
QVERIFY( !textNode.isEmptyField( &record ) );
textNode.setData( QString( "key1" ) );
QCOMPARE( textNode.text( &record ), QString( "" ) );
QVERIFY( !textNode.isEmptyField( nullptr ) );
QVERIFY( textNode.isEmptyField( &record ) );
record["key1"] = "val1";
QCOMPARE( textNode.text( &record ), QString( "val1" ) );
QVERIFY( !textNode.isEmptyField( nullptr ) );
QVERIFY( !textNode.isEmptyField( &record ) );
}
+30
View File
@@ -0,0 +1,30 @@
/* TestTextNode.h
*
* Copyright (C) 2019 Jim Evins <evins@snaught.com>
*
* This file is part of gLabels-qt.
*
* gLabels-qt 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 3 of the License, or
* (at your option) any later version.
*
* gLabels-qt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with gLabels-qt. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtTest/QtTest>
class TestTextNode : public QObject
{
Q_OBJECT
private slots:
void textNode();
};
+24 -4
View File
@@ -1209,6 +1209,10 @@
<source>Delete</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Resize</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>glabels::MainWindow</name>
@@ -1740,6 +1744,14 @@
<source>Quick Access Toolbar</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Undo %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Redo %1</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>glabels::MergeView</name>
@@ -1898,10 +1910,6 @@
<source>Set image</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Move</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Size</source>
<translation type="unfinished"></translation>
@@ -1914,6 +1922,18 @@
<source>Shadow</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Position</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Barcode</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reset</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>glabels::PrintView</name>