Commit 73da7b09 authored by Carsten Fuhrmann's avatar Carsten Fuhrmann

tree structure,

switching and poke,

next:
open tree on hot key,

bugs:
crash on disconnect
parent 873429b5
#include "overlaycontroller.h"
#include <QDesktopWidget>
#include <QTimer>
#include <QStringList>
#include "plugin.h"
#include <qdebug.h>
//#ifndef _DEBUG
//#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
//#endif
OverlayController::OverlayController() : QObject()
struct channelInfo {
uint64 id;
QString name;
uint64 parent;
QTreeWidgetItem* entry;
};
enum nodeType {
channel,
client
};
Q_DECLARE_METATYPE(nodeType);
OverlayController::OverlayController(const struct TS3Functions funcs, quint64 serverConnectionHandlerID) : QObject(), ts3(funcs)
{
QDesktopWidget desktop;
......@@ -16,10 +33,14 @@ OverlayController::OverlayController() : QObject()
m_speakerOffset = 0;
m_debugWindow = new QLabel;
m_debugWindow->setGeometry(320, 200, 750, 360);
m_debugWindow->setGeometry(320, 200, 750, 500);
m_debugWindow->setAlignment(Qt::AlignTop | Qt::AlignLeft);
m_debugWindow->show();
m_SCHID = serverConnectionHandlerID;
m_tree = new QTreeWidget;
m_tree->setHeaderHidden(true);
m_tree->setExpandsOnDoubleClick(false);
}
OverlayController::~OverlayController()
......@@ -33,6 +54,7 @@ OverlayController::~OverlayController()
m_msgLines.clear();
delete m_debugWindow;
delete m_tree;
}
void OverlayController::deleteChatLine(QWidget * line)
......@@ -46,6 +68,25 @@ void OverlayController::deleteChatLine(QWidget * line)
}
}
void OverlayController::treeItemClicked(QTreeWidgetItem * item, int column)
{
int type = item->data(2, Qt::UserRole).toInt();
if (type == channel)
{
anyID clientID;
ts3.getClientID(m_SCHID, &clientID);
quint64 id = item->data(1, Qt::UserRole).value<quint64>();
ts3.requestClientMove(m_SCHID, clientID, id, "", NULL);
}
else if (type == client)
{
anyID id = item->data(1, Qt::UserRole).value<anyID>();
ts3.requestClientPoke(m_SCHID, id, "", NULL);
}
}
void OverlayController::addChatLine(QString message)
{
// generate new chatline
......@@ -158,17 +199,91 @@ void OverlayController::reset()
m_msgLines.clear();
m_speakerOffset = 0;
m_currentChannel = 0;
}
void OverlayController::setCurrentChannel(quint64 id)
void OverlayController::updateChannelList()
{
m_currentChannel = id;
if (m_tree->isVisible())
displayChannelList();
}
quint64 OverlayController::getCurrentChannel() const
void OverlayController::displayChannelList()
{
return m_currentChannel;
}
while (int nb = m_tree->topLevelItemCount())
{
auto item = m_tree->takeTopLevelItem(nb - 1);
disconnect(m_tree, &QTreeWidget::itemDoubleClicked, this, &OverlayController::treeItemClicked);
delete item;
}
uint64* channelIDList;
ts3.getChannelList(m_SCHID, &channelIDList);
QVector<channelInfo> channelList;
// get Channels
int i(0);
while (channelIDList[i] != NULL)
{
channelInfo tmp;
tmp.id = channelIDList[i];
tmp.name = channelID2Name(m_SCHID, channelIDList[i]);
ts3.getParentChannelOfChannel(m_SCHID, channelIDList[i], &tmp.parent);
tmp.entry = new QTreeWidgetItem;
tmp.entry->setData(0, Qt::DisplayRole, tmp.name);
tmp.entry->setData(1, Qt::UserRole, tmp.id);
tmp.entry->setData(2, Qt::UserRole, channel);
channelList.push_back(tmp);
i++;
}
// build tree structure
for (auto& it : channelList)
{
if (it.parent == 0)
m_tree->addTopLevelItem(it.entry);
else
{
bool found(false);
for (auto& it2 : channelList)
{
if (it.parent == it2.id)
{
it2.entry->addChild(it.entry);
found = true;
break;
}
}
if (!found)
{
debugPrint(QString("%1: parent %2 not found").arg(it.name).arg(it.parent));
delete it.entry;
}
}
}
// insert clients
for (auto& it : channelList)
{
anyID* clientIDList;
ts3.getChannelClientList(m_SCHID, it.id, &clientIDList);
int i(0);
while (clientIDList[i] != NULL)
{
QTreeWidgetItem* tmp = new QTreeWidgetItem;
tmp->setData(0, Qt::DisplayRole, clientID2Name(m_SCHID, clientIDList[i]));
tmp->setData(1, Qt::UserRole, clientIDList[i]);
tmp->setData(2, Qt::UserRole, client);
it.entry->addChild(tmp);
i++;
}
}
m_tree->expandAll();
connect(m_tree, &QTreeWidget::itemDoubleClicked, this, &OverlayController::treeItemClicked);
m_tree->show();
}
#pragma once
#include "qttsoverlay_global.h"
#include "ts3_functions.h"
#include <QObject>
#include <QString>
#include <QWidget>
#include <QVector>
#include <QLabel>
#include <QTreeWidget>
#define MAXLINES 5
......@@ -14,34 +16,38 @@
#define TIMEOUT 5000
class QTTSOVERLAY_EXPORT OverlayController : QObject
class QTTSOVERLAY_EXPORT OverlayController : public QObject
{
Q_OBJECT
public:
OverlayController();
OverlayController(const struct TS3Functions funcs, quint64 serverConnectionHandlerID);
~OverlayController();
private:
const struct TS3Functions ts3;
quint64 m_SCHID;
int m_screenWidth;
int m_screenHeight;
int m_speakerOffset;
quint64 m_currentChannel = 0;
QLabel* m_debugWindow;
QVector<QWidget*> m_speakers;
QVector<QWidget*> m_msgLines;
QTreeWidget* m_tree;
private:
void deleteChatLine(QWidget* line);
private slots:
void treeItemClicked(QTreeWidgetItem * item, int column);
public:
void addChatLine(QString message);
void addSpeaker(QString name);
void removeSpeaker(QString name);
void debugPrint(QString text);
void reset();
void setCurrentChannel(quint64 id);
quint64 getCurrentChannel() const;
void updateChannelList();
void displayChannelList();
};
......@@ -20,7 +20,7 @@
#include "teamspeak/clientlib_publicdefinitions.h"
#include "ts3_functions.h"
#include "plugin.h"
#include "overlaycontroller.h"
#include <QMap>
#pragma region defines, global variables
......@@ -44,7 +44,7 @@ static struct TS3Functions ts3Functions;
static char* pluginID = NULL;
OverlayController* controller;
QMap<uint64, OverlayController*> g_serverList;
#ifdef _WIN32
/* Helper function to convert wchar_T to Utf-8 encoded strings on Windows */
......@@ -119,8 +119,6 @@ void ts3plugin_setFunctionPointers(const struct TS3Functions funcs) {
*/
int ts3plugin_init() {
controller = new OverlayController;
return 0; /* 0 = success, 1 = failure, -2 = failure but client will not show a "failed to load" warning */
/* -2 is a very special case and should only be used if a plugin displays a dialog (e.g. overlay) asking the user to disable
* the plugin again, avoiding the show another dialog by the client telling the user the plugin failed to load.
......@@ -130,7 +128,9 @@ int ts3plugin_init() {
/* Custom code called right before the plugin is unloaded */
void ts3plugin_shutdown() {
delete controller;
while (g_serverList.size() > 0)
delete g_serverList.erase(g_serverList.begin()).value();
/*
* Note:
......@@ -227,6 +227,19 @@ int ts3plugin_requestAutoload() {
* Following functions are helper for the callbacks.
*/
#pragma region helper functions
uint64 getCurrentChannel(uint64 serverConnectionHandlerID)
{
uint64 curChannel;
anyID curClient;
ts3Functions.getClientID(serverConnectionHandlerID, &curClient);
ts3Functions.getChannelOfClient(serverConnectionHandlerID, curClient, &curChannel);
return curChannel;
}
QString clientID2Name(uint64 serverConnectionHandlerID, anyID clientID)
{
char* tmp = NULL;
......@@ -253,17 +266,21 @@ QString channelID2Name(uint64 serverConnectionHandlerID, uint64 channelID)
return name;
}
void updateChannelList(uint64 serverConnectionHandlerID)
OverlayController* getController(uint64 serverConnectionHandlerID)
{
anyID* idList;
ts3Functions.getChannelClientList(serverConnectionHandlerID, controller->getCurrentChannel(), &idList);
auto tmp = g_serverList.find(serverConnectionHandlerID);
int i(0);
while (idList[i] != NULL)
controller->debugPrint(clientID2Name(serverConnectionHandlerID, idList[i++]));
if (tmp == g_serverList.end())
{
OverlayController* ret = new OverlayController(ts3Functions, serverConnectionHandlerID);
g_serverList.insert(serverConnectionHandlerID, ret);
return ret;
}
return tmp.value();
}
#pragma endregion
/************************** TeamSpeak callbacks ***************************/
......@@ -280,15 +297,21 @@ void ts3plugin_onConnectStatusChangeEvent(uint64 serverConnectionHandlerID, int
if (newStatus == STATUS_DISCONNECTED)
{
controller->reset();
auto tmp = g_serverList.take(serverConnectionHandlerID);
delete tmp;
}
else if (newStatus == STATUS_CONNECTION_ESTABLISHED)
{
g_serverList.insert(serverConnectionHandlerID, new OverlayController(ts3Functions, serverConnectionHandlerID));
char* name;
ts3Functions.getServerVariableAsString(serverConnectionHandlerID, VIRTUALSERVER_NAME, &name);
controller->debugPrint(QString("Welcome at: %1").arg(name));
getController(serverConnectionHandlerID)->debugPrint(QString("Welcome at: %1").arg(name));
ts3Functions.freeMemory(name);
getController(serverConnectionHandlerID)->displayChannelList();
}
}
......@@ -315,6 +338,8 @@ void ts3plugin_onUpdateClientEvent(uint64 serverConnectionHandlerID, anyID clien
void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientID, uint64 oldChannelID, uint64 newChannelID, int visibility, const char* moveMessage) {
getController(serverConnectionHandlerID)->updateChannelList();
QString name = clientID2Name(serverConnectionHandlerID, clientID);
QString oldChannel = channelID2Name(serverConnectionHandlerID, oldChannelID);
......@@ -324,23 +349,17 @@ void ts3plugin_onClientMoveEvent(uint64 serverConnectionHandlerID, anyID clientI
anyID myID;
ts3Functions.getClientID(serverConnectionHandlerID, &myID);
if (clientID == myID)
{
controller->setCurrentChannel(newChannelID);
updateChannelList(serverConnectionHandlerID);
}
if (!name.isEmpty() && !oldChannel.isEmpty() && !newChannel.isEmpty())
{
// joined my channel
if (newChannelID == controller->getCurrentChannel())
controller->addChatLine(QString("<font color=\"#00FF00\">%1 <font size=\"-5\">entered from</font> %2</font>").arg(name).arg(oldChannel));
if (newChannelID == getCurrentChannel(serverConnectionHandlerID))
getController(serverConnectionHandlerID)->addChatLine(QString("<font color=\"#00FF00\">%1 <font size=\"-5\">entered from</font> %2</font>").arg(name).arg(oldChannel));
// quit my channel
else if (oldChannelID == controller->getCurrentChannel())
controller->addChatLine(QString("<font color=\"#FF0000\">%1 <font size=\"-5\">left to</font> %2</font>").arg(name).arg(newChannel));
else if (oldChannelID == getCurrentChannel(serverConnectionHandlerID))
getController(serverConnectionHandlerID)->addChatLine(QString("<font color=\"#FF0000\">%1 <font size=\"-5\">left to</font> %2</font>").arg(name).arg(newChannel));
// somewhere else
else
controller->addChatLine(QString("<font size=\"-5\">%1 moved from %2 to %3</font>").arg(name).arg(oldChannel).arg(newChannel));
getController(serverConnectionHandlerID)->addChatLine(QString("<font size=\"-5\">%1 moved from %2 to %3</font>").arg(name).arg(oldChannel).arg(newChannel));
}
}
......@@ -381,7 +400,7 @@ void ts3plugin_onServerStopEvent(uint64 serverConnectionHandlerID, const char* s
int ts3plugin_onTextMessageEvent(uint64 serverConnectionHandlerID, anyID targetMode, anyID toID, anyID fromID, const char* fromName, const char* fromUniqueIdentifier, const char* message, int ffIgnored) {
controller->addChatLine(QString("<font size=\"-5\">%1</font> %2").arg(fromName).arg(message));
getController(serverConnectionHandlerID)->addChatLine(QString("<font size=\"-5\">%1</font> %2").arg(fromName).arg(message));
return 0; /* 0 = handle normally, 1 = client will ignore the text message */
}
......@@ -392,9 +411,9 @@ void ts3plugin_onTalkStatusChangeEvent(uint64 serverConnectionHandlerID, int sta
if (ts3Functions.getClientDisplayName(serverConnectionHandlerID, clientID, name, 512) == ERROR_ok)
{
if (status == STATUS_TALKING)
controller->addSpeaker(name);
getController(serverConnectionHandlerID)->addSpeaker(name);
else
controller->removeSpeaker(name);
getController(serverConnectionHandlerID)->removeSpeaker(name);
}
}
......@@ -461,7 +480,7 @@ void ts3plugin_onClientBanFromServerEvent(uint64 serverConnectionHandlerID, anyI
int ts3plugin_onClientPokeEvent(uint64 serverConnectionHandlerID, anyID fromClientID, const char* pokerName, const char* pokerUniqueIdentity, const char* message, int ffIgnored) {
controller->addChatLine(QString("<font color=\"#00FFFF\"><font size=\"-5\">%1</font> Wake up! %2</font>").arg(pokerName).arg(message));
getController(serverConnectionHandlerID)->addChatLine(QString("<font color=\"#00FFFF\"><font size=\"-5\">%1</font> Wake up! %2</font>").arg(pokerName).arg(message));
return 0; /* 0 = handle normally, 1 = client will ignore the poke */
}
......
......@@ -6,6 +6,8 @@
#ifndef PLUGIN_H
#define PLUGIN_H
#include <qstring.h>
#include "overlaycontroller.h"
#ifdef WIN32
#define PLUGINS_EXPORTDLL __declspec(dllexport)
......@@ -144,4 +146,9 @@ extern "C" {
}
#endif
uint64 getCurrentChannel(uint64 serverConnectionHandlerID);
QString clientID2Name(uint64 serverConnectionHandlerID, anyID clientID);
QString channelID2Name(uint64 serverConnectionHandlerID, uint64 channelID);
OverlayController* getController(uint64 serverConnectionHandlerID);
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment