Cleanup, fix TXT parsing, add ShareDetails, add UserRole data

This commit is contained in:
Stefan Bühler 2010-07-25 14:29:01 +02:00
parent 7ff39b3e6d
commit a429d92add
8 changed files with 122 additions and 30 deletions

View File

@ -3,6 +3,27 @@
#define SERVICETYPE "_qcp._tcp" #define SERVICETYPE "_qcp._tcp"
namespace QCP { 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) Browse::Browse(QObject *parent)
: QObject(parent), m_av_browse(new Avahi::Browse(SERVICETYPE, this)) { : QObject(parent), m_av_browse(new Avahi::Browse(SERVICETYPE, this)) {
connect(m_av_browse, SIGNAL(found(Avahi::Service)), this, SLOT(foundService(Avahi::Service))); 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) { void Browse::foundService(Avahi::Service s) {
ShareDetails *details = createDetails(s);
if (!details) return;
ShareData *sd = new ShareData(); ShareData *sd = new ShareData();
sd->details = details;
s.setData(sd); s.setData(sd);
emit found(Share(this, s)); emit found(Share(s));
} }
void Browse::lostService(Avahi::Service s) { void Browse::lostService(Avahi::Service s) {
emit lost(Share(this, s));
ShareData *sd = shareData(s); ShareData *sd = shareData(s);
if (0 != sd) { if (0 != sd) {
emit lost(Share(s));
sd->data = 0;
delete sd; delete sd;
} }
sd->data = 0;
} }
} }

View File

@ -10,7 +10,7 @@
namespace QCP { namespace QCP {
class LIBQCPSHARED_EXPORT Share; class LIBQCPSHARED_EXPORT Share;
class LIBQCPSHARED_EXPORT WatchShare; class LIBQCPSHARED_EXPORT ShareDetails;
class LIBQCPSHARED_EXPORT Browse; class LIBQCPSHARED_EXPORT Browse;
} }
@ -23,6 +23,7 @@ namespace QCP {
friend class QCP::Share; friend class QCP::Share;
struct ShareData { struct ShareData {
QCP::ShareDetails *details;
void *data; void *data;
}; };
@ -53,24 +54,52 @@ namespace QCP {
Avahi::Browse *m_av_browse; 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 { class LIBQCPSHARED_EXPORT Share {
private: private:
friend class QCP::Browse; friend class QCP::Browse;
friend class QCP::WatchShare;
public: 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: public:
Avahi::Service avahiService() const { return m_service; } Avahi::Service avahiService() const { return m_service; }
void* data() const { Browse::ShareData *sd = Browse::shareData(m_service); return sd ? sd->data : 0; } inline void* data() const {
void setData(void *data) const { Browse::ShareData *sd = Browse::shareData(m_service); if (sd) sd->data = data; } 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: private:
QCP::Browse *m_browse;
Avahi::Service m_service; Avahi::Service m_service;
}; };
} }
Q_DECLARE_METATYPE(QCP::Share);
Q_DECLARE_METATYPE(QList<QCP::Share>);
#endif // QCP_H #endif // QCP_H

View File

@ -11,11 +11,20 @@ namespace QCP {
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
switch (col) { switch (col) {
case 0: return service.hostname(); case 0: return m_service.hostname();
case 1: return QString("%1:%2").arg(service.address().toString()).arg(service.port()); case 1:
case 2: return "Hello World!"; 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: default:
return QVariant(); return QVariant();
} }
@ -34,14 +43,37 @@ namespace QCP {
case Qt::DisplayRole: case Qt::DisplayRole:
switch (col) { 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<Avahi::Service> 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: default:
return QVariant(); return QVariant();
} }
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) { Avahi::model::Entry* EntryList::newEntry(const Avahi::Service &s, void *priv) {
QCP::Share *share = static_cast< QCP::Share* >(priv); QCP::Share *share = static_cast< QCP::Share* >(priv);
return new Entry(this, s, *share); return new Entry(this, s, *share);
@ -80,7 +112,7 @@ namespace QCP {
switch (section) { switch (section) {
case 0: return "Name"; case 0: return "Name";
case 1: return "Address"; case 1: return "Address";
case 2: return "Version"; case 2: return "Method";
} }
break; break;
} }

View File

@ -12,6 +12,8 @@ namespace QCP {
virtual QVariant data(int col, int role); virtual QVariant data(int col, int role);
QCP::Share share() const { return m_share; }
protected: protected:
QCP::Share m_share; QCP::Share m_share;
}; };
@ -24,6 +26,8 @@ namespace QCP {
virtual QVariant data(int col, int role); virtual QVariant data(int col, int role);
QCP::Share share(); /* try to find first share */
protected: protected:
virtual Avahi::model::Entry* newEntry(const Avahi::Service &s, void *priv); virtual Avahi::model::Entry* newEntry(const Avahi::Service &s, void *priv);
}; };

