Chat Qt4/SFML

Iniciado por overxfl0w13, 16 Julio 2012, 01:48 AM

0 Miembros y 1 Visitante están viendo este tema.

overxfl0w13

Buenas compañeros :D.

Xeracker y yo llevamos un par de días codeando un chat funcional y así de paso aprender un poco de interfaces en C++, el resultado creo que ha sido bastante bueno y a pesar de que aún tiene algunos bugs y falta la implementación de algunas funciones del mismo, está en condiciones de publicarse su code por si algún usuario quiere ayudar o dar opiniones y hacer críticas.

Scan:



De momento falta la función de mostrar los usuarios en el ListBox derecho, de imprimir los emoticonos en el campo de texto entre muchas otras que iremos añadiendo :)

A continuación os dejo el source de todos los archivos:

Headers

App.hpp
Código (cpp) [Seleccionar]
#include "Window.hpp"
#include "Client.hpp"

class App
{
   Window window;
   Client client;
   void Thread();
   sf::Thread thread;
public:
   App() : thread(&App::Thread, this), window("Anonimo") { thread.launch(); }

};


Client.hpp
Código (cpp) [Seleccionar]
#include <SFML/Network.hpp>

class Client
{
   sf::IpAddress ServerAddress;
   sf::TcpSocket Socket;
   sf::Packet Packet;
   void Receiver();
   void Status();
   void Sender();
   bool connected;
   bool updated;
public:
   Client();
   sf::Thread R, S;
   sf::Packet Receive();
   void Send(sf::Packet);
   bool IsConnected();
   bool IsUpToDate();
};


Window.hpp:
Código (cpp) [Seleccionar]
#include <QObject>
#include <QtGui>
#include <QFile>
class Window : public QObject
{
   Q_OBJECT

public:

   Window(QString usu);
   ~Window();
   void Iconos();
   void Write(QString, QString);
   void ModificarEstado(bool estado);
   bool IsTextUpToDate() { return TextUpdated; }
   bool IsNickUpToDate() { return NickUpdated; }
   QString GetText(), GetNick();

private slots:

   void Send();
   void logueoUsuario();
   void configUser();
   void escribirWink();
   void escribirHappy();
   void escribirHeart();
   void escribirLaughter();
   void escribirSad();
   void escribirUuh();
   void escribirWhoa();

private:

   /* Constructores De Ventana*/
   QLineEdit *TextEdit;
   QLineEdit *UserEdit;

   QPushButton *SendButton;
   QPushButton *LogButton;
   QPushButton *CLogButton;

   QTextEdit *TextBox;
   QListWidget *UserBox;

   QVBoxLayout *mainLayout;
   QVBoxLayout *chatLayout;
   QVBoxLayout *usersLayout;

   QHBoxLayout *buttonLayout;
   QHBoxLayout *usutextLayout;
   QHBoxLayout *emoLayout;
   QWidget *window;

   QString usuario, estado;

   QLabel *etiqueta;
   QLabel *imagenChat;
   QLabel *imagenConectados;

   /*Emoticonos y Capa Emoticonos*/
   QPushButton *emoWink, *emoHappy, *emoHeart, *emoLaughter, *emoSad, *emoUuh, *emoWhoa;

   bool TextUpdated, NickUpdated;


};


Sources

App.cpp:
Código (cpp) [Seleccionar]
#include "App.hpp"

void App::Thread()
{
   while(1)
   {
       if(!client.IsUpToDate())
       {
           QString t1, t2;
           sf::String s1, s2;
           client.Receive() >> s1 >> s2;
           t1 = s1.toAnsiString().c_str();
           t2 = s2.toAnsiString().c_str();
           window.Write(t1,t2);
       }

       if(!window.IsTextUpToDate())
       {
           sf::String str=window.GetText().toStdWString();
           sf::Packet Pack;
           Pack << 1 << str;
           client.Send(Pack);
           Pack.clear();
       }

       if(!window.IsNickUpToDate())
       {
           sf::String str=window.GetNick().toStdWString();
           sf::Packet Pack;
           Pack << 0 << str;
           client.Send(Pack);
           Pack.clear();
       }
       if(client.IsConnected())
       {
            window.ModificarEstado(true);
       }

   }
}


