Mercurial > hg > classical
view common/Objects.h @ 53:bcea875d8d2f tip
More build fixes
author | Chris Cannam |
---|---|
date | Thu, 16 Oct 2014 19:03:51 +0100 |
parents | 5f23d5b29aaf |
children |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ #ifndef _CLASSICAL_DATA_OBJECTS_H_ #define _CLASSICAL_DATA_OBJECTS_H_ #include <dataquay/Uri.h> #include <dataquay/Node.h> #include <QObject> #include <QMetaType> #include <QString> #include <QStringList> #include <QSharedPointer> #include <QSet> #include <QMutex> #include <QMutexLocker> #include <QMap> #include <iostream> #include "data/fileio/FileSource.h" namespace ClassicalData { //!!! need to review ownership more carefully -- and use deletion notify signals? class Year { public: Year() : m_year(0) { } Year(int y) : m_year(y) { } int toInt() const { return m_year; } operator int() { return m_year; } struct Encoder : public Dataquay::Node::VariantEncoder { QString fromVariant(const QVariant &v) { int y = v.value<Year>().toInt(); if (y == 0) return ""; QString s = QString("%1").arg(y); return s; } QVariant toVariant(const QString &s) { if (s == "") return QVariant::fromValue<Year>(Year()); QVariant v = QVariant::fromValue<Year>(s.toInt()); return v; } }; private: int m_year; }; class HistoricalEvent : public QObject { Q_OBJECT Q_PROPERTY(ClassicalData::Year year READ year WRITE setYear NOTIFY yearChanged STORED true) Q_PROPERTY(QString place READ place WRITE setPlace NOTIFY placeChanged STORED true) Q_PROPERTY(bool approximate READ approximate WRITE setApproximate NOTIFY approximateChanged STORED true) public: HistoricalEvent() : m_year(0), m_place(), m_approximate(false) { } HistoricalEvent(Year y) : m_year(y), m_approximate(false) { } HistoricalEvent(Year y, QString p) : m_year(y), m_place(p), m_approximate(false) { } HistoricalEvent(const HistoricalEvent &h) : QObject(), m_year(h.m_year), m_place(h.m_place), m_approximate(h.m_approximate) { } Year year() const { return m_year; } void setYear(Year y) { m_year = y; emit yearChanged(y); } QString place() const { return m_place; } void setPlace(QString p) { m_place = p; emit placeChanged(p); } bool approximate() const { return m_approximate; } void setApproximate(bool a) { m_approximate = a; emit approximateChanged(a); } signals: void yearChanged(Year); void placeChanged(QString); void approximateChanged(bool); private: Year m_year; QString m_place; bool m_approximate; }; class Birth : public HistoricalEvent { Q_OBJECT public: Birth() : HistoricalEvent() { } Birth(Year y) : HistoricalEvent(y) { } Birth(Year y, QString p) : HistoricalEvent(y, p) { } }; class Death : public HistoricalEvent { Q_OBJECT public: Death() : HistoricalEvent() { } Death(Year y) : HistoricalEvent(y) { } Death(Year y, QString p) : HistoricalEvent(y, p) { } }; class Composer; class Work; class Composition : public HistoricalEvent { Q_OBJECT Q_PROPERTY(ClassicalData::Composer *composer READ composer WRITE setComposer NOTIFY composerChanged STORED true) Q_PROPERTY(QSet<ClassicalData::Work *> works READ works WRITE setWorks NOTIFY worksChanged STORED true) Q_PROPERTY(QString composerName READ getComposerName WRITE setComposerName STORED false) public: Composition() : HistoricalEvent(), m_composer(0) { } Composition(Year y) : HistoricalEvent(y), m_composer(0) { } Composition(Year y, QString p) : HistoricalEvent(y, p), m_composer(0) { } Composer *composer() { return m_composer; } void setComposer(Composer *c) { m_composer = c; emit composerChanged(c); } QSet<Work *> works() { return m_works; } void setWorks(QSet<Work *> c) { m_works = c; emit worksChanged(c); } void addWork(Work *w) { m_works.insert(w); emit worksChanged(m_works); } // Not a storable property; set temporarily while composer record // is found, or else looked up from composer after composer has // been found QString getComposerName() const; void setComposerName(QString n) { m_cname = n; } signals: void composerChanged(Composer *); void worksChanged(QSet<Work *>); private: Composer *m_composer; QSet<Work *> m_works; QString m_cname; }; class Document : public QObject { Q_OBJECT Q_PROPERTY(Dataquay::Uri uri READ uri WRITE setUri NOTIFY uriChanged STORED true) Q_PROPERTY(QString siteName READ siteName WRITE setSiteName NOTIFY siteNameChanged STORED true) Q_PROPERTY(QObject *topic READ topic WRITE setTopic NOTIFY topicChanged STORED true) public: Document(QObject *parent = 0) : QObject(parent), m_topic(0) { } Dataquay::Uri uri() const { return m_uri; } void setUri(Dataquay::Uri uri) { m_uri = uri; emit uriChanged(uri); } QString siteName() const { return m_siteName; } void setSiteName(QString n) { m_siteName = n; emit siteNameChanged(n); } QObject *topic() const { return m_topic; } // I don't own this void setTopic(QObject *t) { m_topic = t; emit topicChanged(t); } signals: void uriChanged(Dataquay::Uri); void siteNameChanged(QString); void topicChanged(QObject *); private: Dataquay::Uri m_uri; QString m_siteName; QObject *m_topic; }; class NamedEntity : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged STORED true) Q_PROPERTY(Dataquay::Uri uri READ uri WRITE setUri NOTIFY uriChanged STORED true) Q_PROPERTY(QSet<QString> aliases READ aliases WRITE setAliases NOTIFY aliasesChanged STORED true) Q_PROPERTY(QString remarks READ remarks WRITE setRemarks NOTIFY remarksChanged STORED true) Q_PROPERTY(QSet<ClassicalData::Document*> pages READ pages WRITE setPages NOTIFY pagesChanged STORED true) Q_PROPERTY(QSet<Dataquay::Uri> otherURIs READ otherURIs WRITE setOtherURIs NOTIFY otherURIsChanged STORED true) public: NamedEntity(QObject *parent = 0) : QObject(parent) { } ~NamedEntity() { } QString name() const { return m_name; } virtual void setName(QString n) { m_name = n; emit nameChanged(n); } Dataquay::Uri uri() const { return m_uri; } void setUri(Dataquay::Uri uri) { m_uri = uri; emit uriChanged(uri); } QString remarks() const { return m_remarks; } void setRemarks(QString n) { m_remarks = n; emit remarksChanged(n); } QSet<QString> aliases() const { return m_aliases; } virtual void setAliases(QSet<QString> l) { m_aliases = l; emit aliasesChanged(l); } virtual void addAlias(QString a) { m_aliases.insert(a); emit aliasesChanged(m_aliases); } QSet<Document *> pages() const { return m_pages; } void addPage(Document *p) { m_pages.insert(p); emit pagesChanged(m_pages); } void setPages(QSet<Document *> p) { m_pages = p; emit pagesChanged(p); } QSet<Dataquay::Uri> otherURIs() const { return m_otherURIs; } void addOtherURI(Dataquay::Uri u) { m_otherURIs.insert(u); emit otherURIsChanged(m_otherURIs); } void setOtherURIs(QSet<Dataquay::Uri> u) { m_otherURIs = u; emit otherURIsChanged(u); } signals: void uriChanged(Dataquay::Uri); void nameChanged(QString); void remarksChanged(QString); void aliasesChanged(QSet<QString>); void pagesChanged(QSet<Document *>); void otherURIsChanged(QSet<Dataquay::Uri>); protected: Dataquay::Uri m_uri; QString m_name; QString m_remarks; QSet<QString> m_aliases; QSet<Document *> m_pages; QSet<Dataquay::Uri> m_otherURIs; }; class Movement; class Form; class Work : public NamedEntity { Q_OBJECT Q_PROPERTY(QString key READ key WRITE setKey NOTIFY keyChanged STORED true) Q_PROPERTY(QString opus READ opus WRITE setOpus NOTIFY opusChanged STORED true) Q_PROPERTY(QString catalogue READ catalogue WRITE setCatalogue NOTIFY catalogueChanged STORED true) Q_PROPERTY(QString number READ number WRITE setNumber NOTIFY numberChanged STORED true) Q_PROPERTY(QSet<ClassicalData::Form*> forms READ forms WRITE setForms NOTIFY formsChanged STORED true) Q_PROPERTY(ClassicalData::Work* partOf READ partOf WRITE setPartOf NOTIFY partOfChanged STORED true) Q_PROPERTY(QSet<ClassicalData::Work*> parts READ parts WRITE setParts NOTIFY partsChanged STORED true) Q_PROPERTY(QSet<ClassicalData::Movement*> movements READ movements WRITE setMovements NOTIFY movementsChanged STORED true) Q_PROPERTY(ClassicalData::Composition *composition READ composition WRITE setComposition NOTIFY compositionChanged STORED true) public: Work(QObject *parent = 0) : NamedEntity(parent), m_partOf(0), m_composition(0) { } QString key() const { return m_key; } void setKey(QString n) { m_key = n; emit keyChanged(n); } /// Should omit Op prefix, e.g. in opus 102 no 2, this would be "102" QString opus() const { return m_opus; } void setOpus(QString n) { m_opus = n; emit opusChanged(n); } /// For part of a catalogue entry, e.g. in opus 102 no 2, this /// would be "2". Should normally be used only with partOf QString number() const { return m_number; } void setNumber(QString n) { m_number = n; emit numberChanged(n); } /// Including catalogue prefix, e.g. "BWV 1066"; only for non-opus numbers QString catalogue() const { return m_catalogue; } void setCatalogue(QString n) { m_catalogue = n; emit catalogueChanged(n); } QSet<Form *> forms() const { return m_forms; } void setForms(QSet<Form *> f) { m_forms = f; emit formsChanged(f); } void addForm(Form *f) { m_forms.insert(f); emit formsChanged(m_forms); } Work *partOf() const { return m_partOf; } void setPartOf(Work *w) { m_partOf = w; emit partOfChanged(w); } QSet<Work *> parts() const { return m_parts; } void setParts(QSet<Work *> l) { m_parts = l; emit partsChanged(l); } void addPart(Work *w) { m_parts.insert(w); emit partsChanged(m_parts); } QSet<Movement *> movements() const { return m_movements; } void setMovements(QSet<Movement *> l) { m_movements = l; emit movementsChanged(l); } void addMovement(Movement *w) { m_movements.insert(w); emit movementsChanged(m_movements); } Composition *composition() { return m_composition; } const Composition *composition() const { return m_composition; } void setComposition(Composition *c) { m_composition = c; emit compositionChanged(c); } Composer *getComposer() const { if (m_composition) { return m_composition->composer(); } else { return 0; } } QString getComposerName() const; struct Ordering { bool operator()(Work *, Work *); }; /** * Compare the ordering of two strings that are known to contain * catalogue number texts, such as "Op. 1 no 4" and "Op. 3 no 2" * (which should compare in that order). Return value is as for * strcmp. */ //!!! todo: unit tests static int compareCatalogueNumberTexts(QString a, QString b); /** * Where data (possibly a title string, including opus number or * equivalent) appears to contain some text of a suitable form for * use with compareCatalogueNumberTexts, extract and return each * example. */ static QStringList extractCatalogueNumberTexts(QString data); /// Return name composed from title and catalogue, e.g. Symphony no. 4, Op. 42 QString getDisplayName() const; signals: void keyChanged(QString); void opusChanged(QString); void catalogueChanged(QString); void numberChanged(QString); void formsChanged(QSet<Form *>); void partOfChanged(Work *); void partsChanged(QSet<Work *>); void movementsChanged(QSet<Movement *>); void compositionChanged(Composition *); private: QString m_key; QString m_opus; QString m_catalogue; QString m_number; QSet<Form *> m_forms; Work *m_partOf; QSet<Work *> m_parts; QSet<Movement *> m_movements; Composition *m_composition; }; class Movement : public NamedEntity { Q_OBJECT Q_PROPERTY(QString key READ key WRITE setKey NOTIFY keyChanged STORED true) Q_PROPERTY(QString number READ number WRITE setNumber NOTIFY numberChanged STORED true) Q_PROPERTY(ClassicalData::Work* partOf READ partOf WRITE setPartOf NOTIFY partOfChanged STORED true) Q_PROPERTY(QSet<ClassicalData::Movement*> parts READ parts WRITE setParts NOTIFY partsChanged STORED true) // movements can be nested Q_PROPERTY(ClassicalData::Composition *composition READ composition WRITE setComposition NOTIFY compositionChanged STORED true) public: Movement(QObject *parent = 0) : NamedEntity(parent), m_partOf(0), m_composition(0) { } QString key() const { return m_key; } void setKey(QString n) { m_key = n; emit keyChanged(n); } QString number() const { return m_number; } void setNumber(QString n) { m_number = n; emit numberChanged(n); } Work *partOf() const { return m_partOf; } void setPartOf(Work *w) { m_partOf = w; emit partOfChanged(w); } QSet<Movement *> parts() const { return m_parts; } void setParts(QSet<Movement *> l) { m_parts = l; emit partsChanged(l); } void addPart(Movement *w) { m_parts.insert(w); emit partsChanged(m_parts); } Composition *composition() { return m_composition; } const Composition *composition() const { return m_composition; } void setComposition(Composition *c) { m_composition = c; emit compositionChanged(c); } signals: void keyChanged(QString); void numberChanged(QString); void partOfChanged(Work *); void partsChanged(QSet<Movement *>); void compositionChanged(Composition *); private: QString m_key; QString m_number; Work *m_partOf; QSet<Movement *> m_parts; Composition *m_composition; }; class Composer : public NamedEntity { Q_OBJECT Q_PROPERTY(QString gender READ gender WRITE setGender NOTIFY genderChanged STORED true) Q_PROPERTY(QSet<QString> nationality READ nationality WRITE setNationality NOTIFY nationalityChanged STORED true) Q_PROPERTY(QSet<Dataquay::Uri> geonameURIs READ geonameURIs WRITE setGeonameURIs NOTIFY geonameURIsChanged STORED true) Q_PROPERTY(QString period READ period WRITE setPeriod NOTIFY periodChanged STORED true) Q_PROPERTY(ClassicalData::Birth *birth READ birth WRITE setBirth NOTIFY birthChanged STORED true) Q_PROPERTY(ClassicalData::Death *death READ death WRITE setDeath NOTIFY deathChanged STORED true) Q_PROPERTY(QString surname READ getSurname STORED false) Q_PROPERTY(QString forenames READ getForenames STORED false) public: Composer(QObject *parent = 0) : NamedEntity(parent), m_birth(0), m_death(0), m_namesCached(false) { } QString gender() const { return m_gender; } void setGender(QString n) { m_gender = n; emit genderChanged(n); } QSet<QString> nationality() const { return m_nationality; } void setNationality(QSet<QString> n) { m_nationality = n; emit nationalityChanged(n); } void addNationality(QString n) { m_nationality.insert(n); emit nationalityChanged(m_nationality); } QSet<Dataquay::Uri> geonameURIs() const { return m_geonameURIs; } void setGeonameURIs(QSet<Dataquay::Uri> n) { m_geonameURIs = n; emit geonameURIsChanged(n); } void addGeonameURI(Dataquay::Uri n) { m_geonameURIs.insert(n); emit geonameURIsChanged(m_geonameURIs); } QString period() const { return m_period; } void setPeriod(QString n) { m_period = n; emit periodChanged(n); } Birth *birth() { return m_birth; } const Birth *birth() const { return m_birth; } void setBirth(Birth *b) { m_birth = b; emit birthChanged(b); } Death *death() { return m_death; } const Death *death() const { return m_death; } void setDeath(Death *d) { m_death = d; emit deathChanged(d); } virtual void setName(QString n) { NamedEntity::setName(n); m_namesCached = false; } virtual void setAliases(QSet<QString> l) { NamedEntity::setAliases(l); m_namesCached = false; } virtual void addAlias(QString a) { NamedEntity::addAlias(a); m_namesCached = false; } QString getSurname() const; QString getForenames() const; QString getSortName(bool caps) const; QString getDisplayDates() const; /** * Given another composer, return true if the other composer's * dates match outs. This is mostly intended (like * matchCatalogueName) for use in merging distinct catalogues. * Matching is somewhat fuzzy; more slack is cut when the dates * are very long ago or are marked as approximate. */ bool matchDates(const Composer *other) const; // "well enough" /** * Given another name which is intended to be a well-formatted * catalogue name for a composer (but which may differ in * ordering, number of forenames, and perhaps in spelling), test * whether the name is a plausible match for our own. This is * mostly intended (like matchDates) for use in merging distinct * catalogues. Return true if the given name is highly likely to * match our own. */ bool matchCatalogueName(QString otherName) const; /** * Given another name which is believed to be a user-entered * composer name with unpredictable formatting and spelling (and * probably incomplete), return an estimate for the likelihood * that the intended composer was this one. Higher return values * indicate greater confidence; a value of 1.0 or more indicates * that all of the input is at least close to perfectly matched. */ float matchFuzzyName(QString name) const; /** * Given another name which is believed to be a user-entered * composer name with unpredictable formatting and spelling (and * probably incomplete), return an estimate for the likelihood * that the intended composer was this one. Higher return values * indicate greater confidence; a value of 1.0 or more indicates * that all of the input is at least close to perfectly matched. * The supplied name should have been lower-cased and split on * non-alphabetical characters. */ float matchFuzzyName(QStringList name) const; /** * Given a string that is in the process of being typed by the * user, return an estimate of the likelihood that the text is * intended to become this composer's name. If quick is true, do * a quick(er) scan only and avoid very expensive tests. */ float matchTyping(QString text) const; /** * Given a string that is in the process of being typed by the * user, return an estimate of the likelihood that the text is * intended to become this composer's name. In contrast to * matchTyping, do a quick(er) scan only, avoiding more expensive * tests. */ float matchTypingQuick(QString text) const; /** * Merge data from the given composer into this composer record. * That is, add the composer's name and aliases as aliases of this * composer, copy its dates where we lack them, etc. In all * cases, values that exist in this composer already are preferred * over values from the "other" composer. */ void mergeFrom(Composer *c); /** * Return the supplied name reduced into a "simplified" form, * eliminating many of the differences often found particularly in * European language names that have been anglicised. Used in * catalogue and fuzzy name matching. */ static QString reduceName(QString name); signals: void genderChanged(QString); void nationalityChanged(QSet<QString>); void geonameURIsChanged(QSet<Dataquay::Uri>); void periodChanged(QString); void birthChanged(Birth *); void deathChanged(Death *); private: QString m_gender; QSet<QString> m_nationality; QSet<Dataquay::Uri> m_geonameURIs; QString m_period; Birth *m_birth; Death *m_death; void cacheNames() const; float doMatchTyping(QString, bool) const; mutable bool m_namesCached; mutable QString m_surname; mutable QString m_forenames; mutable QStringList m_surnameElements; mutable QStringList m_connectiveElements; mutable QStringList m_forenameElements; mutable QStringList m_otherElements; mutable QStringList m_reducedSurnameElements; mutable QStringList m_reducedForenameElements; }; class Form : public NamedEntity { Q_OBJECT Q_PROPERTY(Dataquay::Uri uri READ uri) public: Form(QObject *parent = 0) : NamedEntity(parent) { } static Form *getFormByName(QString name) { QMutexLocker locker(&m_mutex); if (!m_map.contains(name)) { Form *f = new Form(); f->setName(name); m_map[name] = f; } return m_map[name]; } Dataquay::Uri uri() const { return Dataquay::Uri (QString(":form_%1").arg(name()).toLower().replace(' ', '_')); } private: static QMap<QString, Form *> m_map; static QMutex m_mutex; }; class AudioFileTag : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged STORED true) Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged STORED true) public: AudioFileTag(QObject *parent = 0) : QObject(parent) { } AudioFileTag(QString name, QString value, QObject *parent = 0) : QObject(parent), m_name(name), m_value(value) { } QString name() const { return m_name; } void setName(QString n) { m_name = n; emit nameChanged(m_name); } QString value() const { return m_value; } void setValue(QString v) { m_value = v; emit valueChanged(m_value); } signals: void nameChanged(QString); void valueChanged(QString); private: QString m_name; QString m_value; }; // Separate AudioFile and Signal, to correspond with MO class AudioFile : public QObject { Q_OBJECT Q_PROPERTY(QString hash READ hash WRITE setHash NOTIFY hashChanged STORED true) Q_PROPERTY(Dataquay::Uri uri READ uri WRITE setUri NOTIFY uriChanged STORED true) Q_PROPERTY(QSet<ClassicalData::AudioFileTag *> tags READ tags WRITE setTags NOTIFY tagsChanged STORED true) public: AudioFile(QObject *parent = 0); AudioFile(FileSource file, QObject *parent = 0); ~AudioFile(); /// The URI is set automatically from the FileSource at construction Dataquay::Uri uri() const { return m_uri; } void setUri(Dataquay::Uri u) { m_uri = u; emit uriChanged(u); } /// The hash is set automatically from the FileSource at construction QString hash() const { return m_hash; } void setHash(QString hash) { m_hash = hash; emit hashChanged(hash); } /// I take ownership of all tags QSet<AudioFileTag *> tags() { return m_tags; } void setTags(QSet<AudioFileTag *> t); void addTag(AudioFileTag *t); signals: void uriChanged(Dataquay::Uri); void hashChanged(QString); void tagsChanged(QSet<AudioFileTag *>); private: Dataquay::Uri m_uri; QString m_hash; QSet<AudioFileTag *> m_tags; }; class Signal : public QObject { Q_OBJECT Q_PROPERTY(QString ofaFingerprint READ ofaFingerprint WRITE setOfaFingerprint NOTIFY ofaFingerprintChanged STORED true) Q_PROPERTY(QString puid READ puid WRITE setPuid NOTIFY puidChanged STORED true) Q_PROPERTY(QSet<ClassicalData::AudioFile *> availableAs READ availableAs WRITE setAvailableAs NOTIFY availableAsChanged STORED true) Q_PROPERTY(ClassicalData::Composer *composer READ composer WRITE setComposer NOTIFY composerChanged STORED true) Q_PROPERTY(ClassicalData::Work *work READ work WRITE setWork NOTIFY workChanged STORED true) Q_PROPERTY(ClassicalData::Movement *movement READ movement WRITE setMovement NOTIFY movementChanged STORED true) public: Signal() : m_composer(0), m_work(0), m_movement(0) { } QString ofaFingerprint() const { return m_ofaFingerprint; } void setOfaFingerprint(QString fprint) { m_ofaFingerprint = fprint; emit ofaFingerprintChanged(fprint); } QString puid() const { return m_puid; } void setPuid(QString puid) { m_puid = puid; emit puidChanged(puid); } QSet<AudioFile *> availableAs() const { return m_availableAs; } void setAvailableAs(QSet<AudioFile *> aa) { m_availableAs = aa; emit availableAsChanged(m_availableAs); } void addAvailableAs(AudioFile *aa) { m_availableAs.insert(aa); emit availableAsChanged(m_availableAs); } Composer *composer() const { return m_composer; } void setComposer(Composer *c) { m_composer = c; emit composerChanged(c); } Work *work() const { return m_work; } void setWork(Work *w) { m_work = w; emit workChanged(w); } Movement *movement() const { return m_movement; } void setMovement(Movement *m) { m_movement = m; emit movementChanged(m); } signals: void ofaFingerprintChanged(QString); void puidChanged(QString); void composerChanged(Composer *); void workChanged(Work *); void movementChanged(Movement *); void availableAsChanged(QSet<AudioFile *>); private: QString m_ofaFingerprint; QString m_puid; Composer *m_composer; Work *m_work; Movement *m_movement; QSet<AudioFile *> m_availableAs; }; } Q_DECLARE_METATYPE(ClassicalData::Year); Q_DECLARE_METATYPE(ClassicalData::HistoricalEvent*); Q_DECLARE_METATYPE(ClassicalData::Birth*); Q_DECLARE_METATYPE(ClassicalData::Death*); Q_DECLARE_METATYPE(ClassicalData::Composition*); Q_DECLARE_METATYPE(ClassicalData::Work*); Q_DECLARE_METATYPE(ClassicalData::Movement*); Q_DECLARE_METATYPE(ClassicalData::Document*); Q_DECLARE_METATYPE(ClassicalData::AudioFileTag*); Q_DECLARE_METATYPE(ClassicalData::AudioFile*); Q_DECLARE_METATYPE(ClassicalData::Signal*); Q_DECLARE_METATYPE(QSet<QString>); Q_DECLARE_METATYPE(QSet<Dataquay::Uri>); Q_DECLARE_METATYPE(QSet<ClassicalData::Work*>); Q_DECLARE_METATYPE(QSet<ClassicalData::Movement*>); Q_DECLARE_METATYPE(QSet<ClassicalData::Document*>); Q_DECLARE_METATYPE(QSet<ClassicalData::AudioFileTag*>); Q_DECLARE_METATYPE(QSet<ClassicalData::AudioFile*>); Q_DECLARE_METATYPE(QSet<ClassicalData::Signal*>); Q_DECLARE_METATYPE(ClassicalData::Composer*); Q_DECLARE_METATYPE(ClassicalData::Form*); Q_DECLARE_METATYPE(QSet<ClassicalData::Form*>); Q_DECLARE_METATYPE(ClassicalData::NamedEntity*); #endif