#ifndef CSM_WOLRD_IDCOLLECTION_H #define CSM_WOLRD_IDCOLLECTION_H #include #include #include #include #include #include #include #include #include "record.hpp" namespace CSMWorld { template struct Column { std::string mTitle; Column (const std::string& title) : mTitle (title) {} virtual ~Column() {} virtual QVariant get (const Record& record) const = 0; virtual void set (Record& record, const QVariant& data) { throw std::logic_error ("Column " + mTitle + " is not editable"); } virtual bool isEditable() const = 0; }; class IdCollectionBase { // not implemented IdCollectionBase (const IdCollectionBase&); IdCollectionBase& operator= (const IdCollectionBase&); public: IdCollectionBase(); virtual ~IdCollectionBase(); virtual int getSize() const = 0; virtual std::string getId (int index) const = 0; virtual int getIndex (const std::string& id) const = 0; virtual int getColumns() const = 0; virtual std::string getTitle (int column) const = 0; virtual QVariant getData (int index, int column) const = 0; virtual void setData (int index, int column, const QVariant& data) = 0; virtual bool isEditable (int column) const = 0; virtual void merge() = 0; ///< Merge modified into base. virtual void purge() = 0; ///< Remove records that are flagged as erased. virtual void removeRows (int index, int count) = 0; virtual void appendBlankRecord (const std::string& id) = 0; }; ///< \brief Collection of ID-based records template class IdCollection : public IdCollectionBase { std::vector > mRecords; std::map mIndex; std::vector *> mColumns; // not implemented IdCollection (const IdCollection&); IdCollection& operator= (const IdCollection&); public: IdCollection(); virtual ~IdCollection(); void add (const ESXRecordT& record); ///< Add a new record (modified) virtual int getSize() const; virtual std::string getId (int index) const; virtual int getIndex (const std::string& id) const; virtual int getColumns() const; virtual QVariant getData (int index, int column) const; virtual void setData (int index, int column, const QVariant& data); virtual std::string getTitle (int column) const; virtual bool isEditable (int column) const; virtual void merge(); ///< Merge modified into base. virtual void purge(); ///< Remove records that are flagged as erased. virtual void removeRows (int index, int count) ; virtual void appendBlankRecord (const std::string& id); void addColumn (Column *column); }; template IdCollection::IdCollection() {} template IdCollection::~IdCollection() { for (typename std::vector *>::iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter) delete *iter; } template void IdCollection::add (const ESXRecordT& record) { std::string id; std::transform (record.mId.begin(), record.mId.end(), std::back_inserter (id), (int(*)(int)) std::tolower); std::map::iterator iter = mIndex.find (id); if (iter==mIndex.end()) { Record record2; record2.mState = Record::State_ModifiedOnly; record2.mModified = record; mRecords.push_back (record2); mIndex.insert (std::make_pair (id, mRecords.size()-1)); } else { mRecords[iter->second].setModified (record); } } template int IdCollection::getSize() const { return mRecords.size(); } template std::string IdCollection::getId (int index) const { return mRecords.at (index).get().mId; } template int IdCollection::getIndex (const std::string& id) const { std::map::const_iterator iter = mIndex.find (id); if (iter==mIndex.end()) throw std::runtime_error ("invalid ID: " + id); return iter->second; } template int IdCollection::getColumns() const { return mColumns.size(); } template QVariant IdCollection::getData (int index, int column) const { return mColumns.at (column)->get (mRecords.at (index)); } template void IdCollection::setData (int index, int column, const QVariant& data) { return mColumns.at (column)->set (mRecords.at (index), data); } template std::string IdCollection::getTitle (int column) const { return mColumns.at (column)->mTitle; } template bool IdCollection::isEditable (int column) const { return mColumns.at (column)->isEditable(); } template void IdCollection::addColumn (Column *column) { mColumns.push_back (column); } template void IdCollection::merge() { for (typename std::vector >::iterator iter (mRecords.begin()); iter!=mRecords.end(); ++iter) iter->merge(); purge(); } template void IdCollection::purge() { mRecords.erase (std::remove_if (mRecords.begin(), mRecords.end(), std::mem_fun_ref (&Record::isErased) // I want lambda :( ), mRecords.end()); } template void IdCollection::removeRows (int index, int count) { mRecords.erase (mRecords.begin()+index, mRecords.begin()+index+count); typename std::map::iterator iter = mIndex.begin(); while (iter!=mIndex.end()) { if (iter->second>=index) { if (iter->second>=index+count) { iter->second -= count; } else { mIndex.erase (iter++); } } ++iter; } } template void IdCollection::appendBlankRecord (const std::string& id) { ESXRecordT record; record.mId = id; add (record); } } #endif