Client.cpp:
Código (cpp) [Seleccionar]
#include "Client.hpp"

Client::Client() : R(&Client::Receiver, this), S(&Client::Sender, this), updated(true)
{
   Socket.connect("**************", 25569);
   R.launch();
   S.launch();
}

void Client::Receiver() //Receiver Thread
{
   while(1)
   {
       sf::Packet buffer;
       Socket.receive(buffer);
       Packet = buffer;
       buffer.clear();
       updated=false;
   }

}


void Client::Sender() //Sender Thread
{

}


sf::Packet Client::Receive()
{
   updated=true;
   return Packet;
}

void Client::Send(sf::Packet Pack)
{
   connected = (Socket.send(Pack) == sf::Socket::Done);
}

bool Client::IsUpToDate()
{
   return updated;
}

bool Client::IsConnected()
{
   return connected;
}




Window.cpp:
Código (cpp) [Seleccionar]
#include "Window.hpp"
void Window::ModificarEstado(bool status)
{
   if(status) estado = "Conectado";
   else estado = "Desconectado";
   window->setWindowTitle("Nick: "+usuario+" <---> Estado: "+estado);
}
void Window::escribirWink()
{
   TextEdit->insert(QString(" ;) "));
}

void Window::escribirHappy()
{
   TextEdit->insert(QString(" :) "));
}

void Window::escribirHeart()
{
   TextEdit->insert(QString(" (L) "));
}

void Window::escribirLaughter()
{
   TextEdit->insert(QString(" :D "));
}

void Window::escribirSad()
{
   TextEdit->insert(QString(" :( "));
}

void Window::escribirUuh()
{
   TextEdit->insert(QString(" ¬¬ "));
}

void Window::escribirWhoa()
{
   TextEdit->insert(QString(" :O "));
}

void Window::Iconos()
{
   /* Emoticonos */

   emoWink = new QPushButton;
   emoHappy = new QPushButton;
   emoHeart = new QPushButton;
   emoLaughter = new QPushButton;
   emoSad = new QPushButton;
   emoUuh = new QPushButton;
   emoWhoa = new QPushButton;
   QObject::connect(emoWink,SIGNAL(clicked()),this,SLOT(escribirWink()));
   QObject::connect(emoHappy,SIGNAL(clicked()),this,SLOT(escribirHappy()));
   QObject::connect(emoHeart,SIGNAL(clicked()),this,SLOT(escribirHeart()));
   QObject::connect(emoLaughter,SIGNAL(clicked()),this,SLOT(escribirLaughter()));
   QObject::connect(emoSad,SIGNAL(clicked()),this,SLOT(escribirSad()));
   QObject::connect(emoUuh,SIGNAL(clicked()),this,SLOT(escribirUuh()));
   QObject::connect(emoWhoa,SIGNAL(clicked()),this,SLOT(escribirWhoa()));
   emoWink->setIcon(QIcon("emoticonos/guinyo.png"));
   emoHappy->setIcon(QIcon("emoticonos/happy.png"));
   emoHeart->setIcon(QIcon("emoticonos/heart.png"));
   emoLaughter->setIcon(QIcon("emoticonos/laughter.png"));
   emoSad->setIcon(QIcon("emoticonos/sad.png"));
   emoUuh->setIcon(QIcon("emoticonos/uhh.png"));
   emoWhoa->setIcon(QIcon("emoticonos/whoa.png"));

   /* Capa Horizontal Emoticonos */

   emoLayout = new QHBoxLayout;
   emoLayout->addWidget(emoWink);
   emoLayout->addWidget(emoHappy);
   emoLayout->addWidget(emoHeart);
   emoLayout->addWidget(emoLaughter);
   emoLayout->addWidget(emoSad);
   emoLayout->addWidget(emoUuh);
   emoLayout->addWidget(emoWhoa);

   /* Anidacion capa horizontal en vertical */

   mainLayout->addLayout(emoLayout);

}

