#ifndef DICTIONARY_H #define DICTIONARY_H #include #include #include #include #include #include #include #include "../export-import/CsvData.h" #include "IDictionary.h" #include "Card.h" #include "Field.h" #include "TreeItem.h" class DicRecord; class CardPack; class AppModel; /** \brief The dictionary * * The dictionary consists of entries #iEntries. * The property #iIsContentModified shows if the dictionary contents are modified and not saved. Different modifications are possible: * \li A single card was modified. Means contents of a card were modified. Signal CardModified(int) is emitted. * \li The Content Modified state is changed. Means that iIsContentModified has changed. Signal ContentModifiedChanged(bool) is emitted. * \li Some cards were inserted or removed. Independently of whether the cards are valid, signal * CardsInserted(int, int) or CardsRemoved(int,int) is emitted. * \li The file path is modified. Means that the dictionary file was renamed, e.g. after "Save as" operation. * Signal filePathChanged() is emitted. * * All card-modifying functions and signals call SetModified(). */ class Dictionary: public TreeItem, public IDictionary { Q_OBJECT friend class DictionaryReader; public: // Methods Dictionary( const QString& aFilePath = "", bool aNameIsTemp = false, const AppModel* aAppModel = NULL ); ~Dictionary(); const TreeItem* parent() const { return NULL; } const TreeItem* child( int aRow ) const; int childCount() const { return cardPacksNum(); } int columnCount() const { return 1; } QVariant data( int aColumn ) const; int row() const; int topParentRow() const { return row(); } void clearFieldPackConfig(); void setDictConfig( const Dictionary* aOtherDic ); void setDefaultFields(); bool load(const QString aFilePath); QFile::FileError save(const QString aFilePath, bool aChangeFilePath = true ); QFile::FileError save() { return save( filePath ); } QFile::FileError saveContent( const QString aFilePath ); QFile::FileError saveStudy(); QString getFilePath() const { return filePath; } QString shortName( bool aMarkModified = true ) const; QString getStudyFilePath() const; QString getErrorMessage() const { return errorMessage; } bool contentModified() const { return m_contentModified; } bool studyModified() const { return m_studyModified; } bool nameIsTemp() const { return m_nameIsTemp; } bool empty() const { return records.isEmpty(); } QList fields() const { return m_fields; } const Field* field( int aIx ) const { return m_fields.value( aIx ); } const Field* field( const QString aFieldName ) const; QString getFieldValue(int recordNum, int fieldNum) const; int fieldsNum() const { return m_fields.size(); } QStringList fieldNames() const; int cardPacksNum() const { return m_cardPacks.size(); } QList cardPacks() const { return m_cardPacks; } CardPack* cardPack( int aIx ) const {return m_cardPacks.value(aIx);} CardPack* cardPack( QString aId ) const; int indexOfCardPack( CardPack* aPack ) const { return m_cardPacks.indexOf( aPack ); } int fieldId04ToIx( const QString aId ) const; // Obsolete const DicRecord* getRecord( int aIndex ) const; const DicRecord* entry04( const QString aId04 ) const; // Obsolete const DicRecord* operator[]( int aIndex ) const { return getRecord(aIndex); } int entriesNum() const { return records.size(); } int indexOfRecord( DicRecord* aRecord ) const { return records.indexOf( aRecord ); } void setAppModel( const AppModel* aModel ) { Q_ASSERT( !m_appModel ); m_appModel = aModel; } // Modify fields void setFieldName( int aField, QString aName ); void setFieldStyle( int aField, QString aStyle ); void insertField( int aPos, QString aName ); void insertField( int aPos, Field* aFieldPtr ); void addField( QString aName, QString aStyle = "" ); void addFields( QStringList aFieldNames ); void removeField( int aPos ); void destroyField( int aPos ); // Modify card packs void insertPack( int aPos, CardPack* aPack ); void removePack( int aPos ); void destroyPack( int aPos ); void addCardPack( CardPack* aCardPack ); // Modify records void setFieldValue( int aEntryIx, int aFieldIx, QString aValue ); void setRecord( int aIndex, const DicRecord& aRecord ); void insertEntry(int aIndex, DicRecord* aEntry); void insertEntries(int aIndex, int aNum); void insertEntries( int aIndex, QList aEntries ); void removeEntry(int aIndex) { removeRecords( aIndex, 1 ); } void cleanRecords(); void removeRecords(int aIndex, int aNum); void removeRecord(QString aQuestion); void disableRecordUpdates(); void enableRecordUpdates(); QString shortenImagePaths(QString text) const; signals: void entryChanged( int aEntryIx, int aFieldIx ); void entriesRemoved( int aIndex, int aNum ); void entriesInserted( int aIndex, int aNum ); void fieldChanged( int aField ); void fieldInserted( int aField ); void fieldRemoved( int aField ); void fieldDestroyed( Field* aField ); void packInserted( int aPack ); void packRemoved( int aPack ); void packDestroyed( CardPack* aPack ); void contentModifiedChanged( bool aModified ); void studyModifiedChanged( bool aModified ); void filePathChanged(); void cardsGenerated(); public slots: void setContentModified( bool aModified = true ); void setContentClean( bool aClean = true ) { setContentModified( !aClean ); } void setStudyModified( bool aModified = true ); void generateCards(); private: bool loadDictFile(const QString filePath); bool loadStudyFile(const QString filePath); void cleanObsoleteId(); protected: void notifyRecordsInserted(int index, int num); public: static const char* NoName; static const QString DictFileExtension; static const QString StudyFileExtension; private: const AppModel* m_appModel; QUuid obsoleteId; // Obsolete starting from 1.0 QList m_fields; bool m_contentModified; bool m_studyModified; /** The current file name is temporary and must be changed at the next save. Use cases: \li the dictionary has just been imported from a CSV file \li the dictionary of obsolete format was converted to the modern format */ bool m_nameIsTemp; QString errorMessage; }; #endif