Доброго времени суток.
Имею дерево (QTreeView), которое содержит список сетей: 255.255,
Для каждой сети сегментов: 255.255.255,
Для каждого сегмента ip-адресов: 255.255.255.255
При клике на Item, отвечающий за сегмент, открывается QTableView, при открытии этой таблицы создаётся модель, содержащая строки с ip-адресами, и некоторой информацией об этом устройстве. Самый первый Item имеет тип IpStandardItemWithThread, наследуемый от QStandardItem и QObject.
При клике на другой item в дереве – строки в QTableView удаляются.
Суть в чём. В классе IpStandardItemWithThread я создаю объект класса Ping, который перемещаю в созданный в IpStandardItemWithThread поток (moveToThread()) .
В классе Ping имеется функция, в которой в бесконечном цикле происходит пингование ip-адреса.
Возникли 2 проблемы:
Во-первых, при таком коннекте connect(itemPing,&Ping::isPing,[this](QString,bool statusPing){}
Вываливаются вот такие ошибки.
QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QVector<int>'
(Make sure 'QVector<int>' is registered using qRegisterMetaType().)
Как от них избавиться?
Во-вторых, как по дестрою грамотно завершить поток и удалить объекты классов QThread и Ping? При нынешнем варианте после клика на другой item вылетает программа, хотя должен завершаться поток и должна очищаться память, выделенная под объекты.
Класс пинга:
#ifndef PING_H
#define PING_H
#include "winsock2.h"
#include "iphlpapi.h"
#include "icmpapi.h"
#include <QObject>
#include <QString>
class Ping : public QObject
{
Q_OBJECT
private:
HANDLE hIcmpFile; // Обработчик
unsigned long ipaddr; // Адрес назначения
DWORD dwRetVal; // Количество ответов
char SendData[32]; // Буффер отсылаемых данных
LPVOID ReplyBuffer; // Буффер ответов
DWORD ReplySize;
QString _ipAddress;
int _pingInterval;
public:
explicit Ping(QString ipAddress,int pingInterval,QObject *parent = 0);
~Ping();
signals:
void isPing(QString ipAddress,bool is_p);
public slots:
void windowsPing();
};
#endif // PING_H
#include "ping.h"
#include <QDebug>
Ping::Ping(QString ipAddress,int pingInterval,QObject *parent) :
QObject(parent),
_pingInterval(pingInterval),
_ipAddress(ipAddress),
ipaddr(INADDR_NONE),
dwRetVal(0),
//SendData("Data Buffer"),
ReplyBuffer(NULL),
ReplySize(0)
{
strcpy(SendData,"Data Buffer");
// Установка ip-адреса
ipaddr = inet_addr(_ipAddress.toStdString().c_str());
hIcmpFile = IcmpCreateFile(); // создание обработчика
// Выделение памяти под буффер ответов
ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
ReplyBuffer = (VOID*) malloc(ReplySize);
}
Ping::~Ping()
{
if(ReplyBuffer) free(ReplyBuffer);
}
void Ping::windowsPing()
{
while(true)
{
// Вызов функции ICMP эхо запроса
dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData), NULL, ReplyBuffer, ReplySize, 100);
emit isPing(_ipAddress,(dwRetVal != 0));
Sleep(_pingInterval);
}
}
Класс модели таблицы:
#ifndef SEGMENTMODEL_H
#define SEGMENTMODEL_H
#include <QObject>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QModelIndex>
#include <QStringList>
#include <QIcon>
#include <QThread>
#include "centralmodel.h"
#include "ping.h"
class SegmentModel;
class IpStandardItemWithThread;
class SegmentModel : public QStandardItemModel
{
Q_OBJECT
public:
SegmentModel(QObject *parent = NULL);
private:
QModelIndex _segmentModel;
QString _segmentAddress;
QString _segmentName;
void insertRow(HostInfo ipInf);
public slots:
void setNewSegment(QModelIndex segmentModel);
void clearAll();
};
class IpStandardItemWithThread : public QStandardItem, public QObject
{
public:
IpStandardItemWithThread(QString ipAddress,int pingInterval);
~IpStandardItemWithThread();
private:
QString _ipAddress;
int _pingInterval;
QThread *ipThread;
Ping *itemPing;
};
#endif // SEGMENTMODEL_H
#include "segmentmodel.h"
SegmentModel::SegmentModel(QObject *parent):
QStandardItemModel(parent)
{
this->setHorizontalHeaderLabels(QStringList() << tr("Д") << tr("IP") << tr("NetBIOS") << tr("MAC") << tr("Тип устройства") << tr("Операционная\nсистема") << tr("Комментарий") << tr("Р"));
}
void SegmentModel::insertRow(HostInfo ipInf)
{
IpStandardItemWithThread *item0 = new IpStandardItemWithThread(ipInf.IpAddress,3000);
item0->setEditable(false);
item0->setSelectable(false);
QStandardItem *item1 = new QStandardItem(ipInf.IpAddress);
item1->setEditable(false);
item1->setSelectable(false);
QStandardItem *item2 = new QStandardItem(ipInf.NetBIOS);
item2->setEditable(false);
item2->setSelectable(false);
QStandardItem *item3 = new QStandardItem(ipInf.MAC);
item3->setEditable(false);
item3->setSelectable(false);
QStandardItem *item4 = new QStandardItem(ipInf.DeviceType);
item4->setEditable(false);
item4->setSelectable(false);
QStandardItem *item5 = new QStandardItem(ipInf.OS);
item5->setEditable(false);
item5->setSelectable(false);
QStandardItem *item6 = new QStandardItem(ipInf.comment);
item6->setEditable(false);
item6->setSelectable(false);
QStandardItem *item7 = new QStandardItem("");
item7->setEditable(false);
item7->setSelectable(false);
this->appendRow(QList<QStandardItem *>() << item0 << item1 << item2 << item3 << item4 << item5 << item6 << item7);
}
void SegmentModel::setNewSegment(QModelIndex segmentModel)
{
_segmentModel = segmentModel;
_segmentAddress = _segmentModel.data().toString();
_segmentName = _segmentModel.sibling(_segmentModel.row(),1).data().toString();
QStandardItem *segmentItem = ((CentralModel*)(_segmentModel.model()))->itemFromIndex(_segmentModel);
for(int i=0;i<segmentItem->rowCount();i++)
{
IpStandardItem *ipItem = (IpStandardItem *)segmentItem->child(i,0);
insertRow(ipItem->getIpInformation());
}
}
void SegmentModel::clearAll()
{
this->removeRows(0,this->rowCount());
}
IpStandardItemWithThread::IpStandardItemWithThread(QString ipAddress, int pingInterval):
_ipAddress(ipAddress),
_pingInterval(pingInterval)
{
this->setIcon(QIcon(":/icons/ping_unknown.png"));
ipThread = new QThread();
itemPing = new Ping(_ipAddress,_pingInterval);
itemPing->moveToThread(ipThread);
connect(itemPing,&Ping::isPing,[this](QString,bool statusPing){
if(statusPing)
{
this->setIcon(QIcon(":/icons/ping_on.png"));
}
else
{
this->setIcon(QIcon(":/icons/ping_off.png"));
}
});
connect(ipThread,SIGNAL(started()),itemPing,SLOT(windowsPing()));
connect(ipThread,SIGNAL(finished()),itemPing,SLOT(deleteLater()));
ipThread->start();
}
IpStandardItemWithThread::~IpStandardItemWithThread()
{
if(ipThread->isRunning())
{
ipThread->terminate();
}
}