Cleanup, fix TXT parsing, add ShareDetails, add UserRole data
This commit is contained in:
parent
7ff39b3e6d
commit
a429d92add
@ -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;
|
||||
}
|
||||
}
|
||||
|
41
libqcp/qcp.h
41
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<QCP::Share>);
|
||||
|
||||
#endif // QCP_H
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user