Chris@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: #ifndef _CLASSICAL_DATA_OBJECTS_H_ Chris@0: #define _CLASSICAL_DATA_OBJECTS_H_ Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: Chris@4: extern unsigned int qHash(const QUrl &u); Chris@4: Chris@0: namespace ClassicalData { Chris@0: Chris@0: class HistoricalEvent : public QObject Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: Q_PROPERTY(int year READ year WRITE setYear STORED true) Chris@0: Q_PROPERTY(QString place READ place WRITE setPlace STORED true) Chris@0: Q_PROPERTY(bool approximate READ approximate WRITE setApproximate STORED true) Chris@0: Chris@0: public: Chris@0: HistoricalEvent() : m_year(0), m_place(), m_approximate(false) { } Chris@0: HistoricalEvent(int y) : m_year(y), m_approximate(false) { } Chris@0: HistoricalEvent(int y, QString p) : m_year(y), m_place(p), m_approximate(false) { } Chris@0: Chris@0: int year() const { return m_year; } Chris@0: void setYear(int y) { m_year = y; } Chris@0: QString place() const { return m_place; } Chris@0: void setPlace(QString p) { m_place = p; } Chris@0: bool approximate() const { return m_approximate; } Chris@0: void setApproximate(bool a) { m_approximate = a; } Chris@0: Chris@0: private: Chris@0: int m_year; Chris@0: QString m_place; Chris@0: bool m_approximate; Chris@0: }; Chris@0: Chris@0: class Birth : public HistoricalEvent Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: public: Chris@0: Birth() : HistoricalEvent() { } Chris@0: Birth(int y) : HistoricalEvent(y) { } Chris@0: Birth(int y, QString p) : HistoricalEvent(y, p) { } Chris@0: }; Chris@0: Chris@0: class Death : public HistoricalEvent Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: public: Chris@0: Death() : HistoricalEvent() { } Chris@0: Death(int y) : HistoricalEvent(y) { } Chris@0: Death(int y, QString p) : HistoricalEvent(y, p) { } Chris@0: }; Chris@0: Chris@0: class Composer; Chris@0: class Work; Chris@0: Chris@0: class Composition : public HistoricalEvent Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: Q_PROPERTY(ClassicalData::Composer *composer READ composer WRITE setComposer STORED true) Chris@0: Q_PROPERTY(QSet works READ works WRITE setWorks STORED true) Chris@0: Q_PROPERTY(QString composerName READ composerName WRITE setComposerName STORED false) Chris@0: Chris@0: public: Chris@0: Composition() : HistoricalEvent(), m_composer(0) { } Chris@0: Composition(int y) : HistoricalEvent(y), m_composer(0) { } Chris@0: Composition(int y, QString p) : HistoricalEvent(y, p), m_composer(0) { } Chris@0: Chris@0: Composer *composer() { return m_composer; } Chris@0: void setComposer(Composer *c) { m_composer = c; } Chris@0: Chris@0: QSet works() { return m_works; } Chris@0: void setWorks(QSet c) { m_works = c; } Chris@0: void addWork(Work *w) { m_works.insert(w); } Chris@0: Chris@0: // Not a storable property, set temporarily while composer record is found Chris@0: QString composerName() const { return m_cname; } Chris@0: void setComposerName(QString n) { m_cname = n; } Chris@0: Chris@0: private: Chris@0: Composer *m_composer; Chris@0: QSet m_works; Chris@0: QString m_cname; Chris@0: }; Chris@0: Chris@0: class Document : public QObject Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: Q_PROPERTY(QUrl uri READ uri WRITE setUri STORED true) Chris@0: Q_PROPERTY(QString siteName READ siteName WRITE setSiteName STORED true) Chris@0: Q_PROPERTY(QObject *topic READ topic WRITE setTopic STORED true) Chris@0: Chris@0: public: Chris@0: Document(QObject *parent = 0) : QObject(parent), m_topic(0) { } Chris@0: Chris@0: QUrl uri() const { return m_uri; } Chris@0: void setUri(QUrl uri) { m_uri = uri; } Chris@0: Chris@0: QString siteName() const { return m_siteName; } Chris@0: void setSiteName(QString n) { m_siteName = n; } Chris@0: Chris@0: QObject *topic() const { return m_topic; } Chris@0: void setTopic(QObject *t) { m_topic = t; } Chris@0: Chris@0: private: Chris@0: QUrl m_uri; Chris@0: QString m_siteName; Chris@0: QObject *m_topic; Chris@0: }; Chris@0: Chris@0: Chris@0: class NamedEntity : public QObject Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: Q_PROPERTY(QString name READ name WRITE setName STORED true) Chris@0: Q_PROPERTY(QSet aliases READ aliases WRITE setAliases STORED true) Chris@0: Q_PROPERTY(QString remarks READ remarks WRITE setRemarks STORED true) Chris@0: Q_PROPERTY(QSet pages READ pages WRITE setPages STORED true) Chris@0: Chris@0: public: Chris@0: NamedEntity(QObject *parent = 0) : QObject(parent) { } Chris@0: Chris@0: QString name() const { return m_name; } Chris@11: virtual void setName(QString n) { m_name = n; } Chris@0: Chris@0: QString remarks() const { return m_remarks; } Chris@0: void setRemarks(QString n) { m_remarks = n; } Chris@0: Chris@0: QSet aliases() const { return m_aliases; } Chris@11: virtual void setAliases(QSet l) { m_aliases = l; } Chris@11: virtual void addAlias(QString a) { m_aliases.insert(a); } Chris@0: Chris@0: QSet pages() const { return m_pages; } Chris@0: void addPage(Document *p) { m_pages.insert(p); } Chris@0: void setPages(QSet p) { m_pages = p; } //!!! destroy old ones? do we own? Chris@0: Chris@11: protected: Chris@0: QString m_name; Chris@0: QString m_remarks; Chris@0: QSet m_aliases; Chris@0: QSet m_pages; Chris@0: }; Chris@0: Chris@0: class Movement; Chris@0: Chris@0: class Form; Chris@0: Chris@0: class Work : public NamedEntity Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: Q_PROPERTY(QString key READ key WRITE setKey STORED true) Chris@0: Q_PROPERTY(QString opus READ opus WRITE setOpus STORED true) Chris@0: Q_PROPERTY(QString catalogue READ catalogue WRITE setCatalogue STORED true) Chris@0: Q_PROPERTY(QString number READ number WRITE setNumber STORED true) Chris@0: Q_PROPERTY(QSet forms READ forms WRITE setForms STORED true) Chris@0: Q_PROPERTY(ClassicalData::Work* partOf READ partOf WRITE setPartOf STORED true) Chris@0: Q_PROPERTY(QSet parts READ parts WRITE setParts STORED true) Chris@0: Q_PROPERTY(QSet movements READ movements WRITE setMovements STORED true) Chris@0: Q_PROPERTY(ClassicalData::Composition *composition READ composition WRITE setComposition STORED true) Chris@0: Chris@0: public: Chris@0: Work(QObject *parent = 0) : NamedEntity(parent), m_partOf(0), m_composition(0) { } Chris@0: Chris@0: QString key() const { return m_key; } Chris@0: void setKey(QString n) { m_key = n; } Chris@0: Chris@0: QString opus() const { return m_opus; } Chris@0: void setOpus(QString n) { m_opus = n; } Chris@0: Chris@0: QString catalogue() const { return m_catalogue; } Chris@0: void setCatalogue(QString n) { m_catalogue = n; } Chris@0: Chris@0: QString number() const { return m_number; } Chris@0: void setNumber(QString n) { m_number = n; } Chris@0: Chris@0: QSet
forms() const { return m_forms; } Chris@0: void setForms(QSet f) { m_forms = f; } Chris@0: void addForm(Form *f) { m_forms.insert(f); } Chris@0: Chris@0: Work *partOf() const { return m_partOf; } Chris@0: void setPartOf(Work *w) { m_partOf = w; } Chris@0: Chris@0: QSet parts() const { return m_parts; } Chris@0: void setParts(QSet l) { m_parts = l; } Chris@0: void addPart(Work *w) { m_parts.insert(w); } Chris@0: Chris@0: QSet movements() const { return m_movements; } Chris@0: void setMovements(QSet l) { m_movements = l; } Chris@0: void addMovement(Movement *w) { m_movements.insert(w); } Chris@0: Chris@0: Composition *composition() { return m_composition; } Chris@0: const Composition *composition() const { return m_composition; } Chris@0: void setComposition(Composition *c) { m_composition = c; } Chris@0: Chris@0: struct Ordering { Chris@0: bool operator()(Work *, Work *); Chris@0: }; Chris@0: Chris@10: /** Chris@10: * Compare the ordering of two strings that are known to contain Chris@10: * catalogue number texts, such as "Op. 1 no 4" and "Op. 3 no 2" Chris@10: * (which should compare in that order). Return value is as for Chris@10: * strcmp. Chris@10: */ Chris@10: //!!! todo: unit tests Chris@10: static int compareCatalogueNumberTexts(QString a, QString b); Chris@10: Chris@0: private: Chris@0: QString m_key; Chris@0: QString m_opus; Chris@0: QString m_catalogue; Chris@0: QString m_number; Chris@0: QSet m_forms; Chris@0: Work *m_partOf; Chris@0: QSet m_parts; Chris@0: QSet m_movements; Chris@0: Composition *m_composition; Chris@0: }; Chris@0: Chris@0: class Movement : public NamedEntity Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: Q_PROPERTY(QString key READ key WRITE setKey STORED true) Chris@0: Q_PROPERTY(QString number READ number WRITE setNumber STORED true) Chris@0: Q_PROPERTY(ClassicalData::Work* partOf READ partOf WRITE setPartOf STORED true) Chris@0: Q_PROPERTY(QSet parts READ parts WRITE setParts STORED true) // movements can be nested Chris@0: Q_PROPERTY(ClassicalData::Composition *composition READ composition WRITE setComposition STORED true) Chris@0: Chris@0: public: Chris@0: Movement(QObject *parent = 0) : NamedEntity(parent), m_partOf(0), m_composition(0) { } Chris@0: Chris@0: QString key() const { return m_key; } Chris@0: void setKey(QString n) { m_key = n; } Chris@0: Chris@0: QString number() const { return m_number; } Chris@0: void setNumber(QString n) { m_number = n; } Chris@0: Chris@0: Work *partOf() const { return m_partOf; } Chris@0: void setPartOf(Work *w) { m_partOf = w; } Chris@0: Chris@0: QSet parts() const { return m_parts; } Chris@0: void setParts(QSet l) { m_parts = l; } Chris@0: void addPart(Movement *w) { m_parts.insert(w); } Chris@0: Chris@0: Composition *composition() { return m_composition; } Chris@0: const Composition *composition() const { return m_composition; } Chris@0: void setComposition(Composition *c) { m_composition = c; } Chris@0: Chris@0: private: Chris@0: QString m_key; Chris@0: QString m_number; Chris@0: Work *m_partOf; Chris@0: QSet m_parts; Chris@0: Composition *m_composition; Chris@0: }; Chris@0: Chris@0: class Composer : public NamedEntity Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: Q_PROPERTY(QString gender READ gender WRITE setGender STORED true) Chris@4: Q_PROPERTY(QSet nationality READ nationality WRITE setNationality STORED true) Chris@4: Q_PROPERTY(QSet geonameURIs READ geonameURIs WRITE setGeonameURIs STORED true) Chris@0: Q_PROPERTY(QString period READ period WRITE setPeriod STORED true) Chris@0: Q_PROPERTY(ClassicalData::Birth *birth READ birth WRITE setBirth STORED true) Chris@0: Q_PROPERTY(ClassicalData::Death *death READ death WRITE setDeath STORED true) Chris@0: Chris@10: Q_PROPERTY(QString surname READ getSurname STORED false) Chris@10: Q_PROPERTY(QString forenames READ getForenames STORED false) Chris@10: Chris@0: public: Chris@11: Composer(QObject *parent = 0) : Chris@11: NamedEntity(parent), m_birth(0), m_death(0), m_namesCached(false) { } Chris@0: Chris@0: QString gender() const { return m_gender; } Chris@0: void setGender(QString n) { m_gender = n; } Chris@0: Chris@4: QSet nationality() const { return m_nationality; } Chris@4: void setNationality(QSet n) { m_nationality = n; } Chris@4: void addNationality(QString n) { m_nationality.insert(n); } Chris@4: Chris@4: QSet geonameURIs() const { return m_geonameURIs; } Chris@4: void setGeonameURIs(QSet n) { m_geonameURIs = n; } Chris@4: void addGeonameURI(QUrl n) { m_geonameURIs.insert(n); } Chris@0: Chris@0: QString period() const { return m_period; } Chris@0: void setPeriod(QString n) { m_period = n; } Chris@0: Chris@0: Birth *birth() { return m_birth; } Chris@0: const Birth *birth() const { return m_birth; } Chris@0: void setBirth(Birth *b) { m_birth = b; } Chris@0: Chris@0: Death *death() { return m_death; } Chris@0: const Death *death() const { return m_death; } Chris@0: void setDeath(Death *d) { m_death = d; } Chris@0: Chris@11: virtual void setName(QString n) { Chris@11: NamedEntity::setName(n); Chris@11: m_namesCached = false; Chris@11: } Chris@11: virtual void setAliases(QSet l) { Chris@11: NamedEntity::setAliases(l); Chris@11: m_namesCached = false; Chris@11: } Chris@11: virtual void addAlias(QString a) { Chris@11: NamedEntity::addAlias(a); Chris@11: m_namesCached = false; Chris@11: } Chris@11: Chris@10: QString getSurname() const; Chris@10: QString getForenames() const; Chris@0: QString getSortName(bool caps) const; Chris@0: QString getDisplayDates() const; Chris@0: Chris@10: /** Chris@10: * Given another composer, return true if the other composer's Chris@10: * dates match outs. This is mostly intended (like Chris@10: * matchCatalogueName) for use in merging distinct catalogues. Chris@10: * Matching is somewhat fuzzy; more slack is cut when the dates Chris@10: * are very long ago or are marked as approximate. Chris@10: */ Chris@10: bool matchDates(const Composer *other) const; // "well enough" Chris@10: Chris@10: /** Chris@10: * Given another name which is intended to be a well-formatted Chris@10: * catalogue name for a composer (but which may differ in Chris@10: * ordering, number of forenames, and perhaps in spelling), test Chris@10: * whether the name is a plausible match for our own. This is Chris@10: * mostly intended (like matchDates) for use in merging distinct Chris@10: * catalogues. Return true if the given name is highly likely to Chris@10: * match our own. Chris@10: */ Chris@10: bool matchCatalogueName(QString otherName) const; Chris@10: Chris@10: /** Chris@10: * Given another name which is believed to be a user-entered Chris@10: * composer name with unpredictable formatting and spelling (and Chris@10: * probably incomplete), return an estimate for the likelihood Chris@10: * that the intended composer was this one. Higher return values Chris@10: * indicate greater confidence. Chris@10: */ Chris@10: int matchFuzzyName(QString name) const; Chris@10: Chris@10: /** Chris@10: * Return the supplied name reduced into a "simplified" form, Chris@10: * eliminating many of the differences often found particularly in Chris@10: * European language names that have been anglicised. Used in Chris@10: * catalogue and fuzzy name matching. Chris@10: */ Chris@10: static QString reduceName(QString name); Chris@10: Chris@0: private: Chris@0: QString m_gender; Chris@4: QSet m_nationality; Chris@4: QSet m_geonameURIs; Chris@0: QString m_period; Chris@0: Birth *m_birth; Chris@0: Death *m_death; Chris@11: Chris@11: void cacheNames() const; Chris@11: mutable bool m_namesCached; Chris@11: mutable QString m_surname; Chris@11: mutable QString m_forenames; Chris@11: mutable QStringList m_surnameElements; Chris@11: mutable QStringList m_connectiveElements; Chris@11: mutable QStringList m_forenameElements; Chris@11: mutable QStringList m_otherElements; Chris@11: mutable QStringList m_reducedSurnameElements; Chris@11: mutable QStringList m_reducedForenameElements; Chris@0: }; Chris@0: Chris@0: class Form : public NamedEntity Chris@0: { Chris@0: Q_OBJECT Chris@0: Chris@0: Q_PROPERTY(QString uri READ uri) Chris@0: Chris@0: public: Chris@0: Form(QObject *parent = 0) : NamedEntity(parent) { } Chris@0: Chris@0: static Form *getFormByName(QString name) { Chris@0: QMutexLocker locker(&m_mutex); Chris@0: if (!m_map.contains(name)) { Chris@0: Form *f = new Form(); Chris@0: f->setName(name); Chris@0: m_map[name] = f; Chris@0: } Chris@0: return m_map[name]; Chris@0: } Chris@0: Chris@0: QString uri() const { Chris@0: return QString(":form_%1").arg(name()).toLower().replace(' ', '_'); Chris@0: } Chris@0: Chris@0: private: Chris@0: static QMap m_map; Chris@0: static QMutex m_mutex; Chris@0: }; Chris@0: Chris@0: } Chris@0: Chris@0: Q_DECLARE_METATYPE(ClassicalData::HistoricalEvent*); Chris@0: Q_DECLARE_METATYPE(ClassicalData::Birth*); Chris@0: Q_DECLARE_METATYPE(ClassicalData::Death*); Chris@0: Q_DECLARE_METATYPE(ClassicalData::Composition*); Chris@0: Q_DECLARE_METATYPE(ClassicalData::Work*); Chris@0: Q_DECLARE_METATYPE(ClassicalData::Movement*); Chris@0: Q_DECLARE_METATYPE(ClassicalData::Document*); Chris@0: Q_DECLARE_METATYPE(QSet); Chris@4: Q_DECLARE_METATYPE(QSet); Chris@0: Q_DECLARE_METATYPE(QSet); Chris@0: Q_DECLARE_METATYPE(QSet); Chris@0: Q_DECLARE_METATYPE(QSet); Chris@0: Q_DECLARE_METATYPE(ClassicalData::Composer*); Chris@0: Q_DECLARE_METATYPE(ClassicalData::Form*); Chris@0: Q_DECLARE_METATYPE(QSet); Chris@0: Chris@0: #endif