void Window::configUser()
{
   usuario = UserEdit->text();
   NickUpdated=false;
   delete etiqueta;
   delete UserEdit;
   delete CLogButton;
   window->setWindowTitle("Nick: "+usuario+" <---> Estado: "+estado);
   SendButton = new QPushButton("Enviar");
   TextEdit = new QLineEdit;
   SendButton->setIcon(QIcon("emoticonos/aceptar.png"));
   QObject::connect(SendButton,SIGNAL(clicked()),this,SLOT(Send()));
   mainLayout->addWidget(TextEdit);
   mainLayout->addWidget(SendButton);
   window->setLayout(mainLayout);
   window->show();
}

void Window::Write(QString user, QString msg)
{
   TextBox->append(user+": "+msg);
}

void Window::Send()
{
   if(TextEdit->text()!= "")
   {
       TextUpdated=false;
       TextEdit->clear();
   }
}

QString Window::GetText()
{
   TextUpdated=true;
   return TextEdit->text();
}

QString Window::GetNick()
{
   NickUpdated=true;
   return usuario;
}


void Window::logueoUsuario()
{
   delete LogButton;
   delete SendButton;
   delete TextEdit;
   CLogButton = new QPushButton("Aceptar");
   CLogButton->setIcon(QIcon("emoticonos/aceptar.png"));
   QObject::connect(CLogButton,SIGNAL(clicked()),this,SLOT(configUser()));
   UserEdit = new QLineEdit;
   etiqueta = new QLabel("Inserta nickname");
   etiqueta->setAlignment(Qt::AlignCenter);
   mainLayout->addWidget(etiqueta);
   mainLayout->addWidget(UserEdit);
   mainLayout->addWidget(CLogButton);
   window->setLayout(mainLayout);
   window->show();

}

Window::Window(QString user) : usuario(user), TextUpdated(true), NickUpdated(false)
{
   window = new QWidget;
   LogButton = new QPushButton("Loguear");
   LogButton->setIcon(QIcon("emoticonos/llave.png"));
   QObject::connect(LogButton,SIGNAL(clicked()),this,SLOT(logueoUsuario()));
   TextBox = new QTextEdit;
   TextBox->setReadOnly(true);
   TextBox->setMinimumSize(QSize(550,0));
   UserBox = new QListWidget;
   imagenChat = new QLabel("Chat");
   QImage imageChat("emoticonos/chat.png");
   imagenChat->setPixmap(QPixmap::fromImage(imageChat));
   imagenChat->setAlignment(Qt::AlignCenter);
   QLabel *etiquetaChat = new QLabel("Chat");
   etiquetaChat->setAlignment(Qt::AlignCenter);
   imagenConectados = new QLabel("Conectados");
   QImage imageUsers("emoticonos/conectados.png");
   imagenConectados->setPixmap(QPixmap::fromImage(imageUsers));
   imagenConectados->setAlignment(Qt::AlignCenter);
   QLabel *etiquetaConectados = new QLabel("Usuarios Conectados");
   etiquetaConectados->setAlignment(Qt::AlignCenter);
   usutextLayout = new QHBoxLayout;
   TextEdit = new QLineEdit;
   SendButton = new QPushButton("Enviar");
   SendButton->setIcon(QIcon("emoticonos/aceptar.png"));
   chatLayout = new QVBoxLayout;
   usersLayout = new QVBoxLayout;
   mainLayout = new QVBoxLayout;
   buttonLayout = new QHBoxLayout;
   window->setMinimumSize(700,500);
   window->setMaximumSize(700,500);
   QObject::connect(SendButton,SIGNAL(clicked()),this,SLOT(Send()));
   chatLayout->addWidget(imagenChat);
   chatLayout->addWidget(etiquetaChat);
   chatLayout->addWidget(TextBox);
   usersLayout->addWidget(imagenConectados);
   usersLayout->addWidget(etiquetaConectados);
   usersLayout->addWidget(UserBox);
   usutextLayout->addLayout(chatLayout);
   usutextLayout->addLayout(usersLayout);
   mainLayout->addLayout(usutextLayout);
   Iconos();
   mainLayout->addWidget(TextEdit);
   buttonLayout->addWidget(SendButton);
   buttonLayout->addWidget(LogButton);
   mainLayout->addLayout(buttonLayout);
   window->setLayout(mainLayout);
   window->show();
}

Window::~Window() {}


main.cpp:
Código (cpp) [Seleccionar]
#include "App.hpp"

