diff --git a/glabels/ColorNode.cpp b/glabels/ColorNode.cpp index 852f833..e25b9fc 100644 --- a/glabels/ColorNode.cpp +++ b/glabels/ColorNode.cpp @@ -20,7 +20,7 @@ #include "ColorNode.h" -#include "Merge/MergeRecord.h" +#include "Merge/Record.h" /// @@ -160,7 +160,7 @@ uint32_t ColorNode::rgba( void ) const } -QColor ColorNode::color( MergeRecord* record ) const +QColor ColorNode::color( merge::Record* record ) const { if ( mFieldFlag ) { diff --git a/glabels/ColorNode.h b/glabels/ColorNode.h index e046e7a..ae34077 100644 --- a/glabels/ColorNode.h +++ b/glabels/ColorNode.h @@ -24,8 +24,7 @@ #include #include #include - -class MergeRecord; // Forward reference +#include "Merge/Record.h" /// @@ -89,7 +88,7 @@ public: ///////////////////////////////// public: uint32_t rgba( void ) const; - QColor color( MergeRecord* record ) const; + QColor color( merge::Record* record ) const; ///////////////////////////////// diff --git a/glabels/LabelModel.cpp b/glabels/LabelModel.cpp index 03d5500..cfb3427 100644 --- a/glabels/LabelModel.cpp +++ b/glabels/LabelModel.cpp @@ -28,9 +28,7 @@ #include #include -#include "Merge/Merge.h" -#include "Merge/MergeNone.h" -#include "Merge/MergeRecord.h" +#include "Merge/None.h" #include "LabelModelObject.h" #include "LabelRegion.h" #include "XmlLabelCreator.h" @@ -48,7 +46,7 @@ namespace /// LabelModel::LabelModel() : mUntitledInstance(0), mModified(true), mTmplate(0), mRotate(false) { - mMerge = new MergeNone(); + mMerge = new merge::None(); } @@ -278,7 +276,7 @@ QString LabelModel::shortName() /// /// Get merge object /// -Merge* LabelModel::merge() const +merge::Merge* LabelModel::merge() const { return mMerge; } @@ -287,7 +285,7 @@ Merge* LabelModel::merge() const /// /// Set merge object /// -void LabelModel::setMerge( Merge* merge ) +void LabelModel::setMerge( merge::Merge* merge ) { if ( merge != mMerge ) { @@ -1399,7 +1397,7 @@ void LabelModel::paste() /// /// Draw label objects /// -void LabelModel::draw( QPainter* painter, bool inEditor, MergeRecord* record ) const +void LabelModel::draw( QPainter* painter, bool inEditor, merge::Record* record ) const { foreach ( LabelModelObject* object, mObjectList ) { diff --git a/glabels/LabelModel.h b/glabels/LabelModel.h index b91e779..661a54a 100644 --- a/glabels/LabelModel.h +++ b/glabels/LabelModel.h @@ -26,6 +26,9 @@ #include #include "libglabels/Template.h" +#include "Merge/Merge.h" +#include "Merge/Record.h" + #include "Settings.h" @@ -33,8 +36,6 @@ class LabelModelObject; class Handle; class LabelRegion; -class Merge; -class MergeRecord; class ColorNode; @@ -103,8 +104,8 @@ public: const QList& objectList() const; - Merge* merge() const; - void setMerge( Merge* merge ); + merge::Merge* merge() const; + void setMerge( merge::Merge* merge ); ///////////////////////////////// @@ -200,7 +201,7 @@ public: // Drawing operations ///////////////////////////////// public: - void draw( QPainter* painter, bool inEditor = true, MergeRecord* record = 0 ) const; + void draw( QPainter* painter, bool inEditor = true, merge::Record* record = 0 ) const; ///////////////////////////////// @@ -226,7 +227,7 @@ private: QList mObjectList; - Merge* mMerge; + merge::Merge* mMerge; }; diff --git a/glabels/LabelModelBoxObject.cpp b/glabels/LabelModelBoxObject.cpp index 3c005b8..589bffa 100644 --- a/glabels/LabelModelBoxObject.cpp +++ b/glabels/LabelModelBoxObject.cpp @@ -66,7 +66,7 @@ LabelModelBoxObject* LabelModelBoxObject::clone() const /// /// Draw shadow of object /// -void LabelModelBoxObject::drawShadow( QPainter* painter, bool inEditor, MergeRecord* record ) const +void LabelModelBoxObject::drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const { QColor lineColor = mLineColorNode.color( record ); QColor fillColor = mFillColorNode.color( record ); @@ -111,7 +111,7 @@ void LabelModelBoxObject::drawShadow( QPainter* painter, bool inEditor, MergeRec /// /// Draw object itself /// -void LabelModelBoxObject::drawObject( QPainter* painter, bool inEditor, MergeRecord* record ) const +void LabelModelBoxObject::drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const { QColor lineColor = mLineColorNode.color( record ); QColor fillColor = mFillColorNode.color( record ); diff --git a/glabels/LabelModelBoxObject.h b/glabels/LabelModelBoxObject.h index cf7c287..91f0b30 100644 --- a/glabels/LabelModelBoxObject.h +++ b/glabels/LabelModelBoxObject.h @@ -51,8 +51,8 @@ public: // Drawing operations /////////////////////////////////////////////////////////////// protected: - virtual void drawShadow( QPainter* painter, bool inEditor, MergeRecord* record ) const; - virtual void drawObject( QPainter* painter, bool inEditor, MergeRecord* record ) const; + virtual void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const; + virtual void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const; virtual QPainterPath hoverPath( double scale ) const; }; diff --git a/glabels/LabelModelObject.cpp b/glabels/LabelModelObject.cpp index 08772b7..cbb3b26 100644 --- a/glabels/LabelModelObject.cpp +++ b/glabels/LabelModelObject.cpp @@ -29,7 +29,6 @@ #include "TextNode.h" #include "BarcodeStyle.h" #include "LabelRegion.h" -#include "Merge/MergeRecord.h" /// @@ -992,7 +991,7 @@ Handle* LabelModelObject::handleAt( double scale, /// /// Draw object + shadow /// -void LabelModelObject::draw( QPainter* painter, bool inEditor, MergeRecord* record ) const +void LabelModelObject::draw( QPainter* painter, bool inEditor, merge::Record* record ) const { painter->save(); painter->translate( mX0.pt(), mY0.pt() ); diff --git a/glabels/LabelModelObject.h b/glabels/LabelModelObject.h index d7e6197..2829db2 100644 --- a/glabels/LabelModelObject.h +++ b/glabels/LabelModelObject.h @@ -27,6 +27,7 @@ #include #include "libglabels/Distance.h" +#include "Merge/Record.h" #include "ColorNode.h" #include "TextNode.h" #include "BarcodeStyle.h" @@ -36,7 +37,6 @@ // Forward References class LabelRegion; -class MergeRecord; /// @@ -338,12 +338,12 @@ public: // Drawing operations /////////////////////////////////////////////////////////////// public: - void draw( QPainter* painter, bool inEditor, MergeRecord* record ) const; + void draw( QPainter* painter, bool inEditor, merge::Record* record ) const; void drawSelectionHighlight( QPainter* painter, double scale ) const; protected: - virtual void drawShadow( QPainter* painter, bool inEditor, MergeRecord* record ) const = 0; - virtual void drawObject( QPainter* painter, bool inEditor, MergeRecord* record ) const = 0; + virtual void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const = 0; + virtual void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const = 0; virtual QPainterPath hoverPath( double scale ) const = 0; diff --git a/glabels/Merge/CMakeLists.txt b/glabels/Merge/CMakeLists.txt index 9c536e0..dbc4cee 100644 --- a/glabels/Merge/CMakeLists.txt +++ b/glabels/Merge/CMakeLists.txt @@ -10,12 +10,12 @@ project (Merge CXX) # Sources #======================================= set (merge_sources + Factory.cpp + Record.cpp Merge.cpp - MergeFactory.cpp - MergeRecord.cpp - MergeNone.cpp - MergeText.cpp - MergeTextCsv.cpp + None.cpp + Text.cpp + TextCsv.cpp ) set (merge_qobject_headers diff --git a/glabels/Merge/Factory.cpp b/glabels/Merge/Factory.cpp new file mode 100644 index 0000000..a27a55e --- /dev/null +++ b/glabels/Merge/Factory.cpp @@ -0,0 +1,180 @@ +/* Merge/Factory.cpp + * + * Copyright (C) 2016 Jim Evins + * + * 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 . + */ + +#include "Factory.h" + +#include "None.h" +#include "TextCsv.h" + + +namespace merge +{ + + /// + /// Static data + /// + QMap Factory::mBackendIdMap; + QMap Factory::mBackendNameMap; + + + /// + /// Constructor + /// + Factory::Factory() + { + registerBackend( None::id(), + tr("None"), + NONE, + &None::create ); + + registerBackend( TextCsv::id(), + tr("Text: Comma Separated Values (CSV)"), + FILE, + &TextCsv::create ); + } + + + /// + /// Initialize + /// + void Factory::init() + { + static Factory* singletonInstance = 0; + if ( !singletonInstance ) + { + singletonInstance = new Factory(); + } + } + + + /// + /// Create Merge object + /// + Merge* Factory::createMerge( const QString& id ) + { + QMap::iterator iBackend = mBackendIdMap.find( id ); + if ( iBackend != mBackendIdMap.end() ) + { + return iBackend->create(); + } + + return None::create(); + } + + + /// + /// Get name list + /// + QStringList Factory::nameList() + { + QStringList list; + + foreach ( BackendEntry backend, mBackendIdMap ) + { + list << backend.name; + } + + return list; + } + + + /// + /// Convert ID to name + /// + QString Factory::idToName( const QString& id ) + { + if ( mBackendIdMap.contains( id ) ) + { + return mBackendIdMap[id].name; + } + else + { + return tr("None"); + } + } + + + /// + /// Convert name to ID + /// + QString Factory::nameToId( const QString& name ) + { + if ( mBackendNameMap.contains( name ) ) + { + return mBackendNameMap[name].id; + } + else + { + return "None"; + } + } + + + /// + /// Convert ID to type + /// + Factory::SourceType Factory::idToType( const QString& id ) + { + if ( mBackendIdMap.contains( id ) ) + { + return mBackendIdMap[id].type; + } + else + { + return NONE; + } + } + + + /// + /// Lookup ID from index + /// + QString Factory::indexToId( int index ) + { + QList ids = mBackendIdMap.keys(); + + if ( (index > 0) && (index < ids.size()) ) + { + return ids[index]; + } + + return "None"; + } + + + /// + /// Register backend + /// + void Factory::registerBackend( const QString& id, + const QString& name, + SourceType type, + CreateFct create ) + { + BackendEntry backend; + + backend.name = name; + backend.type = type; + backend.create = create; + + mBackendIdMap[ id ] = backend; + } + +} + diff --git a/glabels/Merge/Factory.h b/glabels/Merge/Factory.h new file mode 100644 index 0000000..be84869 --- /dev/null +++ b/glabels/Merge/Factory.h @@ -0,0 +1,102 @@ +/* Merge/Factory.h + * + * Copyright (C) 2016 Jim Evins + * + * 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 . + */ + +#ifndef merge_Factory_h +#define merge_Factory_h + +#include +#include +#include + + +namespace merge +{ + class Merge; // Forward reference + + + /// + /// Factory + /// + class Factory + { + Q_DECLARE_TR_FUNCTIONS(Factory) + + + ///////////////////////////////// + // Source Type + ///////////////////////////////// + public: + enum SourceType { NONE, FIXED, FILE }; + + + ///////////////////////////////// + // Life Cycle + ///////////////////////////////// + protected: + Factory(); + + + ///////////////////////////////// + // Static methods + ///////////////////////////////// + public: + static void init(); + + static Merge* createMerge( const QString& id ); + + static QStringList nameList(); + static QString idToName( const QString& id ); + static QString nameToId( const QString& name ); + static SourceType idToType( const QString& id ); + static QString indexToId( int index ); + + + ///////////////////////////////// + // private methods + ///////////////////////////////// + private: + typedef Merge* (*CreateFct)(); + + static void registerBackend( const QString& id, + const QString& name, + SourceType type, + CreateFct create ); + + + ///////////////////////////////// + // private data + ///////////////////////////////// + class BackendEntry + { + public: + QString id; + QString name; + SourceType type; + CreateFct create; + }; + + static QMap mBackendIdMap; + static QMap mBackendNameMap; + + }; + +} + +#endif // merge_Factory_h diff --git a/glabels/Merge/Merge.cpp b/glabels/Merge/Merge.cpp index 41fc00e..05366dd 100644 --- a/glabels/Merge/Merge.cpp +++ b/glabels/Merge/Merge.cpp @@ -1,4 +1,4 @@ -/* Merge.cpp +/* Merge/Merge.cpp * * Copyright (C) 2015-2016 Jim Evins * @@ -20,184 +20,191 @@ #include "Merge.h" +#include "Record.h" -/// -/// Constructor -/// -Merge::Merge() + +namespace merge { -} - -/// -/// Constructor -/// -Merge::Merge( const Merge* merge ) : mSource(merge->mSource) -{ - foreach ( MergeRecord* record, merge->mRecordList ) + /// + /// Constructor + /// + Merge::Merge() { - mRecordList << record->clone(); } -} -/// -/// Destructor -/// -Merge::~Merge() -{ - foreach ( MergeRecord* record, mRecordList ) + /// + /// Constructor + /// + Merge::Merge( const Merge* merge ) : mSource(merge->mSource) { - delete record; + foreach ( Record* record, merge->mRecordList ) + { + mRecordList << record->clone(); + } } - mRecordList.clear(); -} -/// -/// Get id -/// -QString Merge::id() const -{ - return mId; -} - - -/// -/// Get source -/// -QString Merge::source() const -{ - return mSource; -} - - -/// -/// Set source -/// -void Merge::setSource( const QString& source ) -{ - mSource = source; - - // Clear out any old records - foreach ( MergeRecord* record, mRecordList ) + /// + /// Destructor + /// + Merge::~Merge() { - delete record; + foreach ( Record* record, mRecordList ) + { + delete record; + } + mRecordList.clear(); } - mRecordList.clear(); - open(); - for ( MergeRecord* record = readNextRecord(); record != 0; record = readNextRecord() ) + + /// + /// Get id + /// + QString Merge::id() const { - mRecordList.append( record ); + return mId; } - close(); + + + /// + /// Get source + /// + QString Merge::source() const + { + return mSource; + } + + + /// + /// Set source + /// + void Merge::setSource( const QString& source ) + { + mSource = source; + + // Clear out any old records + foreach ( Record* record, mRecordList ) + { + delete record; + } + mRecordList.clear(); + + open(); + for ( Record* record = readNextRecord(); record != 0; record = readNextRecord() ) + { + mRecordList.append( record ); + } + close(); - emit sourceChanged(); -} - - -/// -/// Get record list -/// -const QList& Merge::recordList( void ) const -{ - return mRecordList; -} - - -/// -/// Select matching record -/// -void Merge::select( MergeRecord* record ) -{ - record->setSelected( true ); - emit selectionChanged(); -} - - -/// -/// Unselect matching record -/// -void Merge::unselect( MergeRecord* record ) -{ - record->setSelected( false ); - emit selectionChanged(); -} - - -/// -/// Select/unselect i'th record -/// -void Merge::setSelected( int i, bool state ) -{ - if ( (i >= 0) && (i < mRecordList.size()) ) - { - mRecordList[i]->setSelected( state ); - emit selectionChanged(); + emit sourceChanged(); } -} -/// -/// Select all records -/// -void Merge::selectAll() -{ - foreach ( MergeRecord* record, mRecordList ) + /// + /// Get record list + /// + const QList& Merge::recordList( void ) const + { + return mRecordList; + } + + + /// + /// Select matching record + /// + void Merge::select( Record* record ) { record->setSelected( true ); + emit selectionChanged(); } - emit selectionChanged(); -} - -/// -/// Unselect all records -/// -void Merge::unselectAll() -{ - foreach ( MergeRecord* record, mRecordList ) + + /// + /// Unselect matching record + /// + void Merge::unselect( Record* record ) { record->setSelected( false ); + emit selectionChanged(); } - emit selectionChanged(); -} -/// -/// Return count of selected records -/// -int Merge::nSelectedRecords() const -{ - int count = 0; - - foreach ( MergeRecord* record, mRecordList ) + /// + /// Select/unselect i'th record + /// + void Merge::setSelected( int i, bool state ) { - if ( record->isSelected() ) + if ( (i >= 0) && (i < mRecordList.size()) ) { - count++; + mRecordList[i]->setSelected( state ); + emit selectionChanged(); } } - return count; -} - -/// -/// Return list of selected records -/// -const QList Merge::selectedRecords() const -{ - QList list; - - foreach ( MergeRecord* record, mRecordList ) + /// + /// Select all records + /// + void Merge::selectAll() { - if ( record->isSelected() ) + foreach ( Record* record, mRecordList ) { - list.append( record ); + record->setSelected( true ); } + emit selectionChanged(); + } + + + /// + /// Unselect all records + /// + void Merge::unselectAll() + { + foreach ( Record* record, mRecordList ) + { + record->setSelected( false ); + } + emit selectionChanged(); + } + + + /// + /// Return count of selected records + /// + int Merge::nSelectedRecords() const + { + int count = 0; + + foreach ( Record* record, mRecordList ) + { + if ( record->isSelected() ) + { + count++; + } + } + + return count; + } + + + /// + /// Return list of selected records + /// + const QList Merge::selectedRecords() const + { + QList list; + + foreach ( Record* record, mRecordList ) + { + if ( record->isSelected() ) + { + list.append( record ); + } + } + + return list; } - return list; } diff --git a/glabels/Merge/Merge.h b/glabels/Merge/Merge.h index f9f2cc8..345acff 100644 --- a/glabels/Merge/Merge.h +++ b/glabels/Merge/Merge.h @@ -1,4 +1,4 @@ -/* Merge.h +/* Merge/Merge.h * * Copyright (C) 2015-2016 Jim Evins * @@ -18,95 +18,99 @@ * along with gLabels-qt. If not, see . */ -#ifndef Merge_h -#define Merge_h +#ifndef merge_Merge_h +#define merge_Merge_h #include #include #include #include -#include "MergeRecord.h" - -/// -/// Merge Object -/// -struct Merge : QObject +namespace merge { - Q_OBJECT + class Record; // Forward reference - - ///////////////////////////////// - // Life Cycle - ///////////////////////////////// -protected: - Merge(); - Merge( const Merge* merge ); -public: - virtual ~Merge(); - - - ///////////////////////////////// - // Object duplication - ///////////////////////////////// - virtual Merge* clone() const = 0; - - - ///////////////////////////////// - // Properties - ///////////////////////////////// -public: - QString id() const; - QString source() const; - void setSource( const QString& source ); - - const QList& recordList( void ) const; - - - ///////////////////////////////// - // Selection methods - ///////////////////////////////// -public: - void select( MergeRecord* record ); - void unselect( MergeRecord* record ); - void setSelected( int i, bool state = true ); - void selectAll(); - void unselectAll(); - int nSelectedRecords() const; - const QList selectedRecords() const; + /// + /// Merge Object + /// + struct Merge : QObject + { + Q_OBJECT - ///////////////////////////////// - // Virtual methods - ///////////////////////////////// -public: - virtual QStringList keys() const = 0; - virtual QString primaryKey() const = 0; -protected: - virtual void open() = 0; - virtual void close() = 0; - virtual MergeRecord* readNextRecord() = 0; + ///////////////////////////////// + // Life Cycle + ///////////////////////////////// + protected: + Merge(); + Merge( const Merge* merge ); + public: + virtual ~Merge(); + + + ///////////////////////////////// + // Object duplication + ///////////////////////////////// + virtual Merge* clone() const = 0; + + + ///////////////////////////////// + // Properties + ///////////////////////////////// + public: + QString id() const; + QString source() const; + void setSource( const QString& source ); + + const QList& recordList( void ) const; + + + ///////////////////////////////// + // Selection methods + ///////////////////////////////// + public: + void select( Record* record ); + void unselect( Record* record ); + void setSelected( int i, bool state = true ); + void selectAll(); + void unselectAll(); + + int nSelectedRecords() const; + const QList selectedRecords() const; + + + ///////////////////////////////// + // Virtual methods + ///////////////////////////////// + public: + virtual QStringList keys() const = 0; + virtual QString primaryKey() const = 0; + protected: + virtual void open() = 0; + virtual void close() = 0; + virtual Record* readNextRecord() = 0; - ///////////////////////////////// - // Signals - ///////////////////////////////// -signals: - void sourceChanged(); - void selectionChanged(); + ///////////////////////////////// + // Signals + ///////////////////////////////// + signals: + void sourceChanged(); + void selectionChanged(); - ///////////////////////////////// - // Private data - ///////////////////////////////// -protected: - QString mId; -private: - QString mSource; - QList mRecordList; -}; + ///////////////////////////////// + // Private data + ///////////////////////////////// + protected: + QString mId; + private: + QString mSource; + QList mRecordList; + }; +} -#endif // Merge_h +#endif // merge_Merge_h diff --git a/glabels/Merge/MergeFactory.cpp b/glabels/Merge/MergeFactory.cpp deleted file mode 100644 index 008bd27..0000000 --- a/glabels/Merge/MergeFactory.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* MergeFactory.cpp - * - * Copyright (C) 2016 Jim Evins - * - * 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 . - */ - -#include "MergeFactory.h" - -#include "MergeNone.h" -#include "MergeTextCsv.h" - - -/// -/// Static data -/// -QMap MergeFactory::mBackendIdMap; -QMap MergeFactory::mBackendNameMap; - - -/// -/// Constructor -/// -MergeFactory::MergeFactory() -{ - registerBackend( MergeNone::id(), - tr("None"), - NONE, - &MergeNone::create ); - - registerBackend( MergeTextCsv::id(), - tr("Text: Comma Separated Values (CSV)"), - FILE, - &MergeTextCsv::create ); -} - - -/// -/// Initialize -/// -void MergeFactory::init() -{ - static MergeFactory* singletonInstance = 0; - if ( !singletonInstance ) - { - singletonInstance = new MergeFactory(); - } -} - - -/// -/// Create Merge object -/// -Merge* MergeFactory::createMerge( const QString& id ) -{ - QMap::iterator iBackend = mBackendIdMap.find( id ); - if ( iBackend != mBackendIdMap.end() ) - { - return iBackend->create(); - } - - return MergeNone::create(); -} - - -/// -/// Get name list -/// -QStringList MergeFactory::nameList() -{ - QStringList list; - - foreach ( BackendEntry backend, mBackendIdMap ) - { - list << backend.name; - } - - return list; -} - - -/// -/// Convert ID to name -/// -QString MergeFactory::idToName( const QString& id ) -{ - if ( mBackendIdMap.contains( id ) ) - { - return mBackendIdMap[id].name; - } - else - { - return tr("None"); - } -} - - -/// -/// Convert name to ID -/// -QString MergeFactory::nameToId( const QString& name ) -{ - if ( mBackendNameMap.contains( name ) ) - { - return mBackendNameMap[name].id; - } - else - { - return "None"; - } -} - - -/// -/// Convert ID to type -/// -MergeFactory::SourceType MergeFactory::idToType( const QString& id ) -{ - if ( mBackendIdMap.contains( id ) ) - { - return mBackendIdMap[id].type; - } - else - { - return NONE; - } -} - - -/// -/// Lookup ID from index -/// -QString MergeFactory::indexToId( int index ) -{ - QList ids = mBackendIdMap.keys(); - - if ( (index > 0) && (index < ids.size()) ) - { - return ids[index]; - } - - return "None"; -} - - -/// -/// Register backend -/// -void MergeFactory::registerBackend( const QString& id, - const QString& name, - SourceType type, - CreateFct create ) -{ - BackendEntry backend; - - backend.name = name; - backend.type = type; - backend.create = create; - - mBackendIdMap[ id ] = backend; -} - - diff --git a/glabels/Merge/MergeFactory.h b/glabels/Merge/MergeFactory.h deleted file mode 100644 index edd3718..0000000 --- a/glabels/Merge/MergeFactory.h +++ /dev/null @@ -1,96 +0,0 @@ -/* MergeFactory.h - * - * Copyright (C) 2016 Jim Evins - * - * 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 . - */ - -#ifndef MergeFactory_h -#define MergeFactory_h - -#include "Merge.h" -#include -#include - - -/// -/// MergeFactory -/// -struct MergeFactory -{ - Q_DECLARE_TR_FUNCTIONS(MergeFactory) - - - ///////////////////////////////// - // Source Type - ///////////////////////////////// -public: - enum SourceType { NONE, FIXED, FILE }; - - - ///////////////////////////////// - // Life Cycle - ///////////////////////////////// -protected: - MergeFactory(); - - - ///////////////////////////////// - // Static methods - ///////////////////////////////// -public: - static void init(); - - static Merge* createMerge( const QString& id ); - - static QStringList nameList(); - static QString idToName( const QString& id ); - static QString nameToId( const QString& name ); - static SourceType idToType( const QString& id ); - static QString indexToId( int index ); - - - ///////////////////////////////// - // private methods - ///////////////////////////////// -private: - typedef Merge* (*CreateFct)(); - - static void registerBackend( const QString& id, - const QString& name, - SourceType type, - CreateFct create ); - - - ///////////////////////////////// - // private data - ///////////////////////////////// - class BackendEntry - { - public: - QString id; - QString name; - SourceType type; - CreateFct create; - }; - - static QMap mBackendIdMap; - static QMap mBackendNameMap; - -}; - - -#endif // MergeFactory_h diff --git a/glabels/Merge/MergeNone.cpp b/glabels/Merge/MergeNone.cpp deleted file mode 100644 index 732b513..0000000 --- a/glabels/Merge/MergeNone.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* MergeNone.cpp - * - * Copyright (C) 2015 Jim Evins - * - * 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 . - */ - -#include "MergeNone.h" - - -/// -/// Constructor -/// -MergeNone::MergeNone() : Merge() -{ - mId = "None"; -} - - -/// -/// Constructor -/// -MergeNone::MergeNone( const MergeNone* merge ) : Merge( merge ) -{ -} - - -/// -/// Destructor -/// -MergeNone::~MergeNone() -{ -} - - -/// -/// Clone -/// -MergeNone* MergeNone::clone() const -{ - return new MergeNone( this ); -} - - -/// -/// Get ID -/// -QString MergeNone::id() -{ - return "None"; -} - - -/// -/// Create -/// -Merge* MergeNone::create() -{ - return new MergeNone(); -} - - -/// -/// Get key list -/// -QStringList MergeNone::keys() const -{ - QStringList emptyList; - return emptyList; -} - - -/// -/// Get primary key -/// -QString MergeNone::primaryKey() const -{ - return ""; -} - - -/// -/// Open source -/// -void MergeNone::open() -{ -} - - -/// -/// Close source -/// -void MergeNone::close() -{ -} - - -/// -/// Read next record -/// -MergeRecord* MergeNone::readNextRecord() -{ - return 0; -} diff --git a/glabels/Merge/MergeNone.h b/glabels/Merge/MergeNone.h deleted file mode 100644 index f17d64d..0000000 --- a/glabels/Merge/MergeNone.h +++ /dev/null @@ -1,70 +0,0 @@ -/* MergeNone.h - * - * Copyright (C) 2015 Jim Evins - * - * 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 . - */ - -#ifndef MergeNone_h -#define MergeNone_h - -#include "Merge.h" - - -/// -/// MergeNone Backend -/// -struct MergeNone : public Merge -{ - - ///////////////////////////////// - // Life Cycle - ///////////////////////////////// -public: - MergeNone(); - MergeNone( const MergeNone* merge ); - virtual ~MergeNone(); - - - ///////////////////////////////// - // Object duplication - ///////////////////////////////// - MergeNone* clone() const; - - - ///////////////////////////////// - // Static methods - ///////////////////////////////// -public: - static QString id(); - static Merge* create(); - - - ///////////////////////////////// - // Implementation of virtual methods - ///////////////////////////////// -public: - QStringList keys() const; - QString primaryKey() const; -protected: - void open(); - void close(); - MergeRecord* readNextRecord(); - -}; - - -#endif // MergeNone_h diff --git a/glabels/Merge/MergeText.cpp b/glabels/Merge/MergeText.cpp deleted file mode 100644 index 60d6e1f..0000000 --- a/glabels/Merge/MergeText.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* MergeText.cpp - * - * Copyright (C) 2016 Jim Evins - * - * 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 . - */ - -#include "MergeText.h" - -#include -#include - - -/// -/// Constructor -/// -MergeText::MergeText( QChar delimiter, bool line1HasKeys ) - : mNFieldsMax(0), mDelimeter(delimiter), mLine1HasKeys(line1HasKeys) -{ -} - - -/// -/// Constructor -/// -MergeText::MergeText( const MergeText* merge ) - : Merge( merge ), - mNFieldsMax(merge->mNFieldsMax), - mDelimeter(merge->mDelimeter), mLine1HasKeys(merge->mLine1HasKeys) -{ -} - - -/// -/// Destructor -/// -MergeText::~MergeText() -{ -} - - -/// -/// Get key list -/// -QStringList MergeText::keys() const -{ - QStringList keys; - for ( int iField = 0; iField < mNFieldsMax; iField++ ) - { - keys << keyFromIndex(iField); - } - return keys; -} - - -/// -/// Get primary key -/// -QString MergeText::primaryKey() const -{ - return keyFromIndex(0); -} - - -/// -/// Open source -/// -void MergeText::open() -{ - mFile.setFileName( source() ); - mFile.open( QIODevice::ReadOnly|QIODevice::Text ); - - mKeys.clear(); - mNFieldsMax = 0; - - if ( mLine1HasKeys && mFile.isOpen() ) - { - mKeys = parseLine(); - if ( (mKeys.size() == 1) && (mKeys[0] == "") ) - { - mKeys.clear(); - } - else - { - mNFieldsMax = mKeys.size(); - } - } -} - - -/// -/// Close source -/// -void MergeText::close() -{ - if ( mFile.isOpen() ) - { - mFile.close(); - } -} - - -/// -/// Read next record -/// -MergeRecord* MergeText::readNextRecord() -{ - QStringList values = parseLine(); - if ( !values.isEmpty() ) - { - MergeRecord* record = new MergeRecord(); - - int iField = 0; - foreach ( QString value, values ) - { - (*record)[ keyFromIndex(iField) ] = value; - iField++; - } - mNFieldsMax = std::max( mNFieldsMax, iField ); - - return record; - } - return 0; -} - - -/// -/// Key from field index -/// -QString MergeText::keyFromIndex( int iField ) const -{ - if ( mLine1HasKeys && ( iField < mKeys.size() ) ) - { - return mKeys[iField]; - } - else - { - return QString::number( iField+1 ); - } -} - - -/// -/// Parse line. -/// -/// Attempt to be a robust parser of various CSV (and similar) formats. -/// -/// Based on CSV format described in RFC 4180 section 2. -/// -/// Additions to RFC 4180 rules: -/// - delimeters and other special characters may be "escaped" by a leading -/// backslash (\) -/// - C escape sequences for newline (\n) and tab (\t) are also translated. -/// - if quoted text is not followed by a delimeter, any additional text is -/// concatenated with quoted portion. -/// -/// Returns a list of fields. A blank line is considered a line with one -/// empty field. Returns an empty list when done. -/// -QStringList MergeText::parseLine() -{ - QStringList fields; - - enum State - { - DELIM, QUOTED, QUOTED_QUOTE1, QUOTED_ESCAPED, SIMPLE, SIMPLE_ESCAPED, DONE - } state = DELIM; - - QByteArray field; - - while ( state != DONE ) - { - char c; - if ( mFile.getChar( &c ) ) - { - switch (state) - { - - case DELIM: - switch (c) - { - case '\n': - /* last field is empty. */ - fields << ""; - state = DONE; - break; - case '\r': - /* ignore */ - state = DELIM; - break; - case '"': - /* start a quoted field. */ - state = QUOTED; - break; - case '\\': - /* simple field, but 1st character is an escape. */ - state = SIMPLE_ESCAPED; - break; - default: - if ( c == mDelimeter ) - { - /* field is empty. */ - fields << ""; - state = DELIM; - } - else - { - /* begining of a simple field. */ - field.append( c ); - state = SIMPLE; - } - break; - } - break; - - case QUOTED: - switch (c) - { - case '"': - /* Possible end of field, but could be 1st of a pair. */ - state = QUOTED_QUOTE1; - break; - case '\\': - /* Escape next character, or special escape, e.g. \n. */ - state = QUOTED_ESCAPED; - break; - default: - /* Use character literally. */ - field.append( c ); - break; - } - break; - - case QUOTED_QUOTE1: - switch (c) - { - case '\n': - /* line ended after quoted item */ - fields << QString( field ); - state = DONE; - break; - case '"': - /* second quote, insert and stay quoted. */ - field.append( c ); - state = QUOTED; - break; - case '\r': - /* ignore and go to fallback */ - state = SIMPLE; - break; - default: - if ( c == mDelimeter ) - { - /* end of field. */ - fields << QString( field ); - field.clear(); - state = DELIM; - } - else - { - /* fallback if not a delim or another quote. */ - field.append( c ); - state = SIMPLE; - } - break; - } - break; - - case QUOTED_ESCAPED: - switch (c) - { - case 'n': - /* Decode "\n" as newline. */ - field.append( '\n' ); - state = QUOTED; - break; - case 't': - /* Decode "\t" as tab. */ - field.append( '\t' ); - state = QUOTED; - break; - default: - /* Use character literally. */ - field.append( c ); - state = QUOTED; - break; - } - break; - - case SIMPLE: - switch (c) - { - case '\n': - /* line ended */ - fields << QString( field ); - state = DONE; - break; - case '\r': - /* ignore */ - state = SIMPLE; - break; - case '\\': - /* Escape next character, or special escape, e.g. \n. */ - state = SIMPLE_ESCAPED; - break; - default: - if ( c == mDelimeter ) - { - /* end of field. */ - fields << QString( field ); - field.clear(); - state = DELIM; - } - else - { - /* Use character literally. */ - field.append( c ); - state = SIMPLE; - } - break; - } - break; - - case SIMPLE_ESCAPED: - switch (c) - { - case 'n': - /* Decode "\n" as newline. */ - field.append( '\n' ); - state = SIMPLE; - break; - case 't': - /* Decode "\t" as tab. */ - field.append( '\t' ); - state = SIMPLE; - break; - default: - /* Use character literally. */ - field.append( (char)c ); - state = SIMPLE; - break; - } - break; - - default: - qWarning( "MergeText::parseLine()::Should not be reached! #1" ); - break; - } - - } - else - { - /* Handle EOF (could also be an error while reading). */ - switch (state) - { - - case DELIM: - /* EOF, no more lines. */ - break; - - case QUOTED: - /* File ended midway through quoted item. Truncate field. */ - fields << QString( field ); - break; - - case QUOTED_QUOTE1: - /* File ended after quoted item. */ - fields << QString( field ); - break; - - case QUOTED_ESCAPED: - /* File ended midway through quoted item. Truncate field. */ - fields << QString( field ); - break; - - case SIMPLE: - /* File ended after simple item. */ - fields << QString( field ); - break; - - case SIMPLE_ESCAPED: - /* File ended midway through escaped item. */ - fields << QString( field ); - break; - - default: - qWarning( "MergeText::parseLine()::Should not be reached! #2" ); - break; - } - - state = DONE; - } - } - - - return fields; -} - - diff --git a/glabels/Merge/MergeText.h b/glabels/Merge/MergeText.h deleted file mode 100644 index e22333a..0000000 --- a/glabels/Merge/MergeText.h +++ /dev/null @@ -1,76 +0,0 @@ -/* MergeText.h - * - * Copyright (C) 2016 Jim Evins - * - * 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 . - */ - -#ifndef MergeText_h -#define MergeText_h - -#include "Merge.h" - -#include - - -/// -/// MergeText Backend -/// -struct MergeText : public Merge -{ - - ///////////////////////////////// - // Life Cycle - ///////////////////////////////// -protected: - MergeText( QChar delimiter, bool line1HasKeys ); - MergeText( const MergeText* merge ); - virtual ~MergeText(); - - - ///////////////////////////////// - // Implementation of virtual methods - ///////////////////////////////// -public: - QStringList keys() const; - QString primaryKey() const; -protected: - void open(); - void close(); - MergeRecord* readNextRecord(); - - - ///////////////////////////////// - // Private methods - ///////////////////////////////// - QString keyFromIndex( int iField ) const; - QStringList parseLine(); - - - ///////////////////////////////// - // Private data - ///////////////////////////////// -private: - QChar mDelimeter; - bool mLine1HasKeys; - - QFile mFile; - QStringList mKeys; - int mNFieldsMax; -}; - - -#endif // MergeText_h diff --git a/glabels/Merge/None.cpp b/glabels/Merge/None.cpp new file mode 100644 index 0000000..c6cfc97 --- /dev/null +++ b/glabels/Merge/None.cpp @@ -0,0 +1,122 @@ +/* Merge/None.cpp + * + * Copyright (C) 2015-2016 Jim Evins + * + * 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 . + */ + +#include "None.h" + + +namespace merge +{ + + /// + /// Constructor + /// + None::None() : Merge() + { + mId = "None"; + } + + + /// + /// Constructor + /// + None::None( const None* merge ) : Merge( merge ) + { + } + + + /// + /// Destructor + /// + None::~None() + { + } + + + /// + /// Clone + /// + None* None::clone() const + { + return new None( this ); + } + + + /// + /// Get ID + /// + QString None::id() + { + return "None"; + } + + + /// + /// Create + /// + Merge* None::create() + { + return new None(); + } + + + /// + /// Get key list + /// + QStringList None::keys() const + { + QStringList emptyList; + return emptyList; + } + + + /// + /// Get primary key + /// + QString None::primaryKey() const + { + return ""; + } + + + /// + /// Open source + /// + void None::open() + { + } + + + /// + /// Close source + /// + void None::close() + { + } + + + /// + /// Read next record + /// + Record* None::readNextRecord() + { + return 0; + } + +} diff --git a/glabels/Merge/None.h b/glabels/Merge/None.h new file mode 100644 index 0000000..63c9fe4 --- /dev/null +++ b/glabels/Merge/None.h @@ -0,0 +1,74 @@ +/* Merge/None.h + * + * Copyright (C) 2015-2016 Jim Evins + * + * 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 . + */ + +#ifndef merge_None_h +#define merge_None_h + +#include "Merge.h" + + +namespace merge +{ + + /// + /// None Merge Backend + /// + struct None : public Merge + { + + ///////////////////////////////// + // Life Cycle + ///////////////////////////////// + public: + None(); + None( const None* merge ); + virtual ~None(); + + + ///////////////////////////////// + // Object duplication + ///////////////////////////////// + None* clone() const; + + + ///////////////////////////////// + // Static methods + ///////////////////////////////// + public: + static QString id(); + static Merge* create(); + + + ///////////////////////////////// + // Implementation of virtual methods + ///////////////////////////////// + public: + QStringList keys() const; + QString primaryKey() const; + protected: + void open(); + void close(); + Record* readNextRecord(); + + }; + +} + +#endif // merge_None_h diff --git a/glabels/Merge/MergeRecord.cpp b/glabels/Merge/Record.cpp similarity index 58% rename from glabels/Merge/MergeRecord.cpp rename to glabels/Merge/Record.cpp index 570988d..5286fa1 100644 --- a/glabels/Merge/MergeRecord.cpp +++ b/glabels/Merge/Record.cpp @@ -1,4 +1,4 @@ -/* MergeRecord.cpp +/* Merge/Record.cpp * * Copyright (C) 2013-2016 Jim Evins * @@ -18,48 +18,53 @@ * along with gLabels-qt. If not, see . */ -#include "MergeRecord.h" +#include "Record.h" -/// -/// Constructor -/// -MergeRecord::MergeRecord() : mSelected( true ) +namespace merge { -} - - -/// -/// Constructor -/// -MergeRecord::MergeRecord( const MergeRecord* record ) - : QMap(*record), mSelected(record->mSelected) -{ -} - - -/// -/// Clone -/// -MergeRecord* MergeRecord::clone() const -{ - return new MergeRecord( this ); -} - - -/// -/// Is record selected? -/// -bool MergeRecord::isSelected() const -{ - return mSelected; -} - - -/// -/// Set selected on not selected -/// -void MergeRecord::setSelected( bool value ) -{ - mSelected = value; + + /// + /// Constructor + /// + Record::Record() : mSelected( true ) + { + } + + + /// + /// Constructor + /// + Record::Record( const Record* record ) + : QMap(*record), mSelected(record->mSelected) + { + } + + + /// + /// Clone + /// + Record* Record::clone() const + { + return new Record( this ); + } + + + /// + /// Is record selected? + /// + bool Record::isSelected() const + { + return mSelected; + } + + + /// + /// Set selected on not selected + /// + void Record::setSelected( bool value ) + { + mSelected = value; + } + } diff --git a/glabels/Merge/MergeRecord.h b/glabels/Merge/Record.h similarity index 51% rename from glabels/Merge/MergeRecord.h rename to glabels/Merge/Record.h index 5323476..d672a59 100644 --- a/glabels/Merge/MergeRecord.h +++ b/glabels/Merge/Record.h @@ -1,4 +1,4 @@ -/* MergeRecord.h +/* Merge/Record.h * * Copyright (C) 2013-2016 Jim Evins * @@ -18,48 +18,52 @@ * along with gLabels-qt. If not, see . */ -#ifndef MergeRecord_h -#define MergeRecord_h +#ifndef merge_Record_h +#define merge_Record_h #include #include -/// -/// Merge Record -/// -struct MergeRecord : public QMap +namespace merge { + + /// + /// Merge Record + /// + struct Record : public QMap + { - ///////////////////////////////// - // Life Cycle - ///////////////////////////////// -public: - MergeRecord(); - MergeRecord( const MergeRecord* record ); + ///////////////////////////////// + // Life Cycle + ///////////////////////////////// + public: + Record(); + Record( const Record* record ); - ///////////////////////////////// - // Object duplication - ///////////////////////////////// - MergeRecord* clone() const; + ///////////////////////////////// + // Object duplication + ///////////////////////////////// + Record* clone() const; - ///////////////////////////////// - // Properties - ///////////////////////////////// -public: - bool isSelected() const; - void setSelected( bool value ); + ///////////////////////////////// + // Properties + ///////////////////////////////// + public: + bool isSelected() const; + void setSelected( bool value ); - ///////////////////////////////// - // Private data - ///////////////////////////////// -private: - bool mSelected; + ///////////////////////////////// + // Private data + ///////////////////////////////// + private: + bool mSelected; -}; + }; +} -#endif // MergeRecord_h +#endif // merge_Record_h diff --git a/glabels/Merge/Text.cpp b/glabels/Merge/Text.cpp new file mode 100644 index 0000000..6558e1b --- /dev/null +++ b/glabels/Merge/Text.cpp @@ -0,0 +1,416 @@ +/* Merge/Text.cpp + * + * Copyright (C) 2016 Jim Evins + * + * 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 . + */ + +#include "Text.h" + +#include "Record.h" +#include +#include + + +namespace merge +{ + + /// + /// Constructor + /// + Text::Text( QChar delimiter, bool line1HasKeys ) + : mNFieldsMax(0), mDelimeter(delimiter), mLine1HasKeys(line1HasKeys) + { + } + + + /// + /// Constructor + /// + Text::Text( const Text* merge ) + : Merge( merge ), + mNFieldsMax(merge->mNFieldsMax), + mDelimeter(merge->mDelimeter), mLine1HasKeys(merge->mLine1HasKeys) + { + } + + + /// + /// Destructor + /// + Text::~Text() + { + } + + + /// + /// Get key list + /// + QStringList Text::keys() const + { + QStringList keys; + for ( int iField = 0; iField < mNFieldsMax; iField++ ) + { + keys << keyFromIndex(iField); + } + return keys; + } + + + /// + /// Get primary key + /// + QString Text::primaryKey() const + { + return keyFromIndex(0); + } + + + /// + /// Open source + /// + void Text::open() + { + mFile.setFileName( source() ); + mFile.open( QIODevice::ReadOnly|QIODevice::Text ); + + mKeys.clear(); + mNFieldsMax = 0; + + if ( mLine1HasKeys && mFile.isOpen() ) + { + mKeys = parseLine(); + if ( (mKeys.size() == 1) && (mKeys[0] == "") ) + { + mKeys.clear(); + } + else + { + mNFieldsMax = mKeys.size(); + } + } + } + + + /// + /// Close source + /// + void Text::close() + { + if ( mFile.isOpen() ) + { + mFile.close(); + } + } + + + /// + /// Read next record + /// + Record* Text::readNextRecord() + { + QStringList values = parseLine(); + if ( !values.isEmpty() ) + { + Record* record = new Record(); + + int iField = 0; + foreach ( QString value, values ) + { + (*record)[ keyFromIndex(iField) ] = value; + iField++; + } + mNFieldsMax = std::max( mNFieldsMax, iField ); + + return record; + } + return 0; + } + + + /// + /// Key from field index + /// + QString Text::keyFromIndex( int iField ) const + { + if ( mLine1HasKeys && ( iField < mKeys.size() ) ) + { + return mKeys[iField]; + } + else + { + return QString::number( iField+1 ); + } + } + + + /// + /// Parse line. + /// + /// Attempt to be a robust parser of various CSV (and similar) formats. + /// + /// Based on CSV format described in RFC 4180 section 2. + /// + /// Additions to RFC 4180 rules: + /// - delimeters and other special characters may be "escaped" by a leading + /// backslash (\) + /// - C escape sequences for newline (\n) and tab (\t) are also translated. + /// - if quoted text is not followed by a delimeter, any additional text is + /// concatenated with quoted portion. + /// + /// Returns a list of fields. A blank line is considered a line with one + /// empty field. Returns an empty list when done. + /// + QStringList Text::parseLine() + { + QStringList fields; + + enum State + { + DELIM, QUOTED, QUOTED_QUOTE1, QUOTED_ESCAPED, SIMPLE, SIMPLE_ESCAPED, DONE + } state = DELIM; + + QByteArray field; + + while ( state != DONE ) + { + char c; + if ( mFile.getChar( &c ) ) + { + switch (state) + { + + case DELIM: + switch (c) + { + case '\n': + /* last field is empty. */ + fields << ""; + state = DONE; + break; + case '\r': + /* ignore */ + state = DELIM; + break; + case '"': + /* start a quoted field. */ + state = QUOTED; + break; + case '\\': + /* simple field, but 1st character is an escape. */ + state = SIMPLE_ESCAPED; + break; + default: + if ( c == mDelimeter ) + { + /* field is empty. */ + fields << ""; + state = DELIM; + } + else + { + /* begining of a simple field. */ + field.append( c ); + state = SIMPLE; + } + break; + } + break; + + case QUOTED: + switch (c) + { + case '"': + /* Possible end of field, but could be 1st of a pair. */ + state = QUOTED_QUOTE1; + break; + case '\\': + /* Escape next character, or special escape, e.g. \n. */ + state = QUOTED_ESCAPED; + break; + default: + /* Use character literally. */ + field.append( c ); + break; + } + break; + + case QUOTED_QUOTE1: + switch (c) + { + case '\n': + /* line ended after quoted item */ + fields << QString( field ); + state = DONE; + break; + case '"': + /* second quote, insert and stay quoted. */ + field.append( c ); + state = QUOTED; + break; + case '\r': + /* ignore and go to fallback */ + state = SIMPLE; + break; + default: + if ( c == mDelimeter ) + { + /* end of field. */ + fields << QString( field ); + field.clear(); + state = DELIM; + } + else + { + /* fallback if not a delim or another quote. */ + field.append( c ); + state = SIMPLE; + } + break; + } + break; + + case QUOTED_ESCAPED: + switch (c) + { + case 'n': + /* Decode "\n" as newline. */ + field.append( '\n' ); + state = QUOTED; + break; + case 't': + /* Decode "\t" as tab. */ + field.append( '\t' ); + state = QUOTED; + break; + default: + /* Use character literally. */ + field.append( c ); + state = QUOTED; + break; + } + break; + + case SIMPLE: + switch (c) + { + case '\n': + /* line ended */ + fields << QString( field ); + state = DONE; + break; + case '\r': + /* ignore */ + state = SIMPLE; + break; + case '\\': + /* Escape next character, or special escape, e.g. \n. */ + state = SIMPLE_ESCAPED; + break; + default: + if ( c == mDelimeter ) + { + /* end of field. */ + fields << QString( field ); + field.clear(); + state = DELIM; + } + else + { + /* Use character literally. */ + field.append( c ); + state = SIMPLE; + } + break; + } + break; + + case SIMPLE_ESCAPED: + switch (c) + { + case 'n': + /* Decode "\n" as newline. */ + field.append( '\n' ); + state = SIMPLE; + break; + case 't': + /* Decode "\t" as tab. */ + field.append( '\t' ); + state = SIMPLE; + break; + default: + /* Use character literally. */ + field.append( (char)c ); + state = SIMPLE; + break; + } + break; + + default: + qWarning( "merge::Text::parseLine()::Should not be reached! #1" ); + break; + } + + } + else + { + /* Handle EOF (could also be an error while reading). */ + switch (state) + { + + case DELIM: + /* EOF, no more lines. */ + break; + + case QUOTED: + /* File ended midway through quoted item. Truncate field. */ + fields << QString( field ); + break; + + case QUOTED_QUOTE1: + /* File ended after quoted item. */ + fields << QString( field ); + break; + + case QUOTED_ESCAPED: + /* File ended midway through quoted item. Truncate field. */ + fields << QString( field ); + break; + + case SIMPLE: + /* File ended after simple item. */ + fields << QString( field ); + break; + + case SIMPLE_ESCAPED: + /* File ended midway through escaped item. */ + fields << QString( field ); + break; + + default: + qWarning( "merge::Text::parseLine()::Should not be reached! #2" ); + break; + } + + state = DONE; + } + } + + + return fields; + } + +} diff --git a/glabels/Merge/Text.h b/glabels/Merge/Text.h new file mode 100644 index 0000000..ae9c872 --- /dev/null +++ b/glabels/Merge/Text.h @@ -0,0 +1,80 @@ +/* Merge/Text.h + * + * Copyright (C) 2016 Jim Evins + * + * 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 . + */ + +#ifndef merge_Text_h +#define merge_Text_h + +#include "Merge.h" + +#include + + +namespace merge +{ + + /// + /// Text Merge Backend + /// + struct Text : public Merge + { + + ///////////////////////////////// + // Life Cycle + ///////////////////////////////// + protected: + Text( QChar delimiter, bool line1HasKeys ); + Text( const Text* merge ); + virtual ~Text(); + + + ///////////////////////////////// + // Implementation of virtual methods + ///////////////////////////////// + public: + QStringList keys() const; + QString primaryKey() const; + protected: + void open(); + void close(); + Record* readNextRecord(); + + + ///////////////////////////////// + // Private methods + ///////////////////////////////// + QString keyFromIndex( int iField ) const; + QStringList parseLine(); + + + ///////////////////////////////// + // Private data + ///////////////////////////////// + private: + QChar mDelimeter; + bool mLine1HasKeys; + + QFile mFile; + QStringList mKeys; + int mNFieldsMax; + }; + +} + +#endif // merge_Text_h diff --git a/glabels/Merge/MergeTextCsv.cpp b/glabels/Merge/TextCsv.cpp similarity index 58% rename from glabels/Merge/MergeTextCsv.cpp rename to glabels/Merge/TextCsv.cpp index 086b885..e774afe 100644 --- a/glabels/Merge/MergeTextCsv.cpp +++ b/glabels/Merge/TextCsv.cpp @@ -1,4 +1,4 @@ -/* MergeTextCsv.cpp +/* Merge/TextCsv.cpp * * Copyright (C) 2016 Jim Evins * @@ -18,56 +18,61 @@ * along with gLabels-qt. If not, see . */ -#include "MergeTextCsv.h" +#include "TextCsv.h" -/// -/// Constructor -/// -MergeTextCsv::MergeTextCsv() : MergeText(',',false) +namespace merge { - mId = "Text/Comma"; -} - - -/// -/// Constructor -/// -MergeTextCsv::MergeTextCsv( const MergeTextCsv* merge ) : MergeText( merge ) -{ -} - - -/// -/// Destructor -/// -MergeTextCsv::~MergeTextCsv() -{ -} - - -/// -/// Clone -/// -MergeTextCsv* MergeTextCsv::clone() const -{ - return new MergeTextCsv( this ); -} - - -/// -/// Get ID -/// -QString MergeTextCsv::id() -{ - return "Text/Comma"; -} - - -/// -/// Create -/// -Merge* MergeTextCsv::create() -{ - return new MergeTextCsv(); + + /// + /// Constructor + /// + TextCsv::TextCsv() : Text(',',false) + { + mId = "Text/Comma"; + } + + + /// + /// Constructor + /// + TextCsv::TextCsv( const TextCsv* merge ) : Text( merge ) + { + } + + + /// + /// Destructor + /// + TextCsv::~TextCsv() + { + } + + + /// + /// Clone + /// + TextCsv* TextCsv::clone() const + { + return new TextCsv( this ); + } + + + /// + /// Get ID + /// + QString TextCsv::id() + { + return "Text/Comma"; + } + + + /// + /// Create + /// + Merge* TextCsv::create() + { + return new TextCsv(); + } + } diff --git a/glabels/Merge/MergeTextCsv.h b/glabels/Merge/TextCsv.h similarity index 53% rename from glabels/Merge/MergeTextCsv.h rename to glabels/Merge/TextCsv.h index c6991ce..c5d0255 100644 --- a/glabels/Merge/MergeTextCsv.h +++ b/glabels/Merge/TextCsv.h @@ -1,4 +1,4 @@ -/* MergeTextCsv.h +/* Merge/TextCsv.h * * Copyright (C) 2016 Jim Evins * @@ -18,42 +18,46 @@ * along with gLabels-qt. If not, see . */ -#ifndef MergeTextCsv_h -#define MergeTextCsv_h +#ifndef merge_TextCsv_h +#define merge_TextCsv_h -#include "MergeText.h" +#include "Text.h" -/// -/// MergeTextCsv Backend -/// -struct MergeTextCsv : public MergeText +namespace merge { + + /// + /// TextCsv Merge Backend + /// + struct TextCsv : public Text + { - ///////////////////////////////// - // Life Cycle - ///////////////////////////////// -private: - MergeTextCsv(); - MergeTextCsv( const MergeTextCsv* merge ); - virtual ~MergeTextCsv(); + ///////////////////////////////// + // Life Cycle + ///////////////////////////////// + private: + TextCsv(); + TextCsv( const TextCsv* merge ); + virtual ~TextCsv(); - ///////////////////////////////// - // Object duplication - ///////////////////////////////// -public: - static QString id(); - MergeTextCsv* clone() const; + ///////////////////////////////// + // Object duplication + ///////////////////////////////// + public: + static QString id(); + TextCsv* clone() const; - ///////////////////////////////// - // Static methods - ///////////////////////////////// -public: - static Merge* create(); + ///////////////////////////////// + // Static methods + ///////////////////////////////// + public: + static Merge* create(); -}; + }; +} -#endif // MergeTextCsv_h +#endif // merge_TextCsv_h diff --git a/glabels/MergeView.cpp b/glabels/MergeView.cpp index 1e76bc9..769c83e 100644 --- a/glabels/MergeView.cpp +++ b/glabels/MergeView.cpp @@ -21,7 +21,7 @@ #include "MergeView.h" #include "LabelModel.h" -#include "Merge/MergeFactory.h" +#include "Merge/Factory.h" #include #include #include @@ -35,7 +35,7 @@ MergeView::MergeView( QWidget *parent ) { setupUi( this ); - mMergeFormatNames = MergeFactory::nameList(); + mMergeFormatNames = merge::Factory::nameList(); formatCombo->addItems( mMergeFormatNames ); } @@ -76,20 +76,20 @@ void MergeView::setModel( LabelModel* model, UndoRedoModel* undoRedoModel ) /// void MergeView::onMergeChanged() { - int index = mMergeFormatNames.indexOf( MergeFactory::idToName( mModel->merge()->id() ) ); + int index = mMergeFormatNames.indexOf( merge::Factory::idToName( mModel->merge()->id() ) ); mOldFormatComboIndex = index; formatCombo->setCurrentIndex( index ); - switch ( MergeFactory::idToType( mModel->merge()->id() ) ) + switch ( merge::Factory::idToType( mModel->merge()->id() ) ) { - case MergeFactory::NONE: - case MergeFactory::FIXED: + case merge::Factory::NONE: + case merge::Factory::FIXED: locationLabel->setEnabled( false ); locationButton->setEnabled( false ); locationButton->setText( "" ); break; - case MergeFactory::FILE: + case merge::Factory::FILE: locationLabel->setEnabled( true ); locationButton->setEnabled( true ); if ( mModel->merge()->source().isEmpty() ) @@ -140,10 +140,10 @@ void MergeView::onMergeSelectionChanged() { mBlock = true; // Don't recurse - const QList& records = mModel->merge()->recordList(); + const QList& records = mModel->merge()->recordList(); int iRow = 0; - foreach ( MergeRecord* record, records ) + foreach ( merge::Record* record, records ) { QTableWidgetItem* item = recordsTable->item( iRow, 0 ); item->setCheckState( record->isSelected() ? Qt::Checked : Qt::Unchecked ); @@ -164,7 +164,7 @@ void MergeView::onFormatComboActivated() { mOldFormatComboIndex = index; - mModel->setMerge( MergeFactory::createMerge( MergeFactory::indexToId(index) ) ); + mModel->setMerge( merge::Factory::createMerge( merge::Factory::indexToId(index) ) ); } } @@ -223,7 +223,7 @@ void MergeView::onCellChanged( int iRow, int iCol ) /// /// Load headers /// -void MergeView::loadHeaders( Merge* merge ) +void MergeView::loadHeaders( merge::Merge* merge ) { mPrimaryKey = merge->primaryKey(); mKeys = merge->keys(); @@ -264,15 +264,15 @@ void MergeView::loadHeaders( Merge* merge ) /// /// Load table /// -void MergeView::loadTable( Merge* merge ) +void MergeView::loadTable( merge::Merge* merge ) { mBlock = true; - const QList& records = merge->recordList(); + const QList& records = merge->recordList(); recordsTable->setRowCount( records.size() ); int iRow = 0; - foreach ( MergeRecord* record, records ) + foreach ( merge::Record* record, records ) { // First column for primay field QTableWidgetItem* item = new QTableWidgetItem(); diff --git a/glabels/MergeView.h b/glabels/MergeView.h index 4227867..df33c72 100644 --- a/glabels/MergeView.h +++ b/glabels/MergeView.h @@ -22,16 +22,16 @@ #define MergeView_h #include "ui_MergeView.h" +#include "Merge/Merge.h" // Forward references class LabelModel; class UndoRedoModel; -class Merge; /// -/// Merge Property Editor Widget +/// merge::Merge Property Editor Widget /// class MergeView : public QWidget, public Ui_MergeView { @@ -71,8 +71,8 @@ private slots: // Private methods ///////////////////////////////// private: - void loadHeaders( Merge* merge ); - void loadTable( Merge* merge ); + void loadHeaders( merge::Merge* merge ); + void loadTable( merge::Merge* merge ); ///////////////////////////////// diff --git a/glabels/PageRenderer.cpp b/glabels/PageRenderer.cpp index 78a44ec..ff8eec1 100644 --- a/glabels/PageRenderer.cpp +++ b/glabels/PageRenderer.cpp @@ -22,8 +22,8 @@ #include "LabelModel.h" #include "Merge/Merge.h" -#include "Merge/MergeNone.h" -#include "Merge/MergeRecord.h" +#include "Merge/None.h" +#include "Merge/Record.h" #include #include @@ -52,7 +52,7 @@ void PageRenderer::setModel( const LabelModel* model ) mMerge = mModel->merge(); mOrigins = mModel->frame()->getOrigins(); mNLabelsPerPage = mModel->frame()->nLabels(); - mIsMerge = ( dynamic_cast(mMerge) == 0 ); + mIsMerge = ( dynamic_cast(mMerge) == 0 ); updateNPages(); } @@ -226,7 +226,7 @@ void PageRenderer::printMergePage( QPainter* painter, int iPage ) const iEnd = mLastLabel % mNLabelsPerPage; } - const QList records = mMerge->selectedRecords(); + const QList records = mMerge->selectedRecords(); int iRecord = (iPage*mNLabelsPerPage + iStart - mStartLabel) % records.size(); printCropMarks( painter ); @@ -336,7 +336,7 @@ void PageRenderer::clipLabel( QPainter* painter ) const } -void PageRenderer::printLabel( QPainter* painter, MergeRecord* record ) const +void PageRenderer::printLabel( QPainter* painter, merge::Record* record ) const { painter->save(); diff --git a/glabels/PageRenderer.h b/glabels/PageRenderer.h index ee6fc55..be4680d 100644 --- a/glabels/PageRenderer.h +++ b/glabels/PageRenderer.h @@ -24,14 +24,15 @@ #include "libglabels/Point.h" +#include "Merge/Merge.h" +#include "Merge/Record.h" + #include #include // Forward references class QPainter; class LabelModel; -class Merge; -class MergeRecord; /// @@ -74,15 +75,15 @@ private: void printCropMarks( QPainter* painter ) const; void printOutline( QPainter* painter ) const; void clipLabel( QPainter* painter ) const; - void printLabel( QPainter* painter, MergeRecord* record ) const; + void printLabel( QPainter* painter, merge::Record* record ) const; ///////////////////////////////// // Private Data ///////////////////////////////// private: - const LabelModel* mModel; - const Merge* mMerge; + const LabelModel* mModel; + const merge::Merge* mMerge; int mNCopies; int mStartLabel; diff --git a/glabels/XmlLabelCreator.cpp b/glabels/XmlLabelCreator.cpp index f0474d1..09bdcdc 100644 --- a/glabels/XmlLabelCreator.cpp +++ b/glabels/XmlLabelCreator.cpp @@ -27,7 +27,7 @@ //#include "LabelObjectLine.h" //#include "LabelObjectImage.h" //#include "LabelObjectBarcode.h" -#include "Merge/MergeNone.h" +#include "Merge/None.h" #include "libglabels/XmlTemplateCreator.h" #include "libglabels/XmlUtil.h" @@ -97,7 +97,7 @@ XmlLabelCreator::createDoc( QDomDocument& doc, const LabelModel* label ) createObjectsNode( root, label ); - if ( label->merge() && !dynamic_cast(label->merge()) ) + if ( label->merge() && !dynamic_cast(label->merge()) ) { createMergeNode( root, label ); } diff --git a/glabels/XmlLabelParser.cpp b/glabels/XmlLabelParser.cpp index 3e9e99e..9aefd81 100644 --- a/glabels/XmlLabelParser.cpp +++ b/glabels/XmlLabelParser.cpp @@ -27,7 +27,7 @@ //#include "LabelObjectLine.h" //#include "LabelObjectImage.h" //#include "LabelObjectBarcode.h" -#include "Merge/MergeFactory.h" +#include "Merge/Factory.h" #include "libglabels/XmlTemplateParser.h" #include "libglabels/XmlUtil.h" @@ -441,7 +441,7 @@ XmlLabelParser::parseMergeNode( const QDomElement &node, LabelModel* label ) QString type = XmlUtil::getStringAttr( node, "type", "None" ); QString src = XmlUtil::getStringAttr( node, "src", "" ); - Merge* merge = MergeFactory::createMerge( type ); + merge::Merge* merge = merge::Factory::createMerge( type ); merge->setSource( src ); label->setMerge( merge ); diff --git a/glabels/glabels_main.cpp b/glabels/glabels_main.cpp index 52a2172..42510d6 100644 --- a/glabels/glabels_main.cpp +++ b/glabels/glabels_main.cpp @@ -22,7 +22,7 @@ #include #include "libglabels/Db.h" -#include "Merge/MergeFactory.h" +#include "Merge/Factory.h" #include "Settings.h" #include "MainWindow.h" @@ -37,7 +37,7 @@ int main( int argc, char **argv ) Settings::init(); glabels::Db::init(); - MergeFactory::init(); + merge::Factory::init(); ////// TEMPORARY TESTING //////// #if 0 glabels::Db::printKnownPapers();