diff --git a/libqcp/qcp.cpp b/libqcp/qcp.cpp index cf06f6d..c4e7bf6 100644 --- a/libqcp/qcp.cpp +++ b/libqcp/qcp.cpp @@ -3,6 +3,27 @@ #define SERVICETYPE "_qcp._tcp" namespace QCP { + + class ShareFile : public QCP::ShareDetails { + public: + ShareFile(const Avahi::Service &s) : ShareDetails(s) { + } + + virtual QString methodName() { return "File"; } + }; + + + QCP::ShareDetails *createDetails(const Avahi::Service &s) { + QString methodName = s.txt("m"); + + if (methodName == "file") { + return new ShareFile(s); + } + + qDebug() << "Unknown share method: " << methodName; + return 0; + } + Browse::Browse(QObject *parent) : QObject(parent), m_av_browse(new Avahi::Browse(SERVICETYPE, this)) { connect(m_av_browse, SIGNAL(found(Avahi::Service)), this, SLOT(foundService(Avahi::Service))); @@ -12,17 +33,22 @@ namespace QCP { } void Browse::foundService(Avahi::Service s) { + ShareDetails *details = createDetails(s); + if (!details) return; + ShareData *sd = new ShareData(); + sd->details = details; + s.setData(sd); - emit found(Share(this, s)); + emit found(Share(s)); } void Browse::lostService(Avahi::Service s) { - emit lost(Share(this, s)); ShareData *sd = shareData(s); if (0 != sd) { + emit lost(Share(s)); + sd->data = 0; delete sd; } - sd->data = 0; } } diff --git a/libqcp/qcp.h b/libqcp/qcp.h index 2aef16b..6e1fd0b 100644 --- a/libqcp/qcp.h +++ b/libqcp/qcp.h @@ -10,7 +10,7 @@ namespace QCP { class LIBQCPSHARED_EXPORT Share; - class LIBQCPSHARED_EXPORT WatchShare; + class LIBQCPSHARED_EXPORT ShareDetails; class LIBQCPSHARED_EXPORT Browse; } @@ -23,6 +23,7 @@ namespace QCP { friend class QCP::Share; struct ShareData { + QCP::ShareDetails *details; void *data; }; @@ -53,24 +54,52 @@ namespace QCP { Avahi::Browse *m_av_browse; }; + class LIBQCPSHARED_EXPORT ShareDetails { + protected: + ShareDetails(const Avahi::Service &service) : m_service(service) { } + + public: + virtual ~ShareDetails() { } + + virtual QString methodName() = 0; + + Avahi::Service service() const { return m_service; } + + protected: + Avahi::Service m_service; + }; + class LIBQCPSHARED_EXPORT Share { private: friend class QCP::Browse; - friend class QCP::WatchShare; public: - inline Share(QCP::Browse *browse, Avahi::Service service) : m_browse(browse), m_service(service) { } + inline Share(Avahi::Service service) : m_service(service) { } + inline Share() { } public: Avahi::Service avahiService() const { return m_service; } - void* data() const { Browse::ShareData *sd = Browse::shareData(m_service); return sd ? sd->data : 0; } - void setData(void *data) const { Browse::ShareData *sd = Browse::shareData(m_service); if (sd) sd->data = data; } + inline void* data() const { + Browse::ShareData *sd = Browse::shareData(m_service); + return sd ? sd->data : 0; + } + inline void setData(void *data) const { + Browse::ShareData *sd = Browse::shareData(m_service); + if (sd) sd->data = data; + } + + inline QCP::ShareDetails* details() const { + Browse::ShareData *sd = Browse::shareData(m_service); + return sd ? sd->details : 0; + } private: - QCP::Browse *m_browse; Avahi::Service m_service; }; } +Q_DECLARE_METATYPE(QCP::Share); +Q_DECLARE_METATYPE(QList); + #endif // QCP_H diff --git a/libqcp/qcpmodel.cpp b/libqcp/qcpmodel.cpp index d633b12..08ed258 100644 --- a/libqcp/qcpmodel.cpp +++ b/libqcp/qcpmodel.cpp @@ -11,11 +11,20 @@ namespace QCP { switch (role) { case Qt::DisplayRole: switch (col) { - case 0: return service.hostname(); - case 1: return QString("%1:%2").arg(service.address().toString()).arg(service.port()); - case 2: return "Hello World!"; + case 0: return m_service.hostname(); + case 1: + if (m_service.address().protocol() == QAbstractSocket::IPv6Protocol) { + QString scope = m_service.address().scopeId(); + if (!scope.isEmpty()) scope = "%" + scope; + return QString("[%1%2]:%3").arg(m_service.address().toString(), scope).arg(m_service.port()); + } else { + return QString("%1:%2").arg(m_service.address().toString()).arg(m_service.port()); + } } - // case Qt::UserRole + break; + case Qt::UserRole: + return qVariantFromValue(m_service); + break; default: return QVariant(); } @@ -33,15 +42,38 @@ namespace QCP { switch (role) { case Qt::DisplayRole: switch (col) { - case 0: return key.name; + case 0: return key.name; + case 2: { + ShareDetails *d = share().details(); + if (d) return d->methodName(); + } } - // case Qt::UserRole + break; + case Qt::UserRole: { + QList l; + for (int i = 0; i < list.length(); i++) { + Entry *e = dynamic_cast< Entry* >(list.at(i)); + if (!e) continue; + l.append(e->service()); + } + return qVariantFromValue(l); + } + break; default: return QVariant(); } return QVariant(); } + QCP::Share EntryList::share() { /* try to find first share */ + for (int i = 0; i < list.length(); i++) { + Entry *e = dynamic_cast< Entry* >(list.at(i)); + if (!e) continue; + return e->share(); + } + return QCP::Share(); + } + Avahi::model::Entry* EntryList::newEntry(const Avahi::Service &s, void *priv) { QCP::Share *share = static_cast< QCP::Share* >(priv); return new Entry(this, s, *share); @@ -80,7 +112,7 @@ namespace QCP { switch (section) { case 0: return "Name"; case 1: return "Address"; - case 2: return "Version"; + case 2: return "Method"; } break; } diff --git a/libqcp/qcpmodel.h b/libqcp/qcpmodel.h index e82543a..bc6dcc7 100644 --- a/libqcp/qcpmodel.h +++ b/libqcp/qcpmodel.h @@ -12,6 +12,8 @@ namespace QCP { virtual QVariant data(int col, int role); + QCP::Share share() const { return m_share; } + protected: QCP::Share m_share; }; @@ -24,6 +26,8 @@ namespace QCP { virtual QVariant data(int col, int role); + QCP::Share share(); /* try to find first share */ + protected: virtual Avahi::model::Entry* newEntry(const Avahi::Service &s, void *priv); }; diff --git a/libqtavahi/qtavahi.cpp b/libqtavahi/qtavahi.cpp index 09f9ea7..8de9ed7 100644 --- a/libqtavahi/qtavahi.cpp +++ b/libqtavahi/qtavahi.cpp @@ -197,15 +197,16 @@ namespace Avahi { AvahiStringList *psl; for (psl = txt ; psl ; psl = psl->next) { QString e = QString::fromUtf8((const char*) psl->text, psl->size), key, value; - int eqPos = e.indexOf(QChar('"')); + int eqPos = e.indexOf(QChar('=')); if (eqPos == 0) continue; /* ignore empty keys */ - if (eqPos < -1) { /* "boolean" */ + if (eqPos < 0) { /* "boolean" */ key = e; } else { - key = e.left(eqPos - 1); + key = e.left(eqPos); value = e.mid(eqPos + 1); } key = key.toLower(); + // qDebug() << "Resolver: key = " << key << ", value = " << value; qtxt.insert(key, value); } diff --git a/libqtavahi/qtavahi.h b/libqtavahi/qtavahi.h index aca8981..cf6d5b9 100644 --- a/libqtavahi/qtavahi.h +++ b/libqtavahi/qtavahi.h @@ -82,6 +82,7 @@ namespace Avahi { protocol = s.m_priv->m_protocol; name = s.m_priv->m_name; domain = s.m_priv->m_domain; + txt = s.m_priv->m_txt; } } @@ -89,6 +90,7 @@ namespace Avahi { int protocol; /* AvahiProtocol */ QString name; QString domain; + QHash txt; /* not included in comparisons and hashing, informational only */ }; inline bool operator==(const ServiceKey &a, const ServiceKey &b) { @@ -184,6 +186,9 @@ namespace Avahi { } +Q_DECLARE_METATYPE(Avahi::Service); +Q_DECLARE_METATYPE(QList); + QT_BEGIN_NAMESPACE inline uint qHash(const Avahi::ServiceKey& k) { return qHash(k.interface ^ k.protocol) ^ qHash(k.name) ^ qHash(k.domain); diff --git a/libqtavahi/qtavahimodel.cpp b/libqtavahi/qtavahimodel.cpp index 00d12ec..ae556cf 100644 --- a/libqtavahi/qtavahimodel.cpp +++ b/libqtavahi/qtavahimodel.cpp @@ -130,8 +130,6 @@ namespace Avahi { beginInsertRows(QModelIndex(), row, row); m_services = tmp; m_root->list.insert(row, el); - endInsertRows(); - beginInsertRows(createIndex(row, 0, (Row*) el), 0, 0); el->list.push_front(el->newEntry(s, priv)); endInsertRows(); } @@ -145,7 +143,7 @@ namespace Avahi { for (int i = 0; i < el->list.size(); ++i) { Entry *e = dynamic_cast< Entry* >(el->list.value(i)); - if (e->service == s) { + if (e->service() == s) { /* found service */ if (1 == el->list.size()) { @@ -160,11 +158,8 @@ namespace Avahi { m_root->list.removeAt(row); endResetModel(); } else { - beginRemoveRows(createIndex(row, 0, (Row*) el), i, i); - el->list.removeAt(i); - endRemoveRows(); - beginRemoveRows(QModelIndex(), row, row); + el->list.removeAt(i); m_services.remove(k); m_root->list.removeAt(row); endRemoveRows(); diff --git a/libqtavahi/qtavahimodel.h b/libqtavahi/qtavahimodel.h index 8c10712..363ff3c 100644 --- a/libqtavahi/qtavahimodel.h +++ b/libqtavahi/qtavahimodel.h @@ -45,12 +45,12 @@ namespace Avahi { class Entry : public Row { public: - Entry(Row *parent, const Avahi::Service &s) : Row(parent), service(s) { } + Entry(Row *parent, const Avahi::Service &s) : Row(parent), m_service(s) { } + + inline Avahi::Service service() const { return m_service; } protected: - friend class Avahi::BrowseModel; - - Avahi::Service service; + Avahi::Service m_service; }; class EntryList : public RowList {