The complete source code of IdealIRC http://www.idealirc.org/
 
 
 
 
idealirc/IdealIRC/MdiManager.cpp

329 lines
9.2 KiB

/*
* IdealIRC - Internet Relay Chat client
* Copyright (C) 2019 Tom-Andre Barstad
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "IWin/IWinStatus.h"
#include "IWin/IWinChannel.h"
#include "IWin/IWinPrivate.h"
#include "MdiManager.h"
#include "ConfigMgr.h"
#include <QApplication>
#include <QDebug>
namespace {
constexpr int WINDOW_DEFAULT_WIDTH = 800;
constexpr int WINDOW_DEFAULT_HEIGHT = 600;
constexpr int WINDOW_STEP = 30;
constexpr int WINDOW_STEP_RESET_POSITION = 400;
constexpr int WINDOW_STEP_RESET_ADJUST = 60;
}
MdiManager* MdiManager::m_instance{ nullptr };
MdiManager::MdiManager(QMdiArea& mdiArea, QToolBar& buttonBar, QSystemTrayIcon& trayIcon)
: m_mdiArea(mdiArea)
, trayIcon(trayIcon)
, m_bbMgr(&buttonBar)
{
m_instance = this;
connect(&m_mdiArea, &QMdiArea::subWindowActivated, this, &MdiManager::subwinActivated);
connect(&m_bbMgr, &ButtonbarMgr::changeWindow, &m_mdiArea, &QMdiArea::setActiveSubWindow);
}
MdiManager& MdiManager::instance()
{
return *m_instance;
}
MdiManager::ButtonBarEntry::ButtonBarEntry(QAction* button_, const QString& buttonText, QMdiSubWindow* parent)
: subwin(parent)
, button(button_)
{
menu = new QMenu(parent);
menuHead = menu->addAction(buttonText);
QFont f = menuHead->font();
f.setBold(true);
menuHead->setFont(f);
menuHead->setDisabled(true);
menuSep = menu->addSeparator();
menuClose = menu->addAction(tr("Close"));
connect(menuClose, &QAction::triggered, [&](bool){
subwin->close();
});
}
IWin* MdiManager::createSubwindow(IWin* parent, const QString& buttonText, IWin::Type windowType, bool activate)
{
IWin* basePtr{ nullptr };
IWinStatus* statusParent{ nullptr };
QMdiSubWindow* mdiwin{ nullptr };
if (parent && parent->getType() == IWin::Type::Status)
statusParent = dynamic_cast<IWinStatus*>(parent);
switch (windowType) {
case IWin::Type::Status:
basePtr = new IWinStatus(buttonText);
m_activeStatus = dynamic_cast<IWinStatus*>(basePtr);
break;
case IWin::Type::Channel:
basePtr = new IWinChannel(statusParent, buttonText);
break;
case IWin::Type::Private:
basePtr = new IWinPrivate(statusParent, buttonText);
break;
case IWin::Type::Custom:
[[fallthrough]]; // Use createCustomSubwindow; treat this as an error.
case IWin::Type::Undefined:
break;
}
if (!basePtr) {
qWarning() << "Failed to create subwindow of type" << IWin::TypeString[windowType] << "with button text" << buttonText;
return nullptr;
}
connect(basePtr, &IWin::aboutToClose,
this, &MdiManager::subwinAboutToClose);
mdiwin = m_mdiArea.addSubWindow(basePtr, Qt::SubWindow);
mdiwin->setAttribute(Qt::WA_DeleteOnClose);
m_bbMgr.addButton(basePtr, mdiwin);
QRect spawnCoord = generateSpawnCoordinates();
mdiwin->setGeometry(spawnCoord);
qInfo() << "Created a subwindow of type" << IWin::TypeString[windowType] << "with button text" << buttonText;
if (!m_active || m_active->isMaximized())
mdiwin->showMaximized();
else
mdiwin->show();
if (!activate) {
m_mdiArea.activatePreviousSubWindow();
mdiwin->lower();
}
return basePtr;
}
IWin* MdiManager::currentWindow() const
{
return m_active;
}
IWinStatus* MdiManager::currentStatus() const
{
return m_activeStatus;
}
IWin* MdiManager::findWindow(IWin* statusParent, const QString& buttonText)
{
for (QMdiSubWindow* mdiwin : m_mdiArea.subWindowList()) {
IWin* subwin = dynamic_cast<IWin*>(mdiwin->widget());
if (subwin->getParent() == statusParent && buttonText.compare(subwin->getButtonText(), Qt::CaseInsensitive) == 0) {
subwin->setButtonText(buttonText);
renameWindowButton(subwin, buttonText);
return subwin;
}
}
return nullptr;
}
QMdiSubWindow* MdiManager::toMdiwin(IWin* win)
{
for (QMdiSubWindow* mdiwin : m_mdiArea.subWindowList()) {
if (mdiwin->widget() == win)
return mdiwin;
}
return nullptr;
}
QList<QMdiSubWindow*> MdiManager::mdiChildrenOf(const IWin* statusParent, IWin::Type type) const
{
QList<QMdiSubWindow*> retlist;
for (QMdiSubWindow* mdiwin : m_mdiArea.subWindowList()) {
IWin* subwin = dynamic_cast<IWin*>(mdiwin->widget());
if (type != IWin::Type::Undefined && subwin->getType() != type)
continue;
if (subwin->getParent() == statusParent)
retlist.push_back(mdiwin);
}
return retlist;
}
QList<IWin*> MdiManager::childrenOf(const IWin* statusParent, IWin::Type type) const
{
QList<IWin*> retlist;
QList<QMdiSubWindow*> subwinList = mdiChildrenOf(statusParent, type);
for (QMdiSubWindow* subwin : subwinList)
retlist.push_back(qobject_cast<IWin*>(subwin->widget()));
return retlist;
}
void MdiManager::showTrayInfo(const QString& title, const QString& message)
{
showTray(title, message, QSystemTrayIcon::MessageIcon::Information);
}
void MdiManager::showTrayWarn(const QString& title, const QString& message)
{
showTray(title, message, QSystemTrayIcon::MessageIcon::Warning);
}
int MdiManager::connectionsOnlineCount() const
{
int c = 0;
for (QMdiSubWindow* mdiwin : m_mdiArea.subWindowList()) {
IWin* subwin = dynamic_cast<IWin*>(mdiwin->widget());
if (subwin->getType() != IWin::Type::Status)
continue;
IWinStatus* status = dynamic_cast<IWinStatus*>(subwin);
if (status->getConnection().isOnline())
++c;
}
return c;
}
void MdiManager::broadcastProgramExit()
{
for (QMdiSubWindow* mdiwin : m_mdiArea.subWindowList()) {
IWin* subwin = dynamic_cast<IWin*>(mdiwin->widget());
if (subwin->getType() != IWin::Type::Status)
continue;
IWinStatus* status = dynamic_cast<IWinStatus*>(subwin);
if (status->getConnection().isOnline()) {
connect(&status->getConnection(), &IRC::readyForExit, [this](){
if (connectionsOnlineCount() == 0)
emit readyForExit();
});
ConfigMgr& conf = ConfigMgr::instance();
status->getConnection().disconnectForExit(conf.common("QuitMessage"));
}
}
}
void MdiManager::renameWindowButton(IWin* window, const QString& text)
{
m_bbMgr.reloadButtonName(window, text);
}
void MdiManager::print(IWinStatus* parent, const QString& target, const PrintType ptype, const QString& text)
{
IWin* subwin = findWindow(parent, target);
if (!subwin || !subwin->print(ptype, text)) {
if (ptype != PrintType::CTCP)
parent->print(ptype, QStringLiteral("[%1] %2").arg(target).arg(text));
else
parent->print(ptype, text);
}
}
void MdiManager::print(const QString& target, const PrintType ptype, const QString& text)
{
print(m_activeStatus, target, ptype, text);
}
void MdiManager::printToActive(IWinStatus* parent, const PrintType ptype, const QString& text)
{
if (!m_active)
parent->print(ptype, text);
else if (m_active->getParent() != parent)
parent->print(ptype, text);
else
m_active->print(ptype, text);
}
void MdiManager::printToTypes(IWinStatus* parent, const IWin::Type toType, const PrintType ptype, const QString& text)
{
for (QMdiSubWindow* mdiwin : m_mdiArea.subWindowList()) {
IWin* subwin = qobject_cast<IWin*>(mdiwin->widget());
if (subwin->getParent() == parent && subwin->getType() == toType)
subwin->print(ptype, text);
}
}
void MdiManager::printToAll(IWinStatus* parent, const PrintType ptype, const QString& text)
{
for (QMdiSubWindow* mdiwin : m_mdiArea.subWindowList()) {
IWin* subwin = qobject_cast<IWin*>(mdiwin->widget());
if (subwin->getParent() == parent || subwin == parent)
subwin->print(ptype, text);
}
}
void MdiManager::showTray(const QString& title, const QString& message, QSystemTrayIcon::MessageIcon icon)
{
if (QApplication::activeWindow() || QApplication::focusWidget()) return;
ConfigMgr& conf = ConfigMgr::instance();
if (conf.common("TrayNotify") != "1") return;
int delay = conf.common("TrayNotifyDelay").toInt();
trayIcon.showMessage(title, message, icon, delay*1000);
}
void MdiManager::subwinAboutToClose(IWin* who)
{
qInfo() << "Closing" << who;
m_bbMgr.delButton(who);
}
void MdiManager::subwinActivated(QMdiSubWindow* window)
{
if (!window) return;
IWin* cw = dynamic_cast<IWin*>(window->widget());
qInfo() << "Activated:" << cw;
if (!cw) {
qWarning() << "NULL window!";
return;
}
m_bbMgr.subwinActivated(m_active, cw);
m_active = cw;
if (cw->getParent() && cw->getParent()->getType() == IWin::Type::Status)
m_activeStatus = dynamic_cast<IWinStatus*>(cw->getParent());
else if (cw->getType() == IWin::Type::Status)
m_activeStatus = qobject_cast<IWinStatus*>(cw);
emit subwindowSwitched();
}
QRect MdiManager::generateSpawnCoordinates()
{
QRect rectangle(nextXY, nextXY, WINDOW_DEFAULT_WIDTH, WINDOW_DEFAULT_HEIGHT);
nextXY += WINDOW_STEP;
if (nextXY > WINDOW_STEP_RESET_POSITION) {
nextXYadjust += WINDOW_STEP_RESET_ADJUST;
if (nextXYadjust > WINDOW_STEP_RESET_POSITION)
nextXYadjust = 0;
nextXY = nextXYadjust;
}
return rectangle;
}