Merge pull request #789 from PhenomRetroShare/Add_FriendTimeOffsetNewsFeed

Add Friend Time Offset news feed.
This commit is contained in:
csoler 2017-04-30 22:43:10 +02:00 committed by GitHub
commit 3d17d31e49
9 changed files with 172 additions and 42 deletions

View File

@ -78,15 +78,16 @@ const uint32_t RS_FEED_TYPE_SECURITY = 0x0800;
const uint32_t RS_FEED_TYPE_POSTED = 0x1000; const uint32_t RS_FEED_TYPE_POSTED = 0x1000;
const uint32_t RS_FEED_TYPE_SECURITY_IP = 0x2000; const uint32_t RS_FEED_TYPE_SECURITY_IP = 0x2000;
const uint32_t RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001; const uint32_t RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001;
const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002; const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002;
const uint32_t RS_FEED_ITEM_PEER_HELLO = RS_FEED_TYPE_PEER | 0x0003; const uint32_t RS_FEED_ITEM_PEER_HELLO = RS_FEED_TYPE_PEER | 0x0003;
const uint32_t RS_FEED_ITEM_PEER_NEW = RS_FEED_TYPE_PEER | 0x0004; const uint32_t RS_FEED_ITEM_PEER_NEW = RS_FEED_TYPE_PEER | 0x0004;
const uint32_t RS_FEED_ITEM_PEER_OFFSET = RS_FEED_TYPE_PEER | 0x0005;
const uint32_t RS_FEED_ITEM_SEC_CONNECT_ATTEMPT = RS_FEED_TYPE_SECURITY | 0x0001; const uint32_t RS_FEED_ITEM_SEC_CONNECT_ATTEMPT = RS_FEED_TYPE_SECURITY | 0x0001;
const uint32_t RS_FEED_ITEM_SEC_AUTH_DENIED = RS_FEED_TYPE_SECURITY | 0x0002; const uint32_t RS_FEED_ITEM_SEC_AUTH_DENIED = RS_FEED_TYPE_SECURITY | 0x0002;
const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_IN = RS_FEED_TYPE_SECURITY | 0x0003; const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_IN = RS_FEED_TYPE_SECURITY | 0x0003;
const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_OUT = RS_FEED_TYPE_SECURITY | 0x0004; const uint32_t RS_FEED_ITEM_SEC_UNKNOWN_OUT = RS_FEED_TYPE_SECURITY | 0x0004;
const uint32_t RS_FEED_ITEM_SEC_WRONG_SIGNATURE = RS_FEED_TYPE_SECURITY | 0x0005; const uint32_t RS_FEED_ITEM_SEC_WRONG_SIGNATURE = RS_FEED_TYPE_SECURITY | 0x0005;
const uint32_t RS_FEED_ITEM_SEC_BAD_CERTIFICATE = RS_FEED_TYPE_SECURITY | 0x0006; const uint32_t RS_FEED_ITEM_SEC_BAD_CERTIFICATE = RS_FEED_TYPE_SECURITY | 0x0006;
const uint32_t RS_FEED_ITEM_SEC_INTERNAL_ERROR = RS_FEED_TYPE_SECURITY | 0x0007; const uint32_t RS_FEED_ITEM_SEC_INTERNAL_ERROR = RS_FEED_TYPE_SECURITY | 0x0007;

View File