int main(int argc,char *argv[])
{
   QApplication Qt(argc,argv);
   App *app = new App();
   return Qt.exec();
}


Server.cpp:
Código (c++) [Seleccionar]
#include <SFML/Network.hpp>
#include <iostream>
using namespace std;

struct Client{
   sf::TcpSocket s;
   bool connected;
   sf::String alias;
} Client[256];

int main(int argc, char *argv[])
{

   sf::TcpListener Server;
   sf::SocketSelector Selector;
   int Port = 25569;

   for(int i=0; i<256; i++) Client[i].connected=false, Client[i].alias="Unknown";

   Server.listen(Port);
   cout << "Escuchando puerto " << Port << " TCP..." << endl;
   Selector.add(Server);

   while (Selector.wait())
   {
       if (Selector.isReady(Server))
       {
           for(int i=0; i<256; i++)
           {
               if(!Client[i].connected)
               {
                   sf::Packet Packet;
                   Server.accept(Client[i].s);
                   cout << "Client connected (ID: " << i << ", IP: " << Client[i].s.getRemoteAddress() << ")" << endl;
                   Selector.add(Client[i].s);
                   Client[i].connected=true;
                   break;
               }
           }
       }
       else
       {
           for(int i=0; i<256; i++)
           {
               if(Selector.isReady(Client[i].s))
               {
                   sf::Packet Packet;
                   if(Client[i].s.receive(Packet) == sf::Socket::Done)
                   {
                       int com;
                       Packet >> com;
                       switch (com)
                       {
                           case 0:
                               Client[i].alias.clear();
                               Packet >> Client[i].alias;
                               cout << "Client " << i << " ha cambiado su alias a \"" << Client[i].alias.toAnsiString() << "\"." << endl;
                           break;
                           case 1:
                               sf::String Msg;
                               Packet >> Msg;
                               cout << Client[i].alias.toAnsiString() << ": " << Msg.toAnsiString() << endl;

                               Packet.clear();
                               Packet << Client[i].alias << Msg;

                               for (int i=0; i<256; i++)
                                   if(Client[i].connected)
                                       Client[i].s.send(Packet);

                       }
                       break;
                   }
                   else
                   {
                       cerr << Client[i].alias.toAnsiString() << " se ha desconectado (ID: " << i << ", IP: " << Client[i].s.getRemoteAddress() << ")" << endl;
                       Selector.remove(Client[i].s);
                       Client[i].connected=false;
                       Client[i].alias="Unknown";
                       break;
                   }
               }
           }
       }
   }
}



Con todo el code ya publicado, pongo link con un .rar que contiene lo archivos necesarios para compilar desde CodeBlocks junto con los emoticonos y las imágenes del programa.

http://www.mediafire.com/?9h7mlte60p6h2qd

Aclaro que se necesita tener instaladas la librerías Qt y SFML, si tenéis algún problema con su instalación subiré el .rar con las .dll de las librerias necesarias para el correcto funcionamiento del chat.

Un saludo a todos y esperamos que os guste :)
[/url]

DickGumshoe

¡Os está quedando genial! ¡Ánimos, que seguro que conseguís mejorarlo y ponerle muchas cosas más!

P.D.: Ojalá pudiera hacer yo algo en C++ así de bien  :xD

X3R4CK3R

Un detalle que se pasó overxfl0w:

El code anterior es únicamente del cliente (chat), el code del servidor lo dejo aquí, por si alguien quiere compilarlo y probar el cliente por localhost o lo que sea:

Código (cpp) [Seleccionar]
#include <SFML/Network.hpp>
#include <iostream>
using namespace std;

struct Client{
    sf::TcpSocket s;
    bool connected;
    sf::String alias;
} Client[256];

