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"
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;
}
}

View File

@ -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<QCP::Share>);
#endif // QCP_H

View File

@ -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<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:
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;
}

View File

@ -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);
};

View File

@ -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);
}

View File

@ -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<QString, QString> 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<Avahi::Service>);
QT_BEGIN_NAMESPACE
inline uint qHash(const Avahi::ServiceKey& k) {
return qHash(k.interface ^ k.protocol) ^ qHash(k.name) ^ qHash(k.domain);

View File

@ -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();

View File

@ -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 {