@ -2,7 +2,7 @@
#define RETROSHARE_RTT_INTERFACE_H #define RETROSHARE_RTT_INTERFACE_H
/* /*
* libretroshare/src/retroshare: rsrtt.h * libretroshare/src/retroshare: rsrtt.h
* *
* RetroShare C++ Interface. * RetroShare C++ Interface.
* *
@ -58,6 +58,7 @@ class RsRtt
virtual ~RsRtt() { return; } virtual ~RsRtt() { return; }
virtual uint32_t getPongResults(const RsPeerId& id, int n, std::list<RsRttPongResult> &results) = 0; virtual uint32_t getPongResults(const RsPeerId& id, int n, std::list<RsRttPongResult> &results) = 0;
virtual double getMeanOffset(const RsPeerId& id) = 0;
}; };

View File

@ -30,11 +30,13 @@
#include "pqi/pqibin.h" #include "pqi/pqibin.h"
#include "pqi/pqistore.h" #include "pqi/pqistore.h"
#include "pqi/p3linkmgr.h" #include "pqi/p3linkmgr.h"
#include "rsserver/p3face.h"
#include "services/p3rtt.h" #include "services/p3rtt.h"
#include "serialiser/rsrttitems.h" #include "serialiser/rsrttitems.h"
#include <sys/time.h> #include <sys/time.h>
#include <math.h>
/**** /****
* #define DEBUG_RTT 1 * #define DEBUG_RTT 1
@ -358,7 +360,26 @@ int p3rtt::storePongResult(const RsPeerId& id, uint32_t counter, double recv_ts,
peerInfo->mPongResults.pop_front(); peerInfo->mPongResults.pop_front();
} }
/* should do calculations */ //Wait at least 20 pongs before compute mean time offset
if(peerInfo->mPongResults.size() > 20)
{
double mean = 0;
for(std::list<RsRttPongResult>::const_iterator prIt = peerInfo->mPongResults.begin(), end = peerInfo->mPongResults.end(); prIt != end; ++ prIt)
{
mean += prIt->mOffset;
}
peerInfo->mCurrentMeanOffset = mean / peerInfo->mPongResults.size();
if(fabs(peerInfo->mCurrentMeanOffset) > 120)
{
p3Notify *notify = RsServer::notify();
if (notify)
{
//notify->AddPopupMessage(RS_POPUP_OFFSET, eerInfo->mId.toStdString(),"", "Time Offset: ");
notify->AddFeedItem(RS_FEED_ITEM_PEER_OFFSET, peerInfo->mId.toStdString());
}
std::cerr << "(WW) Peer:" << peerInfo->mId << " get time offset more than two minutes with you!!!" << std::endl;
}
}
return 1; return 1;
} }
@ -379,7 +400,16 @@ uint32_t p3rtt::getPongResults(const RsPeerId& id, int n, std::list<RsRttPongRes
return i ; return i ;
} }
double p3rtt::getMeanOffset(const RsPeerId &id)
{
RsStackMutex stack(mRttMtx); /****** LOCKED MUTEX *******/
RttPeerInfo *peer = locked_GetPeerInfo(id);
if(peer)
return peer->mCurrentMeanOffset;
else
return 0;
}
RttPeerInfo *p3rtt::locked_GetPeerInfo(const RsPeerId& id) RttPeerInfo *p3rtt::locked_GetPeerInfo(const RsPeerId& id)
{ {

View File

@ -46,6 +46,7 @@ class RttPeerInfo
double mCurrentPingTS; double mCurrentPingTS;
double mCurrentPingCounter; double mCurrentPingCounter;
bool mCurrentPongRecvd; bool mCurrentPongRecvd;
double mCurrentMeanOffset;
uint32_t mLostPongs; uint32_t mLostPongs;
uint32_t mSentPings; uint32_t mSentPings;
@ -69,6 +70,7 @@ virtual RsServiceInfo getServiceInfo();
/***** overloaded from rsRtt *****/ /***** overloaded from rsRtt *****/
virtual uint32_t getPongResults(const RsPeerId& id, int n, std::list<RsRttPongResult> &results); virtual uint32_t getPongResults(const RsPeerId& id, int n, std::list<RsRttPongResult> &results);
virtual double getMeanOffset(const RsPeerId &id);
/***** overloaded from p3Service *****/ /***** overloaded from p3Service *****/

View File

@ -217,13 +217,17 @@ void NewsFeed::updateDisplay()
if (flags & RS_FEED_TYPE_PEER) if (flags & RS_FEED_TYPE_PEER)
addFeedItemPeerDisconnect(fi); addFeedItemPeerDisconnect(fi);
break; break;
case RS_FEED_ITEM_PEER_HELLO:
if (flags & RS_FEED_TYPE_PEER)
addFeedItemPeerHello(fi);
break;
case RS_FEED_ITEM_PEER_NEW: case RS_FEED_ITEM_PEER_NEW:
if (flags & RS_FEED_TYPE_PEER) if (flags & RS_FEED_TYPE_PEER)
addFeedItemPeerNew(fi); addFeedItemPeerNew(fi);
break; break;
case RS_FEED_ITEM_PEER_HELLO: case RS_FEED_ITEM_PEER_OFFSET:
if (flags & RS_FEED_TYPE_PEER) if (flags & RS_FEED_TYPE_PEER)
addFeedItemPeerHello(fi); addFeedItemPeerOffset(fi);
break; break;
case RS_FEED_ITEM_SEC_CONNECT_ATTEMPT: case RS_FEED_ITEM_SEC_CONNECT_ATTEMPT:
@ -412,8 +416,9 @@ void NewsFeed::testFeeds(uint notifyFlags)
instance->addFeedItemPeerConnect(fi); instance->addFeedItemPeerConnect(fi);
instance->addFeedItemPeerDisconnect(fi); instance->addFeedItemPeerDisconnect(fi);
instance->addFeedItemPeerNew(fi);
instance->addFeedItemPeerHello(fi); instance->addFeedItemPeerHello(fi);
instance->addFeedItemPeerNew(fi);
instance->addFeedItemPeerOffset(fi);
break; break;
case RS_FEED_TYPE_SECURITY: case RS_FEED_TYPE_SECURITY:
@ -906,6 +911,7 @@ struct AddFeedItemIfUniqueData
AddFeedItemIfUniqueData(FeedItem *feedItem, int type, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported) AddFeedItemIfUniqueData(FeedItem *feedItem, int type, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported)
: mType(type), mSslId(sslId), mIpAddr(ipAddr), mIpAddrReported(ipAddrReported) : mType(type), mSslId(sslId), mIpAddr(ipAddr), mIpAddrReported(ipAddrReported)
{ {
mPeerItem = dynamic_cast<PeerItem*>(feedItem);
mSecItem = dynamic_cast<SecurityItem*>(feedItem); mSecItem = dynamic_cast<SecurityItem*>(feedItem);
mSecurityIpItem = dynamic_cast<SecurityIpItem*>(feedItem); mSecurityIpItem = dynamic_cast<SecurityIpItem*>(feedItem);
} }
@ -914,6 +920,7 @@ struct AddFeedItemIfUniqueData
const RsPeerId &mSslId; const RsPeerId &mSslId;
const std::string& mIpAddr; const std::string& mIpAddr;
const std::string& mIpAddrReported; const std::string& mIpAddrReported;
PeerItem *mPeerItem;
SecurityItem *mSecItem; SecurityItem *mSecItem;
SecurityIpItem *mSecurityIpItem; SecurityIpItem *mSecurityIpItem;
}; };
@ -925,6 +932,14 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
return false; return false;
} }
if (findData->mPeerItem) {
PeerItem *peerItem = dynamic_cast<PeerItem*>(feedItem);
if (peerItem && peerItem->isSame(findData->mSslId, findData->mType)) {
return true;
}
return false;
}
if (findData->mSecItem) { if (findData->mSecItem) {
SecurityItem *secitem = dynamic_cast<SecurityItem*>(feedItem); SecurityItem *secitem = dynamic_cast<SecurityItem*>(feedItem);
if (secitem && secitem->isSame(findData->mSslId, findData->mType)) { if (secitem && secitem->isSame(findData->mSslId, findData->mType)) {
@ -955,7 +970,7 @@ void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId
return; return;
} }
ui->feedWidget->removeFeedItem(item); ui->feedWidget->removeFeedItem(feedItem);
} }
addFeedItem(item); addFeedItem(item);
@ -1017,6 +1032,20 @@ void NewsFeed::addFeedItemPeerNew(const RsFeedItem &fi)
#endif #endif
} }
void NewsFeed::addFeedItemPeerOffset(const RsFeedItem &fi)
{
/* make new widget */
PeerItem *pi = new PeerItem(this, NEWSFEED_PEERLIST, RsPeerId(fi.mId1), PEER_TYPE_OFFSET, false);
/* add to layout */
addFeedItemIfUnique(pi, PEER_TYPE_OFFSET, RsPeerId(fi.mId1), "", "", false);
#ifdef NEWS_DEBUG
std::cerr << "NewsFeed::addFeedItemPeerOffset()";
std::cerr << std::endl;
#endif
}
void NewsFeed::addFeedItemSecurityConnectAttempt(const RsFeedItem &fi) void NewsFeed::addFeedItemSecurityConnectAttempt(const RsFeedItem &fi)
{ {
/* make new widget */ /* make new widget */

View File

@ -87,8 +87,9 @@ private:
void addFeedItemPeerConnect(const RsFeedItem &fi); void addFeedItemPeerConnect(const RsFeedItem &fi);
void addFeedItemPeerDisconnect(const RsFeedItem &fi); void addFeedItemPeerDisconnect(const RsFeedItem &fi);
void addFeedItemPeerNew(const RsFeedItem &fi);
void addFeedItemPeerHello(const RsFeedItem &fi); void addFeedItemPeerHello(const RsFeedItem &fi);
void addFeedItemPeerNew(const RsFeedItem &fi);
void addFeedItemPeerOffset(const RsFeedItem &fi);
void addFeedItemSecurityConnectAttempt(const RsFeedItem &fi); void addFeedItemSecurityConnectAttempt(const RsFeedItem &fi);
void addFeedItemSecurityAuthDenied(const RsFeedItem &fi); void addFeedItemSecurityAuthDenied(const RsFeedItem &fi);

View File

@ -34,6 +34,7 @@
#include <retroshare/rsmsgs.h> #include <retroshare/rsmsgs.h>
#include <retroshare/rspeers.h> #include <retroshare/rspeers.h>
#include <retroshare/rsrtt.h>
/***** /*****
* #define DEBUG_ITEM 1 * #define DEBUG_ITEM 1
@ -68,6 +69,16 @@ PeerItem::PeerItem(FeedHolder *parent, uint32_t feedId, const RsPeerId &peerId,
} }
bool PeerItem::isSame(const RsPeerId &peerId, uint32_t type)
{
if ((mPeerId == peerId) && (mType == type))
{
return true;
}
return false;
}
void PeerItem::updateItemStatic() void PeerItem::updateItemStatic()
{ {
if (!rsPeers) if (!rsPeers)
@ -95,6 +106,9 @@ void PeerItem::updateItemStatic()
case PEER_TYPE_NEW_FOF: case PEER_TYPE_NEW_FOF:
title = tr("Friend of Friend"); title = tr("Friend of Friend");
break; break;
case PEER_TYPE_OFFSET:
title = tr("Friend Time Offset");
break;
default: default:
title = tr("Peer"); title = tr("Peer");
break; break;
@ -111,8 +125,14 @@ void PeerItem::updateItemStatic()
/* expanded Info */ /* expanded Info */
nameLabel->setText(QString::fromUtf8(details.name.c_str())); nameLabel->setText(QString::fromUtf8(details.name.c_str()));
idLabel->setText(QString::fromStdString(details.id.toStdString())); idLabel->setText(QString::fromStdString(details.id.toStdString()));
locLabel->setText(QString::fromUtf8(details.location.c_str())); locLabel->setText(QString::fromUtf8(details.location.c_str()));
if (rsRtt)
{
double offset = rsRtt->getMeanOffset(RsPeerId(mPeerId));
offsetLabel->setText(QString::number(offset,'f',2).append(" s"));
}
} }
else else
{ {
@ -187,6 +207,13 @@ void PeerItem::updateItem()
{ {
sendmsgButton->setEnabled(false); sendmsgButton->setEnabled(false);
} }
if (rsRtt)
{
double offset = rsRtt->getMeanOffset(RsPeerId(mPeerId));
offsetLabel->setText(QString::number(offset,'f',2).append(" s"));
}
} }
/* slow Tick */ /* slow Tick */

