The complete source code of IdealIRC
http://www.idealirc.org/
219 lines
6.1 KiB
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);
|
|
}
|
|
|