Your task is to create a peer to peer chat program with Qt. You have been given networking code that finds and connects to peers on the local network and a GUI that demonstrates the basics of how the networking code is used.
You must extend the given project to provide user profile support, images, private chatrooms and private messaging.
The program’s interface must allow the user to do the following:
- Set their nickname (aka username or handle).
- Set user profile details, including an image file, time zone and location.
- Send messages.
- Send private messages to users.
- Create private chatrooms.
- Invite users to private chatrooms.
- Join private chatrooms.
- Kick users from private rooms.
- Send files to rooms.
- Send files to users.
- Save chat transcripts to files (excluding exchanged files)
The program will be using Qt, and will need to utilise the Qt data types.
The supplied networking code handles passing messages between clients, and all running clients (on the same local network) automatically connect to each other in the main (public) chatroom. The code in the Networking folder will not need modification.
The MessageFactory follows a version of the Abstract Factory Pattern and handles messages passed from the network. Each message’s type is defined by a number (id) passed to the MessageFactory::create() member function.
Abstract Factory Pattern - Provide an interface for creating families of related classes, without calling concrete class constructors.
The program must implement the following message types:
This message contains a message for display in the public chatroom, it will be displayed on all user’s screens.
This message contains an image, it may be displayed as an image in the relevant room, or displayed as a link with a pop up window that displays the message.
This message contains a message sent from one user directly to another, this message will not be shown in the public chatroom. This should be displayed in a separate window, one per user.
This message contains a file, it should be displayed in the relevant chatroom as a link, that allows the user to save the file to a location on disk. The file should be saved to a temporary location on receipt of the message (to save memory).
This message contains an action - invite, kick, join, leave. These allow users to join and leave private chatrooms.
This message contains the nickname, image, time zone and location of the user, this should be sent anytime the user’s profile details change. Note: the nickname must not be changed while the user is online.
The above names are the names that must be used for the message classes. They must derive from the Message class, see the Message class documentation for what each member function must do.
The TextMessage class has already been implemented, as a demonstration.
Each message type has a specific data format as follows:
The data contains the text of a message (in UTF8 format).
The data contains the name of the image, followed by a separator |, then the (raw binary) data for the image.
The data contains either a room name (for messages to private chatrooms) or a username (for private messages) followed by a separator |, then the message text (again UTF8 encoded).
The data contains the name of the file, a separator | followed by the data for the file.
The data contains the action name, a separator | followed by the operands separated by |
|JOIN||Room name invited name||Invited name must match the name sent by the invite message. Send to the user who invited. That user forwards to all other users in the private chatroom.|
|LEAVE||Room name||Send to all private room participants when user leaves a private room.|
|INVITE||Room name invitee||Sent from someone in a private room to invite a user from the public chatroom, sent only to the invitee, the invitee operand is the user’s unique identifier.|
|KICK||Room name nickname||Kick a user from a private room. The message is sent to all connected users.The Kicked user will be removed from the room list on all clients.|
The data contains the username, a separator
|, a location, a separator
|, a time zone, a separator
|, and image data.
The supplied code includes example data for messages of each type to allowing testing of message implementations.
As there is no chat server, peers send messages directly to one another, these messages must be stored by each client (chat program) to allow a chat history to be saved. Messages can be sent to either all clients (public) or clients one at a time (private).
Each connected user is uniquely identified by their nickname and their IP address. Multiple users can be connected from one IP address, so long as they have different nicknames.
Each connected user can have profile information, this includes their nickname (which must not change while they are online), a location, a time zone and an image. The image must be PNG formatted at a resolution of 48x48 pixels, to simplify accurate display on all clients. User profiles are sent via Identity messages, these must be sent when new clients join the public chatroom (Hint: p2pnetworking::Client::newParticipant signal) or to all participants when the user profile changes. The interface must allow the user to modify their profile (excluding username) while they are connected. The interface must also handle this change from other users. It is suggested that picture is displayed next to the user in the main GUI, although a pop-up window with the complete profile is also acceptable, either way, the entire profile must be accessible.
The chat program must allow users to send images to the public chatroom, private chatrooms and as private messages to only one user. The image formats jpg, png and gif must be supported, but animation support is optional. The images do not have to display in the main chat window, but must be accessible by a single click. Users must be able to open a file browser to select an image to send, optionally support for drag and drop can be added. (Hint: see the QFileDialog class documentation)
Like images, the program must allow users to send files to the public chatroom, private chatrooms and directly to other users in private messages. Again, users must be able to open a file browser to select an image to send, optionally support for drag and drop can be added. The interface must provide a save dialog for saving a file to disk. It is suggested that files are temporarily stored to disk during each session and deleted at the end, to prevent exhausting memory or filling the disk with unnecessary files, use a scheme to prevent duplicate filenames from overwriting each other i.e. handle when the same or different users to send multiple files with the same name at different times. The file can then be copied from its temporary location to the location requested by the user in the save dialog.
Private chat requires that participating chat clients have support for private chatroom. To support private chatroom, an additional class will be required. This class must contain at least the name of the chatroom and the names of each person in the chatroom. A user first invites another to a chatroom with an invite message. The join message must be sent to the client who invited the user to private chatroom. The user who receives a join following their invite must pass the join message to all other users in the private chatroom, this may be a member function in the private chat class. A message into a private chatroom will be sent to all the members of that room by the sender. (i.e. call the p2pnetworking::Client::sendMessage function overload that takes a nickname parameter, one time per user in the chatroom).
If the menuBar, mainToolBar or statusBar are unused, remove the unused ones from your chatwindow.ui file.
To load images for display in the GUI, use the QImage::fromData() static member function, read the Qt QImage documentation for details. One way to display the image: The QImage can be converted to a QPixmap to be passed to a QLabel for display, however this is not the only way to display images.
You are free to use any of the Qt library classes, you may use C++ STL if you wish, however Qt classes are generally a better fit for GUI applications. You may not use any additional libraries.
Follow the style guide set for the course - see learnonline.