суббота, 17 сентября 2011 г.

создание своего QVariant

Что такое QVariant вы надеюсь знаете, и что там есть эээ штук 10 дефолтных типов
а что бы сделать свой .. я как раз и расскажу.В общем тут не сложно :)

1. что нужно это сделать класс какой нужно что бы QVariant знал.
class dataLobbyList
{
public:

	dataLobbyList(QString _host,QString _port,QString _login,QString _pass)
		: m_Host(_host),m_Port(_port) , m_Login(_login) , m_Password(_pass)
	{}
	dataLobbyList(){}
	virtual int	getTypeData(){return TYPE_LOBBY_LIST;}

	QString	m_Host;
	QString	m_Port;
	QString	m_Login;
	QString	m_Password;
};
Q_DECLARE_METATYPE(dataLobbyList)

И главное в нем , это последняя строчка, она делает регистрацию в метатипах.
Что бы как раз QVariant  знал ваш класс.
2. ну и использование данной вещи.

DialogConnectInfo dialog("host","test","123","123");

QVariant var;
var.setValue<DialogConnectInfo>(dialog);

// ...

DialogConnectInfo bar2 = var.value<DialogConnectInfo>();
var.typeName();  // Foo::Bar

ниже пример не мой )) но я думаю и так понятно.

QTableView и роли.

Когда я начал изучать этот класс (потому что там есть Model и фильтры для него)
я столкнулся с ролями,
на что они похожи ??? а похожи они на простые фабрики классов.
1. параметр это QVariant
2.это как раз и есть значение фабрики

enum ItemDataRole {
        DisplayRole = 0,
        DecorationRole = 1,
        EditRole = 2,
        ToolTipRole = 3,
        StatusTipRole = 4,
        WhatsThisRole = 5,
} more...

то есть что бы сделать какую нить роль для QTableView
нужно ...


QAbstractItemModel_model = m_view->model();
 _model->setData(_model->index(0, 1),QColor(0,0,222), Qt::BackgroundColorRole);
тока модель нужно получить

И получается что для 0 столбца 1 ячейка будет иметь цвет QColor(0,0,222)

И кстати что я заметил , если вы для всего проекта забьете QStyleSheet и сделаете роль.
То роль является круче чем стиль :) 

ps надеюсь я разьяснил что такое роль в Qt , и это применительно не только для модели
но и везде где есть роль :) а их там много

сетевая часть recv

даю реально рабочий кусок из проекта.
Blob это класс контейнер фабрики классов

uint32_t CClientTransport::recv(ClientNode* _pNode)
{

	Blob bb;
	uint8_t* pBuffer = new uint8_t[4];
	int32_t nReceived, nReceivedTotal = 0;
	while(true)
	{
		nReceived = m_pSocket->read((char*) pBuffer + nReceivedTotal, 4);
		nReceivedTotal += nReceived;
		if (nReceivedTotal >= 4)
			break;
		m_pSocket->waitForReadyRead(1000);
	}
	bb.assign(pBuffer, nReceivedTotal, 4);
	int32_t uPacketSize;
	bb >> uPacketSize;


	nReceivedTotal = 0;
	pBuffer = new uint8_t[4096];
	while(true)
	{
		nReceived = m_pSocket->read((char*) pBuffer + nReceivedTotal, 4096);
		nReceivedTotal += nReceived;
		if (nReceivedTotal >= uPacketSize)
			break;
		m_pSocket->waitForReadyRead(1000);
	}
	bb.assign(pBuffer, nReceivedTotal, 4096);
	//bb.print(16, 4);

	uint32_t uCrc32;

	// просто забираем размер пакета
	// забираем CRC32
	bb >> uCrc32;
	// и сравниваем с CRC32 полученных данных пакета
	if (bb.crc32() != uCrc32)
			throw Exception(EX_CT(Exception::CONNECTIONERROR, "CRC32 error"));

	uint32_t uMessageType = bb.readUInt32();
	vn::MessageWrap msgw = _pNode->messageFactory(uMessageType);
	msgw.message()->Serialize(bb, false);
	_pNode->receiveMessage(msgw);
	return uMessageType;
}
В общем в заборе пакета я пользуюсь асинхронным методом m_pSocket->waitForReadyRead(1000);
в общем она похожа если бы я под виндой делал Sleep(1000)
просто ожидание, тормозов в общем не наблюдалось, но мы этот параметр минимизировали до 100 мс

Сетевая часть.

Давно не залезал, вот решил рассказать о тех проблемах
которые я встретил на своем тернистом пути :)

1. если вы хотите сделать нормальное приложение без тормозов и "затыков"
не используйте методы
waitForConnected
waitForReadyRead
waitForBytesWritten
все это приводит к выше перечисленным.
для этого используйте сигналы.
void readyRead();


void connected()
void disconnected()


пример , получения данных с сокета.

m_pSocket = new QTcpSocket();
connect(m_pSocket,SIGNAL(connected()),this,SLOT(sl_conect()));

connect(m_pSocket,SIGNAL(creadyRead()),this,SLOT(sl_ReadyRead()));

И все будет норм.