View File

@ -197,15 +197,16 @@ namespace Avahi {
AvahiStringList *psl; AvahiStringList *psl;
for (psl = txt ; psl ; psl = psl->next) { for (psl = txt ; psl ; psl = psl->next) {
QString e = QString::fromUtf8((const char*) psl->text, psl->size), key, value; 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 == 0) continue; /* ignore empty keys */
if (eqPos < -1) { /* "boolean" */ if (eqPos < 0) { /* "boolean" */
key = e; key = e;
} else { } else {
key = e.left(eqPos - 1); key = e.left(eqPos);
value = e.mid(eqPos + 1); value = e.mid(eqPos + 1);
} }
key = key.toLower(); key = key.toLower();
// qDebug() << "Resolver: key = " << key << ", value = " << value;
qtxt.insert(key, value); qtxt.insert(key, value);
} }

View File

@ -82,6 +82,7 @@ namespace Avahi {
protocol = s.m_priv->m_protocol; protocol = s.m_priv->m_protocol;
name = s.m_priv->m_name; name = s.m_priv->m_name;
domain = s.m_priv->m_domain; domain = s.m_priv->m_domain;
txt = s.m_priv->m_txt;
} }
} }
@ -89,6 +90,7 @@ namespace Avahi {
int protocol; /* AvahiProtocol */ int protocol; /* AvahiProtocol */
QString name; QString name;
QString domain; QString domain;
QHash<QString, QString> txt; /* not included in comparisons and hashing, informational only */
}; };
inline bool operator==(const ServiceKey &a, const ServiceKey &b) { inline bool operator==(const ServiceKey &a, const ServiceKey &b) {
@ -184,6 +186,9 @@ namespace Avahi {
} }
Q_DECLARE_METATYPE(Avahi::Service);
Q_DECLARE_METATYPE(QList<Avahi::Service>);
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
inline uint qHash(const Avahi::ServiceKey& k) { inline uint qHash(const Avahi::ServiceKey& k) {
return qHash(k.interface ^ k.protocol) ^ qHash(k.name) ^ qHash(k.domain); return qHash(k.interface ^ k.protocol) ^ qHash(k.name) ^ qHash(k.domain);

View File

@ -130,8 +130,6 @@ namespace Avahi {
beginInsertRows(QModelIndex(), row, row); beginInsertRows(QModelIndex(), row, row);
m_services = tmp; m_services = tmp;
m_root->list.insert(row, el); m_root->list.insert(row, el);
endInsertRows();
beginInsertRows(createIndex(row, 0, (Row*) el), 0, 0);
el->list.push_front(el->newEntry(s, priv)); el->list.push_front(el->newEntry(s, priv));
endInsertRows(); endInsertRows();
} }
@ -145,7 +143,7 @@ namespace Avahi {
for (int i = 0; i < el->list.size(); ++i) { for (int i = 0; i < el->list.size(); ++i) {
Entry *e = dynamic_cast< Entry* >(el->list.value(i)); Entry *e = dynamic_cast< Entry* >(el->list.value(i));
if (e->service == s) { if (e->service() == s) {
/* found service */ /* found service */
if (1 == el->list.size()) { if (1 == el->list.size()) {
@ -160,11 +158,8 @@ namespace Avahi {
m_root->list.removeAt(row); m_root->list.removeAt(row);
endResetModel(); endResetModel();
} else { } else {
beginRemoveRows(createIndex(row, 0, (Row*) el), i, i);
el->list.removeAt(i);
endRemoveRows();
beginRemoveRows(QModelIndex(), row, row); beginRemoveRows(QModelIndex(), row, row);
el->list.removeAt(i);
m_services.remove(k); m_services.remove(k);
m_root->list.removeAt(row); m_root->list.removeAt(row);
endRemoveRows(); endRemoveRows();

View File

@ -45,12 +45,12 @@ namespace Avahi {
class Entry : public Row { class Entry : public Row {
public: 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: protected:
friend class Avahi::BrowseModel; Avahi::Service m_service;
Avahi::Service service;
}; };
class EntryList : public RowList { class EntryList : public RowList {