#include <tbytevectorlist.h>
#include <id3v2tag.h>
-
+#include <tdebug.h>
#include "textidentificationframe.h"
#include "tpropertymap.h"
#include "id3v1genres.h"
checkFields();
}
+UserTextIdentificationFrame::UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding) :
+ TextIdentificationFrame("TXXX", encoding),
+ d(0)
+{
+ setDescription(description);
+ setText(values);
+}
+
String UserTextIdentificationFrame::toString() const
{
return "[" + description() + "] " + fieldList().toString();
String key = map.prepareKey(tagName);
if(key.isNull()) // this frame's description is not a valid PropertyMap key -> add to unsupported list
map.unsupportedData().append(L"TXXX/" + description());
- else
- for(StringList::ConstIterator it = fieldList().begin(); it != fieldList().end(); ++it)
+ else {
+ StringList v = fieldList();
+ for(StringList::ConstIterator it = v.begin(); it != v.end(); ++it)
if(*it != description())
map.insert(key, *it);
+ }
return map;
}
/*!
* Creates a user defined text identification frame with the given \a description
- * and \a text.
+ * and \a values.
*/
- UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding = String::Latin1);
+ UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding = String::UTF8);
virtual String toString() const;
***************************************************************************/
#include "urllinkframe.h"
+#include "id3v2tag.h"
#include <tdebug.h>
#include <tstringlist.h>
#include <tpropertymap.h>
return map;
}
+UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &description) // static
+{
+ FrameList l = tag->frameList("WXXX");
+ for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) {
+ UserUrlLinkFrame *f = dynamic_cast<UserUrlLinkFrame *>(*it);
+ if(f && f->description() == description)
+ return f;
+ }
+ return 0;
+}
+
void UserUrlLinkFrame::parseFields(const ByteVector &data)
{
if(data.size() < 2) {
*/
PropertyMap asProperties() const;
+ /*!
+ * Searches for the user defined url frame with the description \a description
+ * in \a tag. This returns null if no matching frames were found.
+ */
+ static UserUrlLinkFrame *find(Tag *tag, const String &description);
+
protected:
virtual void parseFields(const ByteVector &data);
virtual ByteVector renderFields() const;
PropertyMap ID3v2::Tag::properties() const
{
PropertyMap properties;
- for(FrameList::ConstIterator it = frameList().begin(); it != frameList().end(); ++it)
- properties.merge((*it)->asProperties());
+
+ for(FrameList::ConstIterator it = frameList().begin(); it != frameList().end(); ++it) {
+ PropertyMap props = (*it)->asProperties();
+ debug(props);
+ properties.merge(props);
+ }
return properties;
}
+void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties)
+{
+ // entries of unsupportedData() are usually frame IDs which are not supported
+ // by the PropertyMap interface. Three special cases exist: TXXX, WXXX, and COMM
+ // frames may also be unsupported if their description() is not a valid key.
+ for(StringList::ConstIterator it = properties.begin(); it != properties.end(); ++it){
+ ByteVector id = it->substr(0,4).data(String::Latin1);
+ if(id == "TXXX") {
+ String description = it->substr(5);
+ Frame *frame = UserTextIdentificationFrame::find(this, description);
+ if(frame)
+ removeFrame(frame);
+ } else if(id == "WXXX") {
+ String description = it->substr(5);
+ Frame *frame = UserUrlLinkFrame::find(this, description);
+ if(frame)
+ removeFrame(frame);
+ } else if(id == "COMM") {
+ String description = it->substr(5);
+ Frame *frame = CommentsFrame::findByDescription(this, description);
+ if(frame)
+ removeFrame(frame);
+ } else
+ removeFrames(id); // there should be only one frame with "id"
+ }
+}
+
PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps)
{
FrameList framesToDelete;
*/
bool operator==(const List<T> &l) const;
+ /*!
+ * Compares this list with \a l and returns true if the lists differ.
+ */
+ bool operator!=(const List<T> &l) const;
+
protected:
/*
* If this List is being shared via implicit sharing, do a deep copy of the
return d->list == l.d->list;
}
+template <class T>
+bool List<T>::operator!=(const List<T> &l) const
+{
+ return d->list != l.d->list;
+}
+
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
***************************************************************************/
#include "tpropertymap.h"
-
using namespace TagLib;
bool PropertyMap::contains(const String &key) const
{
String realKey = prepareKey(key);
- // we consider keys with empty value list as not present
- if(realKey.isNull() || SimplePropertyMap::operator[](realKey).isEmpty())
+ if(realKey.isNull())
return false;
return SimplePropertyMap::contains(realKey);
}
+bool PropertyMap::contains(const PropertyMap &other) const
+{
+ for(ConstIterator it = other.begin(); it != other.end(); ++it) {
+ if(!SimplePropertyMap::contains(it->first))
+ return false;
+ if ((*this)[it->first] != it->second)
+ return false;
+ }
+ return true;
+}
+
PropertyMap &PropertyMap::erase(const String &key)
{
String realKey = prepareKey(key);
- if(realKey.isNull())
- return *this;
- SimplePropertyMap::erase(realKey);
+ if(!realKey.isNull())
+ SimplePropertyMap::erase(realKey);
+ return *this;
+}
+
+PropertyMap &PropertyMap::erase(const PropertyMap &other)
+{
+ for(ConstIterator it = other.begin(); it != other.end(); ++it)
+ erase(it->first);
return *this;
}
return SimplePropertyMap::operator[](realKey);
}
+bool PropertyMap::operator==(const PropertyMap &other) const
+{
+ for(ConstIterator it = other.begin(); it != other.end(); ++it) {
+ ConstIterator thisFind = find(it->first);
+ if( thisFind == end() || (thisFind->second != it->second) )
+ return false;
+ }
+ for(ConstIterator it = begin(); it != end(); ++it) {
+ ConstIterator otherFind = other.find(it->first);
+ if( otherFind == other.end() || (otherFind->second != it->second) )
+ return false;
+ }
+ return unsupported == other.unsupported;
+}
+
+bool PropertyMap::operator!=(const PropertyMap &other) const
+{
+ return !(*this == other);
+}
+
void PropertyMap::removeEmpty()
{
StringList emptyKeys;