Skip to content
Snippets Groups Projects
Select Git revision
  • 1fe231e5b970ce12138a03bddbc90fb64042772f
  • master default protected
2 results

overlaycontroller.cpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    overlaycontroller.cpp 7.79 KiB
    #include "overlaycontroller.h"
    #include <QDesktopWidget>
    #include <QStringList>
    #include "plugin.h"
    #include <qdebug.h>
    #include "teamspeak\public_errors.h"
    
    
    //#ifndef _DEBUG
    //#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
    //#endif
    
    struct channelInfo {
    	uint64 id;
    	QString name;
    	uint64 parent;
    	QTreeWidgetItem* entry;
    	int order;
    };
    
    enum nodeType {
    	channel,
    	client,
    	spacer
    };
    
    Q_DECLARE_METATYPE(nodeType);
    
    OverlayController::OverlayController(const struct TS3Functions funcs, quint64 serverConnectionHandlerID) : QObject(), ts3(funcs)
    {
    	QDesktopWidget desktop;
    
    	m_screenHeight = desktop.screenGeometry().height();
    	m_screenWidth = desktop.screenGeometry().width();
    
    	m_speakerOffset = 0;
    
    	m_debugWindow = new QLabel;
    	m_debugWindow->setGeometry(320, 200, 750, 500);
    	m_debugWindow->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    	m_debugWindow->show();
    
    	m_SCHID = serverConnectionHandlerID;
    
    	m_tree = new ChannelListWidget;
    }
    
    OverlayController::~OverlayController()
    {
    	for (auto &it : m_speakers)
    		delete it;
    	m_speakers.clear();
    
    	for (auto &it : m_msgLines)
    		delete it;
    	m_msgLines.clear();
    
    	delete m_debugWindow;
    	delete m_tree;
    }
    
    void OverlayController::deleteChatLine(QWidget * line, QTimer *timer)
    {
    	//TODO: delete the given line instead of the last
    	int index = m_msgLines.indexOf(line);
    	if (index != -1)
    	{
    		delete m_msgLines.at(index);
    		m_msgLines.remove(index);
    	}
    
    	if (timer)
    		delete timer;
    }
    
    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
    	QWidget* w = new QWidget;
    	QLabel* newChatLine = new QLabel(w);
    
    	w->setAttribute(Qt::WA_TranslucentBackground);
    	w->setAttribute(Qt::WA_ShowWithoutActivating);
    	w->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowTransparentForInput | Qt::SplashScreen);
    
    	newChatLine->setText(message);
    	newChatLine->setStyleSheet("padding:2px;border-radius:5px;border-style:solid;border-width:1px;border-color:rgb(100,100,100);font:bold; font-size:15px;background-color:rgba(50,50,50,150); color:rgb(255,255,255);");
    	newChatLine->adjustSize();
    
    	newChatLine->setAttribute(Qt::WA_ShowWithoutActivating);
    	newChatLine->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::WindowTransparentForInput);
    	newChatLine->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
    
    	w->adjustSize();
    	w->setGeometry(BORDEROFFSET, BORDEROFFSET, w->size().width(), w->size().height() + SPACING);
    
    	newChatLine->show();
    	w->show();
    
    	// move old messages down
    	for (auto &it : m_msgLines)
    		it->setGeometry(it->geometry().x(), it->geometry().y() + w->size().height(), it->geometry().width(), it->geometry().height());
    
    	// inseart new chat line
    	m_msgLines.push_front(w);
    
    	// limit the number of lines
    	if (m_msgLines.size() > MAXLINES)
    		deleteChatLine(m_msgLines.last());
    
    	// hide after time
    	QTimer* timer = new QTimer(this);
    	timer->setSingleShot(true);
    	timer->setInterval(TIMEOUT);
    	connect(timer, &QTimer::timeout, [=]() {deleteChatLine(w, timer);});
    	timer->start();
    }
    
    void OverlayController::addSpeaker(QString name)
    {
    	int labelWidth = 0;
    	QWidget* w = new QWidget;
    	QLabel* newSpeaker = new QLabel(w);
    
    	w->setAttribute(Qt::WA_TranslucentBackground);
    	w->setAttribute(Qt::WA_ShowWithoutActivating);
    	w->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowTransparentForInput | Qt::SplashScreen);
    	w->setObjectName(name);
    
    	newSpeaker->setText(name);
    	newSpeaker->setStyleSheet("padding:2px;border-radius:5px;border-style:solid;border-width:1px;border-color:rgb(100,100,100);font:bold; font-size:15px;background-color:rgba(50,50,50,150); color:rgb(255,255,255);");
    	newSpeaker->adjustSize();
    	
    	newSpeaker->setAttribute(Qt::WA_ShowWithoutActivating);
    	newSpeaker->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::WindowTransparentForInput);
    	newSpeaker->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
    
    	w->adjustSize();
    	w->setGeometry(BORDEROFFSET + m_speakerOffset, m_screenHeight - BORDEROFFSET - w->size().height(), w->size().width() + SPACING, w->size().height());
    	labelWidth = w->geometry().width();
    
    	newSpeaker->show();
    	w->show();
    
    	m_speakerOffset += labelWidth;
    
    	m_speakers.push_back(w);
    }
    
    void OverlayController::removeSpeaker(QString name)
    {
    	int index = -1;
    	int labelWidth = 0;
    
    	// move all speaker to the left side and find the one to delete
    	for (int i = 0; i < m_speakers.size(); i++)
    	{
    		QWidget* it = m_speakers.at(i);
    
    		it->setGeometry(it->geometry().x() - labelWidth, it->geometry().y(), it->geometry().width(), it->geometry().height());
    
    		if (it->objectName() == name)
    		{
    			labelWidth = it->geometry().width();
    			m_speakerOffset -= labelWidth;
    			index = i;
    			delete it;
    		}
    	}
    
    	// remove the deleted label from the list
    	if (index != -1)
    		m_speakers.remove(index);
    }
    
    void OverlayController::debugPrint(QString text)
    {
    	m_debugWindow->setText(text + "\n" + m_debugWindow->text());
    }
    
    void OverlayController::reset()
    {
    	for (auto &it : m_speakers)
    		delete it;
    	m_speakers.clear();
    
    	for (auto &it : m_msgLines)
    		delete it;
    	m_msgLines.clear();
    
    	m_speakerOffset = 0;
    }
    
    void OverlayController::updateChannelList()
    {
    	if (m_tree->isVisible())
    		displayChannelList();
    }
    
    void OverlayController::displayChannelList()
    {
    	while (int nb = m_tree->getTree()->topLevelItemCount())
    	{
    		auto item = m_tree->getTree()->takeTopLevelItem(nb - 1);
    		disconnect(m_tree->getTree(), &QTreeWidget::itemDoubleClicked, this, &OverlayController::treeItemClicked);
    		delete item;
    	}
    
    	uint64* channelIDList;
    	if (ts3.getChannelList(m_SCHID, &channelIDList) != ERROR_ok)
    		return;
    
    	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.getChannelVariableAsInt(m_SCHID, tmp.id, CHANNEL_ORDER, &tmp.order);
    		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);
    		if (tmp.name.startsWith('[') && tmp.name.contains("spacer"))
    			tmp.entry->setData(2, Qt::UserRole, spacer);
    		else
    			tmp.entry->setData(2, Qt::UserRole, channel);
    
    		channelList.push_back(tmp);
    		i++;
    	}
    
    	qSort(channelList.begin(), channelList.end(), [](const channelInfo& a, const channelInfo& b) { return a.order < b.order; });
    
    	// build tree structure
    	for (auto& it : channelList)
    	{
    		if (it.parent == 0)
    			m_tree->getTree()->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->getTree()->expandAll();
    	connect(m_tree->getTree(), &QTreeWidget::itemDoubleClicked, this, &OverlayController::treeItemClicked);
    	m_tree->getTree()->adjustSize();
    	m_tree->adjustSize();
    	m_tree->show();
    }