View File

@ -30,6 +30,7 @@ const uint32_t PEER_TYPE_STD = 0x0001;
const uint32_t PEER_TYPE_CONNECT = 0x0002; const uint32_t PEER_TYPE_CONNECT = 0x0002;
const uint32_t PEER_TYPE_HELLO = 0x0003; /* failed Connect Attempt */ const uint32_t PEER_TYPE_HELLO = 0x0003; /* failed Connect Attempt */
const uint32_t PEER_TYPE_NEW_FOF = 0x0004; /* new Friend of Friend */ const uint32_t PEER_TYPE_NEW_FOF = 0x0004; /* new Friend of Friend */
const uint32_t PEER_TYPE_OFFSET = 0x0005; /* received time offset */
class FeedHolder; class FeedHolder;
@ -43,6 +44,8 @@ public:
void updateItemStatic(); void updateItemStatic();
bool isSame(const RsPeerId &peerId, uint32_t type);
protected: protected:
/* FeedItem */ /* FeedItem */
virtual void doExpand(bool open); virtual void doExpand(bool open);

View File

@ -7,11 +7,20 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>476</width> <width>476</width>
<height>247</height> <height>250</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout"> <layout class="QGridLayout" name="PeerItemGLayout">
<property name="margin"> <property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number> <number>1</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
@ -95,13 +104,13 @@
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Sunken</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QGridLayout"> <layout class="QGridLayout" name="frameGLayout">
<property name="verticalSpacing"> <property name="verticalSpacing">
<number>0</number> <number>0</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QFrame" name="peerFrame"> <widget class="QFrame" name="peerFrame">
<layout class="QGridLayout"> <layout class="QGridLayout" name="peerFrameGLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -128,7 +137,7 @@
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<layout class="QGridLayout"> <layout class="QGridLayout" name="peerNameGLayout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="StyledLabel" name="peerNameLabel"> <widget class="StyledLabel" name="peerNameLabel">
<property name="text"> <property name="text">
@ -165,9 +174,9 @@
</layout> </layout>
</item> </item>
<item row="0" column="2"> <item row="0" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="lastHLayout">
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="lastHSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -204,9 +213,9 @@
</layout> </layout>
</item> </item>
<item row="1" column="1" colspan="2"> <item row="1" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="buttonHLayout">
<item> <item>
<spacer> <spacer name="buttonHSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -317,13 +326,13 @@
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QFrame" name="expandFrame"> <widget class="QFrame" name="expandFrame">
<layout class="QGridLayout"> <layout class="QGridLayout" name="expandFrameGLayout">
<item row="0" column="0"> <item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="expandFrameHLayout">
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="textVLayout">
<item> <item>
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="nameText">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight> <weight>75</weight>
@ -336,7 +345,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="idText">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight> <weight>75</weight>
@ -349,7 +358,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="trustText">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -368,7 +377,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="locText">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight> <weight>75</weight>
@ -381,7 +390,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="ipText">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight> <weight>75</weight>
@ -394,7 +403,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="connText">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight> <weight>75</weight>
@ -407,7 +416,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="typeLabel"> <widget class="QLabel" name="statusText">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -426,10 +435,30 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="offsetText">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<italic>true</italic>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Time offset:</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="labelVLayout">
<item> <item>
<widget class="QLabel" name="nameLabel"> <widget class="QLabel" name="nameLabel">
<property name="sizePolicy"> <property name="sizePolicy">
@ -509,6 +538,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="offsetLabel">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>
@ -531,17 +567,17 @@
</action> </action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>StyledLabel</class>
<extends>QLabel</extends>
<header>gui/common/StyledLabel.h</header>
</customwidget>
<customwidget> <customwidget>
<class>AvatarWidget</class> <class>AvatarWidget</class>
<extends>QLabel</extends> <extends>QLabel</extends>
<header>gui/common/AvatarWidget.h</header> <header>gui/common/AvatarWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>StyledLabel</class>
<extends>QLabel</extends>
<header>gui/common/StyledLabel.h</header>
</customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../images.qrc"/> <include location="../images.qrc"/>