class Master : public QObject { // Обьект передающий уведомление о том что к.либо таблица изменилась Q_OBJECT public : static Master * getObject(); public slots : void tableChange(const QString & ); // этот слот связан со всеми виджетами с помощью которых пользователь может менять данные // он будет вызыватся каждый раз когда к.либо обьект проги изменил данные. void beforeQuit(); void acceptConnection(); signals : void RefreshTable(const QString & ); // сигнал рассылается всем виджетам // в качестве параметра передается имя таблицы которая была изменена. private : Master(QObject * parent = 0); static Master * pointer; sendThread * sThread; QTcpServer * tcpServer; quint16 port; QHostAddress hAdr; };class sendThread : public QThread { // Поток в котором будем рассылать уведомления другим клиентским прогам. Q_OBJECT public : sendThread(QObject * parent = 0); void start(const QString &); void setAddress(QHostAddress & ,quint16 port); protected: void run(); private : int q; QString tName; QSqlDatabase db; QHostAddress hAdr; quint16 port; };
Master * Master::pointer = 0;Master::Master(QObject * parent) :QObject(parent) { QSqlDatabase db = G::getDB(); hAdr = QHostInfo::fromName(QHostInfo::localHostName()).addresses().last(); // создаем сервер tcpServer = new QTcpServer(this); tcpServer->listen(hAdr); port = tcpServer->serverPort(); // ДОБАВЛЯЕМ СЕБЯ В ip_table . QSqlQuery query(G::getDB()); while(true) { if(!query.exec("SELECT max(`key`) FROM ip_table;")) { QMessageBox::information(0,"111",query.lastError().text(),QMessageBox::Yes); }; query.next(); int key = query.value(0).toInt(); key++; QString insert = "INSERT INTO ip_table VALUES("+QString::number(key) +",'"+hAdr.toString()+"',"+QString::number(port)+",0);"; if(query.exec(insert)) break; }; // Создаем sendThread sThread = new sendThread(this); sThread->setAddress(hAdr,port); QObject::connect(tcpServer,SIGNAL(newConnection()),this, SLOT(acceptConnection())); QObject::connect(QApplication::instance(),SIGNAL(aboutToQuit()),this,SLOT(beforeQuit())); };void Master::beforeQuit()// Слот связан с QCoreApplication::aboutToQuit () [signal] {// Удаляем из ip_table данные о себе. QString q("DELETE FROM ip_table WHERE ip='"+hAdr.toString()+"' AND port="+QString::number(port)+";"); QSqlQuery query(G::getDB()); if(!query.exec(q)) { QMessageBox::information(0,QString("Удаление из ip_table не произошло.") ,query.lastError().text()+"\n"+q,QMessageBox::Yes); }; // Если данные о себе не удалим перед выходом то ничего страшного они будут удалены другой клиентской программой. ( потом). };void Master::acceptConnection() { QTcpSocket * incomeConnection = tcpServer->nextPendingConnection(); QString str; QDataStream in(incomeConnection); in.setVersion(QDataStream::Qt_4_0); while (incomeConnection->bytesAvailable() < (int)sizeof(quint16)) { if (!incomeConnection->waitForReadyRead(6660)) { return; }; }; quint16 size; in>>size; while(incomeConnection->bytesAvailable()<size) { if(!incomeConnection->waitForReadyRead(6660)) { return; }; }; in>>str; emit RefreshTable(str); };void Master::tableChange(const QString & tName) { emit RefreshTable(tName); // все виджеты в данном экземпляре проги обновятся. // и еще рассылаем всем другим прогам сообщение. sThread->start(tName); //G::debug("tableChange -"+tName); };Master * Master::getObject() { if(!pointer) { pointer = new Master(QApplication::instance()); }; return pointer; };sendThread::sendThread(QObject * parent) :QThread(parent) ,port(0) { db=G::getDB(); };void sendThread::setAddress(QHostAddress & adr,quint16 q) { hAdr = adr; port = q; };void sendThread::start(const QString & tn) { if(hAdr.isNull()) { QMessageBox::information(0,"Alarm",QString::fromLocal8Bit("Не инициализировали"),QMessageBox::Ok); return; }; if(!port) { return ; }; tName=tn; QThread::start(); };void sendThread::run() { QString q("SELECT `key`,`ip`,`port`,`error_count` FROM ip_table WHERE NOT (ip='"+hAdr.toString()+"' AND port="+QString::number(port)+");"); QSqlQuery query(db); if(!query.exec(q))// выбираем из БД адреса и порты других приложений. { QMessageBox::information(0,"QueryError",query.lastError().text(),QMessageBox::Yes); return; }; QTcpSocket * tcpSocket = new QTcpSocket(this); while(query.next()) { int temp_key = query.value(0).toInt(); QString temp_ip = query.value(1).toString(); int temp_port = query.value(2).toInt(); tcpSocket->connectToHost(QHostAddress(temp_ip),temp_port,QIODevice::WriteOnly); if(!tcpSocket->waitForConnected(666)) { QSqlQuery del_q(db); // Если не дозвонились до к.либо клиента то увеличиваем счетчик ошибок иесли их больше трех удаляем из БД. QString update("UPDATE ip_table SET error_count=error_count+1 WHERE ip= '" +temp_ip+"' AND port="+QString::number(temp_port)+";"); if(!del_q.exec(update)) { QMessageBox::information(0,"",del_q.lastError().text(),QMessageBox::Yes); }; //QMessageBox::information(0,"QueryError","I am in (!tcpSocket->waitForConnected())",QMessageBox::Yes); QString del("DELETE FROM ip_table WHERE error_count>3"); del_q.exec(del); } else { //отправляем имя таблицы. QByteArray block; QDataStream out(&block,QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_0); out << (quint16)0; out << tName; out.device()->seek(0); out << (quint16)(block.size() - sizeof(quint16)); tcpSocket->write(block); tcpSocket->disconnectFromHost(); }; tcpSocket->waitForDisconnected(666); }; };
public slots: void slt_refresh(const QString&); signals : void iChangeTable(const QString & );
void eMAbstractGrid::slt_refresh(const QString& tName) { if(tName!=this->tName) return; setQuery(strQuery); };
CREATE OR ALTER trigger PHYS_PERSONS_MODIFY for PHYS_PERSONSactive after insert or update or delete position 0ASbegin post_event 'PHYS_PERSONS_MODIFY';end