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

219 lines
6.1 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 "IWinChannel.h"
#include "IWinStatus.h"
#include "MdiManager.h"
#include "Commands.h"
#include "Script/Manager.h"
#include "IRCClient/IRCChannel.h"
#include <ConfigMgr.h>
#include <QHeaderView>
IWinChannel::IWinChannel(IWinStatus* statusParent, const QString& channelName)
: IWin(IWin::Type::Channel, statusParent)
, status(statusParent)
, connection(statusParent->getConnection())
{
setButtonText(channelName);
splitter = new QSplitter();
v_layout = new QVBoxLayout();
view = new IIRCView();
listbox = new IListWidget();
input = new ILineEdit();
v_layout->setMargin(0);
v_layout->setSpacing(2);
splitter->addWidget(view);
splitter->addWidget(listbox);
v_layout->addWidget(splitter);
v_layout->addWidget(input);
setLayout(v_layout);
setTabOrder(input, view);
setTabOrder(view, listbox);
splitter->setStretchFactor(0, 8);
splitter->setStretchFactor(1, 1);
view->setFocusPolicy(Qt::FocusPolicy::NoFocus);
listbox->setFocusPolicy(Qt::FocusPolicy::NoFocus);
listbox->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
listbox->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
nlControl = new NicklistController(listbox, connection, channelName, this);
connect(&connection, &IRC::memberListReloaded,
this, &IWinChannel::memberListReloaded);
connect(&connection, &IRC::memberListClearedForAll,
this, &IWinChannel::memberListCleared);
connect(&connection, &IRC::memberAdded,
this, &IWinChannel::memberListAdd);
connect(&connection, &IRC::memberChanged,
this, &IWinChannel::memberListUpdateMember);
connect(&connection, &IRC::memberRemoved,
this, &IWinChannel::memberListRemoveMember);
connect(input, &ILineEdit::returnPressed,
this, &IWinChannel::inputEnter);
connect(listbox, &IListWidget::itemDoubleClicked,
this, &IWinChannel::listboxDoubleclick);
connect(view, &IIRCView::customContextMenuRequested, [this,channelName](const QPoint& point){
menuSymbols.clear();
menuSymbols.set("channel", channelName.toStdString());
ScriptManager::instance()->contextMenuPopup(ScriptMenuType::Channel, mapToGlobal(point), menuSymbols);
});
connect(listbox, &IListWidget::customContextMenuRequested, [this,channelName](const QPoint& pos){
menuSymbols.clear();
menuSymbols.set("channel", channelName.toStdString());
ValueArray members;
auto items = listbox->selectedItems();
if (items.isEmpty()) return;
int idx = 0;
for (auto* item : items) {
QString name = item->text();
if (isUserModePrefix(name[0]))
name.remove(0, 1);
members.emplace(std::to_string(idx++), new ValueHolder(name.toStdString()));
}
menuSymbols.set("selected", std::move(members));
QPoint posAdj = mapToGlobal(pos);
posAdj.setX(posAdj.x() + view->width() + splitter->handleWidth());
ScriptManager::instance()->contextMenuPopup(ScriptMenuType::Memberlist, posAdj, menuSymbols);
});
}
bool IWinChannel::print(const PrintType ptype, const QString& text)
{
view->print(ptype, text);
ConfigMgr& conf = ConfigMgr::instance();
if (conf.logging("Channels") == "1") {
QString path = conf.logging("Path");
if (path.isEmpty())
return true;
path += "/" + getButtonText() + ".log";
QByteArray out;
out.append(IIRCView::formatType(ptype, text));
out.append("\n");
QFile f(path);
if (!f.open(QIODevice::WriteOnly | QIODevice::Append))
return true;
f.write(out);
f.close();
}
return true;
}
void IWinChannel::refreshWindowTitle()
{
auto chan = connection.getChannel(getButtonText().toStdString());
const auto& topic = chan->topic();
QString title;
if (topic.empty())
title = getButtonText();
else
title = QStringLiteral("%1 (%2)")
.arg(getButtonText())
.arg(topic.c_str());
setWindowTitle(title);
}
void IWinChannel::resetNicklist()
{
nlControl->clear();
}
void IWinChannel::inputEnter()
{
QString text = input->text();
input->clear();
InputHandler inHndl(connection);
inHndl.parse(*this, text);
}
void IWinChannel::listboxDoubleclick(QListWidgetItem* item)
{
if (!item)
return;
QString nickname = item->text();
if (isUserModePrefix(nickname[0]))
nickname = nickname.mid(1);
input->setFocus();
IWin* subwin = status->createPrivateWindow(nickname);
subwin->refreshWindowTitle();
}
bool IWinChannel::isUserModePrefix(QChar c)
{
const auto& isupport = connection.isupport();
const auto& prefix = isupport.at("PREFIX"); // Always present in the isupport map.
auto begin = std::find(prefix.begin(), prefix.end(), ')') + 1;
return std::find(begin, prefix.end(), c.toLatin1()) != prefix.end();
}
void IWinChannel::closeEvent(QCloseEvent* evt)
{
connection.command(Command::IRC::PART, { getButtonText().toStdString() }, "");
IWin::closeEvent(evt);
}
void IWinChannel::memberListReloaded(const QString& channel)
{
if (channel != getButtonText()) return;
nlControl->reload();
}
void IWinChannel::memberListCleared()
{
nlControl->clear();
}
void IWinChannel::memberListAdd(const QString& channel, const IRCMemberEntry& member)
{
if (channel != getButtonText()) return;
nlControl->addMember(member);
}
void IWinChannel::memberListUpdateMember(const QString& nickname, const IRCMemberEntry& member)
{
nlControl->updateMember(nickname, member);
}
void IWinChannel::memberListRemoveMember(const QString& channel, const IRCMemberEntry& member)
{
if (channel != getButtonText()) return;
nlControl->removeMember(member);
}