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"
|
#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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
41
libqcp/qcp.h
41
libqcp/qcp.h
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user