int main(int argc, char *argv[])
{

    sf::TcpListener Server;
    sf::SocketSelector Selector;
    int Port = 25569;

    for(int i=0; i<256; i++) Client[i].connected=false, Client[i].alias="Unknown";

    Server.listen(Port);
    cout << "Escuchando puerto " << Port << " TCP..." << endl;
    Selector.add(Server);

    while (Selector.wait())
    {
        if (Selector.isReady(Server))
        {
            for(int i=0; i<256; i++)
            {
                if(!Client[i].connected)
                {
                    sf::Packet Packet;
                    Server.accept(Client[i].s);
                    cout << "Client connected (ID: " << i << ", IP: " << Client[i].s.getRemoteAddress() << ")" << endl;
                    Selector.add(Client[i].s);
                    Client[i].connected=true;
                    break;
                }
            }
        }
        else
        {
            for(int i=0; i<256; i++)
            {
                if(Selector.isReady(Client[i].s))
                {
                    sf::Packet Packet;
                    if(Client[i].s.receive(Packet) == sf::Socket::Done)
                    {
                        int com;
                        Packet >> com;
                        switch (com)
                        {
                            case 0:
                                Client[i].alias.clear();
                                Packet >> Client[i].alias;
                                cout << "Client " << i << " ha cambiado su alias a \"" << Client[i].alias.toAnsiString() << "\"." << endl;
                            break;
                            case 1:
                                sf::String Msg;
                                Packet >> Msg;
                                cout << Client[i].alias.toAnsiString() << ": " << Msg.toAnsiString() << endl;

                                Packet.clear();
                                Packet << Client[i].alias << Msg;

                                for (int i=0; i<256; i++)
                                    if(Client[i].connected)
                                        Client[i].s.send(Packet);

                        }
                        break;
                    }
                    else
                    {
                        cerr << Client[i].alias.toAnsiString() << " se ha desconectado (ID: " << i << ", IP: " << Client[i].s.getRemoteAddress() << ")" << endl;
                        Selector.remove(Client[i].s);
                        Client[i].connected=false;
                        Client[i].alias="Unknown";
                        break;
                    }
                }
            }
        }
    }
}


Saludos!

dato000

Cita de: DickGumshoe en 16 Julio 2012, 01:53 AM
¡Os está quedando genial! ¡Ánimos, que seguro que conseguís mejorarlo y ponerle muchas cosas más!

P.D.: Ojalá pudiera hacer yo algo en C++ así de bien  :xD

+1...yo ni se como implementarlo, pero de verdad que vale la pena hacerlo!!! esta del carajo!!!

oye los graficos tambien son con C++??????

9.99999999999/10 BRAVO!!!!



X3R4CK3R

Cita de: dato000 en 16 Julio 2012, 05:12 AM
+1...yo ni se como implementarlo, pero de verdad que vale la pena hacerlo!!! esta del carajo!!!

oye los graficos tambien son con C++??????

9.99999999999/10 BRAVO!!!!

No, los gráficos son de la librería Qt

dato000

Cita de: XeRaCKeR en 16 Julio 2012, 06:26 AM
No, los gráficos son de la librería Qt

pendiente libreria qt entre las miles de cosas que tengo que mirar.  :)



Sputnik_

increíble, se agradece un montón, justo estaba pensando como hacer uno, me viene genial  :)  ;-)
Las personas lo suficientemente locas como para pensar que pueden cambiar el mundo son las que lo cambian.

[Zero]

#7
Podíais haber usado el modulo QtNetwork de Qt para la conexión y no tener que usar otra librería externa, Qt sirve para mucho más que solo la GUI, y mola más.  También, en los ejemplos de Qt hay un chat multiusuario muy similar, usando QtNetwork, podéis echarle un ojo. Ah y Qt es un framework, no un lenguaje, por lo tanto sí es C++ :D .

Saludos!

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

anonimo12121

Zero cuanto tiempo sin verte agregame al tuenti capullo y hablamos xDD
Página para ganar Bitcoins y Dinero: http://earnbit.hol.es/
Video de YouTube con Hack para el LoL: http://adf.ly/5033746/youtube-lolemuhack
Si quieres ganar dinero con adfly entra y registrate aquí -> http://adf.ly/?id=5033746

X3R4CK3R

@[Zero]: Tienes razón pero no tengo apenas tiempo para ponerme a aprender QTNetwork, es por eso que de momento estamos usando SFML-Network, cuando saque más tiempo libre ya pensaremos en pasarnos.

@Xafi: Existen los mensajes privados, tu mensaje no pinta nada aquí. A ver si usamos un poco la cabeza.

Saludos!