From 93e4840ec43df2be135032d2428a2cf8797cd391 Mon Sep 17 00:00:00 2001 From: Tomatix Date: Thu, 21 Oct 2021 15:51:25 +0200 Subject: [PATCH] #17 Tabs to spaces --- CMakeLists.txt | 12 +- ICommand/CommandData.cpp | 60 +- ICommand/CommandData.h | 16 +- ICommand/Commands.h | 18 +- ICommand/External/kick.cpp | 20 +- ICommand/External/notice.cpp | 28 +- ICommand/External/privmsg.cpp | 30 +- ICommand/ICommand.cpp | 1116 +++++------ ICommand/ICommand.h | 44 +- ICommand/ICommandPriv.cpp | 6 +- ICommand/ICommandPriv.h | 12 +- ICommand/Internal/me.cpp | 26 +- IConfig/ColorConfig.cpp | 552 +++--- IConfig/ColorConfig.h | 74 +- IConfig/IConfig.cpp | 178 +- IConfig/IConfig.h | 52 +- IConfig/IConfigLogging.cpp | 100 +- IConfig/IConfigLogging.h | 30 +- IConfig/IConfigOptions.cpp | 154 +- IConfig/IConfigOptions.h | 66 +- IConfig/IConfigServers.cpp | 128 +- IConfig/IConfigServers.h | 42 +- IConfig/ServerEditor.cpp | 458 ++--- IConfig/ServerEditor.h | 60 +- IConfig/ServerMgr.cpp | 60 +- IConfig/ServerMgr.h | 6 +- IConfig/ServerModel.cpp | 256 ++- IConfig/ServerModel.h | 16 +- IRCClient/Commands.h | 108 +- IRCClient/DCC.cpp | 260 +-- IRCClient/DCC.h | 80 +- IRCClient/IRCBase.cpp | 376 ++-- IRCClient/IRCBase.h | 208 +- IRCClient/IRCBasePriv.h | 28 +- IRCClient/IRCChannel.cpp | 50 +- IRCClient/IRCChannel.h | 40 +- IRCClient/IRCError.cpp | 198 +- IRCClient/IRCError.h | 72 +- IRCClient/IRCMember.cpp | 24 +- IRCClient/IRCMember.h | 20 +- IRCClient/IRCMemberEntry.cpp | 60 +- IRCClient/IRCMemberEntry.h | 18 +- IRCClient/IRCPrefix.cpp | 96 +- IRCClient/IRCPrefix.h | 58 +- IRCClient/Utilities.cpp | 156 +- IWin/IWin.cpp | 22 +- IWin/IWin.h | 60 +- IWin/IWinChannel.cpp | 224 +-- IWin/IWinChannel.h | 50 +- IWin/IWinPrivate.cpp | 102 +- IWin/IWinPrivate.h | 22 +- IWin/IWinStatus.cpp | 216 +-- IWin/IWinStatus.h | 50 +- IWin/NicklistController.cpp | 272 +-- IWin/NicklistController.h | 34 +- IdealIRC/AboutIIRC.cpp | 28 +- IdealIRC/AboutIIRC.h | 8 +- IdealIRC/ButtonbarMgr.cpp | 394 ++-- IdealIRC/ButtonbarMgr.h | 100 +- IdealIRC/CMakeLists.txt | 6 +- IdealIRC/ConfigMgr.cpp | 18 +- IdealIRC/ConfigMgr.h | 48 +- IdealIRC/IRC.cpp | 396 ++-- IdealIRC/IRC.h | 106 +- IdealIRC/IdealIRC.cpp | 254 +-- IdealIRC/IdealIRC.h | 56 +- IdealIRC/IniFile.h | 8 +- IdealIRC/InputHandler.cpp | 76 +- IdealIRC/InputHandler.h | 12 +- IdealIRC/MdiManager.cpp | 342 ++-- IdealIRC/MdiManager.h | 94 +- IdealIRC/ScriptEvent.h | 42 +- IdealIRC/main.cpp | 10 +- Script/Builtin/Builtin.cpp | 174 +- Script/Builtin/DialogUtils.cpp | 254 +-- Script/Builtin/Error.cpp | 64 +- Script/Builtin/GeneralUtils.cpp | 204 +- Script/Builtin/ListUtils.cpp | 258 +-- Script/Builtin/MapUtils.cpp | 86 +- Script/Builtin/Mathematics.cpp | 694 +++---- Script/Builtin/StringUtils.cpp | 308 +-- Script/Dialog.cpp | 194 +- Script/Dialog.h | 106 +- Script/Manager.cpp | 368 ++-- Script/Manager.h | 116 +- Script/ManagerListModel.cpp | 124 +- Script/ManagerListModel.h | 24 +- Script/Menu.cpp | 114 +- Script/Menu.h | 70 +- Script/ParserOperator.h | 30 +- Script/ParserToken.cpp | 124 +- Script/ParserToken.h | 42 +- Script/Script.cpp | 1308 ++++++------- Script/Script.h | 78 +- Script/SymbolScope.cpp | 110 +- Script/SymbolScope.h | 70 +- Script/Tokenizer.cpp | 1720 ++++++++--------- Script/Tokenizer.h | 50 +- Script/Tokens.cpp | 260 +-- Script/Tokens.h | 384 ++-- Script/ValueExtract.cpp | 66 +- Script/ValueExtract.h | 24 +- Script/ValueHolder.cpp | 1214 ++++++------ Script/ValueHolder.h | 118 +- Script/main.cpp | 104 +- ScriptDialog/ScriptDialog.cpp | 1922 +++++++++---------- ScriptDialog/ScriptDialog.h | 42 +- ScriptFunctions/RegisterScriptFunctions.cpp | 20 +- ScriptFunctions/ScriptGeneralUtils.cpp | 262 +-- ScriptFunctions/ScriptIRCUtils.cpp | 46 +- Widgets/IIRCView.cpp | 798 ++++---- Widgets/IIRCView.h | 120 +- Widgets/ILineEdit.cpp | 68 +- Widgets/ILineEdit.h | 32 +- Widgets/IListWidget.cpp | 30 +- Widgets/IListWidget.h | 4 +- config.h.in | 18 +- 117 files changed, 10371 insertions(+), 10373 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c2d696..515cbfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,18 +33,18 @@ option(BUILD_DEV_STUFF "Build additional development stuff" OFF) set(IIRC_DEP_INCLUDE "" CACHE PATH "Additional include path (single path only)") set(IIRC_DEP_LIBRARY "" CACHE PATH "Additional library path (single path only)") if (NOT IIRC_DEP_INCLUDE STREQUAL "") - include_directories(${IIRC_DEP_INCLUDE}) - message("Using additional include path: ${IIRC_DEP_INCLUDE}") + include_directories(${IIRC_DEP_INCLUDE}) + message("Using additional include path: ${IIRC_DEP_INCLUDE}") endif() if (NOT IIRC_DEP_LIBRARY STREQUAL "") - link_directories(${IIRC_DEP_LIBRARY}) - message("Using additional library path: ${IIRC_DEP_LIBRARY}") + link_directories(${IIRC_DEP_LIBRARY}) + message("Using additional library path: ${IIRC_DEP_LIBRARY}") endif() # For GCC and Clang, basically. if (UNIX) # set(CMAKE_CXX_FLAGS "-Wall -Werror") - set(CMAKE_CXX_FLAGS "-pthread") + set(CMAKE_CXX_FLAGS "-pthread") endif() # @@ -85,5 +85,5 @@ add_subdirectory(Widgets) add_subdirectory(IdealIRC) # This one builds the binary. if (BUILD_DEV_STUFF) - add_subdirectory(IRCClientSandbox) + add_subdirectory(IRCClientSandbox) endif() diff --git a/ICommand/CommandData.cpp b/ICommand/CommandData.cpp index d30343a..ff9059d 100644 --- a/ICommand/CommandData.cpp +++ b/ICommand/CommandData.cpp @@ -10,48 +10,48 @@ CommandData::CommandData(const QString& line, PredicateList argp, bool repeatLastPredicate) { - for (int i = 0, ppos = 0; i < line.length(); ++i) { - QChar c = line[i]; - if (c == ' ') - continue; - else { - if (ppos >= static_cast(argp.size()) && m_l.at(ppos-1)) { - if (repeatLastPredicate) - ppos = argp.size()-1; - else - break; - } + for (int i = 0, ppos = 0; i < line.length(); ++i) { + QChar c = line[i]; + if (c == ' ') + continue; + else { + if (ppos >= static_cast(argp.size()) && m_l.at(ppos-1)) { + if (repeatLastPredicate) + ppos = argp.size()-1; + else + break; + } - const auto& result = argp[ppos](i, line); - m_l.push_back(result); - ++ppos; - if (!result) - --i; - } - } + const auto& result = argp[ppos](i, line); + m_l.push_back(result); + ++ppos; + if (!result) + --i; + } + } - while (m_l.size() < argp.size()) - m_l.push_back(std::nullopt); + while (m_l.size() < argp.size()) + m_l.push_back(std::nullopt); } int CommandData::size() const { - return m_l.size(); + return m_l.size(); } const std::optional& CommandData::operator[](int idx) { - return m_l.at(idx); + return m_l.at(idx); } std::string CommandData::joinString(char sep) const { - std::string ret; - for (const auto& item : m_l) { - if (!ret.empty()) - ret += sep; - if (item.has_value()) - ret += *item; - } - return ret; + std::string ret; + for (const auto& item : m_l) { + if (!ret.empty()) + ret += sep; + if (item.has_value()) + ret += *item; + } + return ret; } diff --git a/ICommand/CommandData.h b/ICommand/CommandData.h index d29a29e..93350aa 100644 --- a/ICommand/CommandData.h +++ b/ICommand/CommandData.h @@ -15,22 +15,22 @@ #include using PredicateList = std::vector< std::function< - std::optional - (int& idx, const QString& line) - >>; + std::optional + (int& idx, const QString& line) + >>; class ICommand; class CommandData { public: - CommandData(const QString& line, PredicateList argp, bool repeatLastPredicate = false); - int size() const; - const std::optional& operator[](int idx); - std::string joinString(char sep) const; + CommandData(const QString& line, PredicateList argp, bool repeatLastPredicate = false); + int size() const; + const std::optional& operator[](int idx); + std::string joinString(char sep) const; private: - std::vector> m_l; + std::vector> m_l; }; #endif // COMMANDDATA_H diff --git a/ICommand/Commands.h b/ICommand/Commands.h index 32f310c..aae4bd1 100644 --- a/ICommand/Commands.h +++ b/ICommand/Commands.h @@ -10,15 +10,15 @@ namespace Command::Internal { constexpr auto* ACTION = "ACTION"; - constexpr auto* CTCP = "CTCP"; - constexpr auto* CTCPREPLY = "CTCPREPLY"; - constexpr auto* ME = "ME"; - constexpr auto* ECHO = "ECHO"; - constexpr auto* QUERY = "QUERY"; - constexpr auto* MUTERESP = "MUTERESP"; - constexpr auto* UNMUTERESP = "UNMUTERESP"; - constexpr auto* CLEAR = "CLEAR"; - constexpr auto* MSG = "MSG"; + constexpr auto* CTCP = "CTCP"; + constexpr auto* CTCPREPLY = "CTCPREPLY"; + constexpr auto* ME = "ME"; + constexpr auto* ECHO = "ECHO"; + constexpr auto* QUERY = "QUERY"; + constexpr auto* MUTERESP = "MUTERESP"; + constexpr auto* UNMUTERESP = "UNMUTERESP"; + constexpr auto* CLEAR = "CLEAR"; + constexpr auto* MSG = "MSG"; constexpr auto* QUOTE = "QUOTE"; constexpr auto* RAW = "RAW"; constexpr auto* SERVER = "SERVER"; diff --git a/ICommand/External/kick.cpp b/ICommand/External/kick.cpp index a8ef6c7..81cd1a8 100644 --- a/ICommand/External/kick.cpp +++ b/ICommand/External/kick.cpp @@ -11,16 +11,16 @@ using namespace Command::IRC; void ICommandPriv::cmd_kick(const std::string& channel, const std::string& nickname, const std::string& reason) { - auto& mdi = MdiManager::instance(); - std::string chan = channel; + auto& mdi = MdiManager::instance(); + std::string chan = channel; - if (chan.empty()) { - if (mdi.currentWindow()->getType() != IWin::Type::Channel) { - mdi.currentWindow()->print(PrintType::ProgramInfo, "Not in a channel window"); - return; - } - chan = mdi.currentWindow()->getButtonText().toStdString(); - } + if (chan.empty()) { + if (mdi.currentWindow()->getType() != IWin::Type::Channel) { + mdi.currentWindow()->print(PrintType::ProgramInfo, "Not in a channel window"); + return; + } + chan = mdi.currentWindow()->getButtonText().toStdString(); + } - connection.command(KICK, { channel, nickname }, reason); + connection.command(KICK, { channel, nickname }, reason); } diff --git a/ICommand/External/notice.cpp b/ICommand/External/notice.cpp index 42c2644..21da5f0 100644 --- a/ICommand/External/notice.cpp +++ b/ICommand/External/notice.cpp @@ -11,21 +11,21 @@ using namespace Command::IRC; void ICommandPriv::cmd_notice(const std::string& target, const std::string& message) { - auto& mdi = MdiManager::instance(); + auto& mdi = MdiManager::instance(); - connection.command(NOTICE, { target }, message); + connection.command(NOTICE, { target }, message); - IWin* winTarget = mdi.findWindow(&status, target.c_str()); - IWin* active = status.getActiveWindow(); + IWin* winTarget = mdi.findWindow(&status, target.c_str()); + IWin* active = status.getActiveWindow(); - if (!target.empty() && !message.empty()) { - if (winTarget && winTarget != active) - winTarget->print(PrintType::OwnText, QStringLiteral("->%1<- %2") - .arg(target.c_str()) - .arg(message.c_str())); - if (active && active != winTarget) - active->print(PrintType::OwnText, QStringLiteral("->%1<- %2") - .arg(target.c_str()) - .arg(message.c_str())); - } + if (!target.empty() && !message.empty()) { + if (winTarget && winTarget != active) + winTarget->print(PrintType::OwnText, QStringLiteral("->%1<- %2") + .arg(target.c_str()) + .arg(message.c_str())); + if (active && active != winTarget) + active->print(PrintType::OwnText, QStringLiteral("->%1<- %2") + .arg(target.c_str()) + .arg(message.c_str())); + } } diff --git a/ICommand/External/privmsg.cpp b/ICommand/External/privmsg.cpp index 74d50f7..3c601ac 100644 --- a/ICommand/External/privmsg.cpp +++ b/ICommand/External/privmsg.cpp @@ -11,22 +11,22 @@ using namespace Command::IRC; void ICommandPriv::cmd_privmsg(const std::string& target, const std::string& message) { - auto& mdi = MdiManager::instance(); + auto& mdi = MdiManager::instance(); - connection.command(PRIVMSG, { target }, message); + connection.command(PRIVMSG, { target }, message); - if (!target.empty() && !message.empty()) { - IWin* win = mdi.findWindow(&status, target.c_str()); - if (win) { - const auto* myNick = connection.getNickname().c_str(); - win->print(PrintType::OwnText, QStringLiteral("<%1> %2") - .arg(myNick) - .arg(message.c_str())); - } - else - status.print(PrintType::OwnText, QStringLiteral(">%1< %2") - .arg(target.c_str()) - .arg(message.c_str())); - } + if (!target.empty() && !message.empty()) { + IWin* win = mdi.findWindow(&status, target.c_str()); + if (win) { + const auto* myNick = connection.getNickname().c_str(); + win->print(PrintType::OwnText, QStringLiteral("<%1> %2") + .arg(myNick) + .arg(message.c_str())); + } + else + status.print(PrintType::OwnText, QStringLiteral(">%1< %2") + .arg(target.c_str()) + .arg(message.c_str())); + } } diff --git a/ICommand/ICommand.cpp b/ICommand/ICommand.cpp index 28ffa23..01755b1 100644 --- a/ICommand/ICommand.cpp +++ b/ICommand/ICommand.cpp @@ -25,548 +25,548 @@ #endif ICommand::ICommand(IRC& connection_) - : mp(new ICommandPriv(*this, connection_, connection_.getStatus())) + : mp(new ICommandPriv(*this, connection_, connection_.getStatus())) {} ICommand::~ICommand() = default; void ICommand::parse(QString text) { - auto& connection = mp->connection; - - if (text.isEmpty()) - return; - - if (text[0] == '/') - text = text.mid(1); - - if (tryParseIRC(text) || tryParseInternal(text)) - return; - else if (ScriptManager::instance()->runCommand(text)) - return; - else if (!connection.isOnline()) { - const auto command = text.split(' ')[0]; - print_notConnectedToServer(command); - } - else { - const int nextSpace = text.indexOf(' '); - if (nextSpace == -1) - connection.raw(text.toUpper().toStdString()); - else { - QString command = text.mid(0, nextSpace).toUpper(); - QString out = QString("%1 %2") - .arg(command) - .arg(text.mid(nextSpace + 1)); - connection.raw(out.toStdString()); - } - } + auto& connection = mp->connection; + + if (text.isEmpty()) + return; + + if (text[0] == '/') + text = text.mid(1); + + if (tryParseIRC(text) || tryParseInternal(text)) + return; + else if (ScriptManager::instance()->runCommand(text)) + return; + else if (!connection.isOnline()) { + const auto command = text.split(' ')[0]; + print_notConnectedToServer(command); + } + else { + const int nextSpace = text.indexOf(' '); + if (nextSpace == -1) + connection.raw(text.toUpper().toStdString()); + else { + QString command = text.mid(0, nextSpace).toUpper(); + QString out = QString("%1 %2") + .arg(command) + .arg(text.mid(nextSpace + 1)); + connection.raw(out.toStdString()); + } + } } IRC& ICommand::getConnection() { - return mp->connection; + return mp->connection; } bool ICommand::tryParseIRC(QString cmdLine) { - auto& connection = mp->connection; - - int spaceidx = cmdLine.indexOf(' '); - spaceidx = spaceidx > -1 ? spaceidx : cmdLine.length(); - const QString command = cmdLine.mid(0, spaceidx).toUpper(); - cmdLine.remove(0, spaceidx); - - using namespace Command::IRC; // For the string constants below. - if (command == PASS) { - CommandData argv(cmdLine, { &ICommand::prd_Message }); - if (!argv[0]) - print_notEnoughParameters(command); - else - connection.command(PASS, *argv[0]); - - return true; - } - - else if (command == NICK) { - CommandData argv(cmdLine, { &ICommand::prd_Message }); - if (!argv[0]) - print_notEnoughParameters(command); - else { - if (!connection.isOnline()) - connection.setNickname(*argv[0]); - connection.command(NICK, *argv[0]); - } - - return true; - } - - else if (command == OPER) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (argv.size() < 2) - print_notEnoughParameters(command); - else - connection.command(OPER, { *argv[0], *argv[1] }); - - return true; - } - - else if (command == MODE) { - if (!connection.isOnline()) - print_notConnectedToServer(command); - else { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); - connection.raw(fmt::format("{} {}", MODE, argv.joinString(' '))); - } - - return true; - } - - else if (command == QUIT) { - CommandData argv(cmdLine, { &ICommand::prd_Message }); - - std::string message = argv[0].has_value() - ? *argv[0] - : ConfigMgr::instance().common("QuitMessage").toStdString(); + auto& connection = mp->connection; + + int spaceidx = cmdLine.indexOf(' '); + spaceidx = spaceidx > -1 ? spaceidx : cmdLine.length(); + const QString command = cmdLine.mid(0, spaceidx).toUpper(); + cmdLine.remove(0, spaceidx); + + using namespace Command::IRC; // For the string constants below. + if (command == PASS) { + CommandData argv(cmdLine, { &ICommand::prd_Message }); + if (!argv[0]) + print_notEnoughParameters(command); + else + connection.command(PASS, *argv[0]); + + return true; + } + + else if (command == NICK) { + CommandData argv(cmdLine, { &ICommand::prd_Message }); + if (!argv[0]) + print_notEnoughParameters(command); + else { + if (!connection.isOnline()) + connection.setNickname(*argv[0]); + connection.command(NICK, *argv[0]); + } + + return true; + } + + else if (command == OPER) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (argv.size() < 2) + print_notEnoughParameters(command); + else + connection.command(OPER, { *argv[0], *argv[1] }); + + return true; + } + + else if (command == MODE) { + if (!connection.isOnline()) + print_notConnectedToServer(command); + else { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); + connection.raw(fmt::format("{} {}", MODE, argv.joinString(' '))); + } + + return true; + } + + else if (command == QUIT) { + CommandData argv(cmdLine, { &ICommand::prd_Message }); + + std::string message = argv[0].has_value() + ? *argv[0] + : ConfigMgr::instance().common("QuitMessage").toStdString(); connection.expectDisconnect(); - connection.command(QUIT, message); - return true; - } - - else if (command == SQUIT) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - connection.command(SQUIT, { *argv[0] }, *argv[1]); - - return true; - } - - else if (command == JOIN) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - connection.command(JOIN, { *argv[0], argv[1].value_or("") }); - - return true; - } - - else if (command == PART) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - connection.command(PART, { *argv[0] }, argv[1].value_or("")); - - return true; - } - - else if (command == TOPIC) { - CommandData argv(cmdLine, { &ICommand::prd_Switch, &ICommand::prd_AnyWord, &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[1]) - print_notEnoughParameters(command); - else { - if (argv[0].value_or("") == "-c") { - connection.raw(fmt::format("{} {} :", TOPIC, *argv[1])); - return true; - } - - if (argv[2]) - connection.command(TOPIC, { *argv[1] }, *argv[2]); - else - connection.command(TOPIC, { *argv[1] }); - } - - return true; - } - - else if (command == NAMES) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - connection.command(NAMES, { *argv[0] }); - - return true; - } - - else if (command == LIST) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(LIST, { argv[0].value_or("") }); - - return true; - } - - else if (command == INVITE) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0] || !argv[1]) - print_notEnoughParameters(command); - else - connection.command(INVITE, { *argv[0], *argv[1] }); - - return true; - } - - else if (command == KICK) { - CommandData argv(cmdLine, { &ICommand::prd_OptionalChannel, &ICommand::prd_AnyWord, &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[1]) - print_notEnoughParameters(command); - else - mp->cmd_kick(*argv[0], *argv[1], argv[2].value_or("")); - - return true; - } - - else if (command == PRIVMSG || command == Command::Internal::MSG) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - mp->cmd_privmsg(*argv[0], argv[1].value_or("")); - - return true; - } - - else if (command == NOTICE) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - mp->cmd_notice(*argv[0], argv[1].value_or("")); - - return true; - } - - else if (command == MOTD) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(MOTD, { argv[0].value_or("") }); - return true; - } - - else if (command == LUSERS) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(LUSERS, { argv[0].value_or("") }); - return true; - } - - else if (command == VERSION) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(VERSION, { argv[0].value_or("") }); - return true; - } - - else if (command == STATS) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(STATS, { argv[0].value_or("") }); - return true; - } - - else if (command == LINKS) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(LINKS, { argv[0].value_or("") }); - return true; - } - - else if (command == TIME) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(TIME, { argv[0].value_or("") }); - return true; - } - - else if (command == CONNECT) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(CONNECT, { argv[0].value_or("") }); - return true; - } - - else if (command == TRACE) { - CommandData argv(cmdLine, { &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(TRACE, { argv[0].value_or("") }); - return true; - } - - else if (command == ADMIN) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(ADMIN, { argv[0].value_or("") }); - return true; - } - - else if (command == INFO) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(INFO, { argv[0].value_or("") }); - return true; - } - - else if (command == SERVLIST) { - - } - - else if (command == SQUERY) { - - } - - else if (command == WHO) { - CommandData argv(cmdLine, { &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else - connection.command(WHO, { argv[0].value_or("") }); - return true; - } - - else if (command == WHOIS) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - connection.command(WHOIS, { *argv[0] }); - return true; - } - - else if (command == WHOWAS) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - connection.command(WHOWAS, { *argv[0] }); - return true; - } - - else if (command == KILL) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) { - print_notEnoughParameters(command); - return true; - } - connection.command(KILL, { *argv[0] }, argv[1].value_or("")); - return true; - } - - else if (command == PING) { - - } - - else if (command == PONG) { - - } - - else if (command == AWAY) { - CommandData argv(cmdLine, { &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (argv[0]) - connection.command(AWAY, *argv[0]); - else - connection.raw(AWAY); - return true; - } - - else if (command == REHASH) { - - } - - else if (command == DIE) { - - } - - else if (command == RESTART) { - - } - - else if (command == SUMMON) { - - } - - else if (command == USERS) { + connection.command(QUIT, message); + return true; + } + + else if (command == SQUIT) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + connection.command(SQUIT, { *argv[0] }, *argv[1]); + + return true; + } + + else if (command == JOIN) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + connection.command(JOIN, { *argv[0], argv[1].value_or("") }); + + return true; + } + + else if (command == PART) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + connection.command(PART, { *argv[0] }, argv[1].value_or("")); + + return true; + } + + else if (command == TOPIC) { + CommandData argv(cmdLine, { &ICommand::prd_Switch, &ICommand::prd_AnyWord, &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[1]) + print_notEnoughParameters(command); + else { + if (argv[0].value_or("") == "-c") { + connection.raw(fmt::format("{} {} :", TOPIC, *argv[1])); + return true; + } + + if (argv[2]) + connection.command(TOPIC, { *argv[1] }, *argv[2]); + else + connection.command(TOPIC, { *argv[1] }); + } + + return true; + } + + else if (command == NAMES) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + connection.command(NAMES, { *argv[0] }); + + return true; + } + + else if (command == LIST) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(LIST, { argv[0].value_or("") }); + + return true; + } + + else if (command == INVITE) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0] || !argv[1]) + print_notEnoughParameters(command); + else + connection.command(INVITE, { *argv[0], *argv[1] }); + + return true; + } + + else if (command == KICK) { + CommandData argv(cmdLine, { &ICommand::prd_OptionalChannel, &ICommand::prd_AnyWord, &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[1]) + print_notEnoughParameters(command); + else + mp->cmd_kick(*argv[0], *argv[1], argv[2].value_or("")); + + return true; + } + + else if (command == PRIVMSG || command == Command::Internal::MSG) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + mp->cmd_privmsg(*argv[0], argv[1].value_or("")); + + return true; + } + + else if (command == NOTICE) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + mp->cmd_notice(*argv[0], argv[1].value_or("")); + + return true; + } + + else if (command == MOTD) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(MOTD, { argv[0].value_or("") }); + return true; + } + + else if (command == LUSERS) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(LUSERS, { argv[0].value_or("") }); + return true; + } + + else if (command == VERSION) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(VERSION, { argv[0].value_or("") }); + return true; + } + + else if (command == STATS) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(STATS, { argv[0].value_or("") }); + return true; + } + + else if (command == LINKS) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(LINKS, { argv[0].value_or("") }); + return true; + } + + else if (command == TIME) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(TIME, { argv[0].value_or("") }); + return true; + } + + else if (command == CONNECT) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(CONNECT, { argv[0].value_or("") }); + return true; + } - } + else if (command == TRACE) { + CommandData argv(cmdLine, { &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(TRACE, { argv[0].value_or("") }); + return true; + } - else if (command == WALLOPS) { - CommandData argv(cmdLine, { &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - connection.command(WALLOPS, *argv[0]); - return true; - } + else if (command == ADMIN) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(ADMIN, { argv[0].value_or("") }); + return true; + } - else if (command == USERHOST) { + else if (command == INFO) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(INFO, { argv[0].value_or("") }); + return true; + } + + else if (command == SERVLIST) { - } + } - else if (command == ISON) { - - } - - return false; + else if (command == SQUERY) { + + } + + else if (command == WHO) { + CommandData argv(cmdLine, { &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else + connection.command(WHO, { argv[0].value_or("") }); + return true; + } + + else if (command == WHOIS) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + connection.command(WHOIS, { *argv[0] }); + return true; + } + + else if (command == WHOWAS) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + connection.command(WHOWAS, { *argv[0] }); + return true; + } + + else if (command == KILL) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) { + print_notEnoughParameters(command); + return true; + } + connection.command(KILL, { *argv[0] }, argv[1].value_or("")); + return true; + } + + else if (command == PING) { + + } + + else if (command == PONG) { + + } + + else if (command == AWAY) { + CommandData argv(cmdLine, { &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (argv[0]) + connection.command(AWAY, *argv[0]); + else + connection.raw(AWAY); + return true; + } + + else if (command == REHASH) { + + } + + else if (command == DIE) { + + } + + else if (command == RESTART) { + + } + + else if (command == SUMMON) { + + } + + else if (command == USERS) { + + } + + else if (command == WALLOPS) { + CommandData argv(cmdLine, { &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + connection.command(WALLOPS, *argv[0]); + return true; + } + + else if (command == USERHOST) { + + } + + else if (command == ISON) { + + } + + return false; } bool ICommand::tryParseInternal(QString cmdLine) { - auto& connection = mp->connection; - auto& status = mp->status; - - int spaceidx = cmdLine.indexOf(' '); - spaceidx = spaceidx > -1 ? spaceidx : cmdLine.length(); - const QString command = cmdLine.mid(0, spaceidx).toUpper(); - cmdLine.remove(0, spaceidx); - - using namespace Command::Internal; - using namespace Command::IRC; - - if (command == CTCP || command == CTCPREPLY) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_AnyWordToUpper, &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0] || !argv[1]) - print_notEnoughParameters(command); - else { + auto& connection = mp->connection; + auto& status = mp->status; + + int spaceidx = cmdLine.indexOf(' '); + spaceidx = spaceidx > -1 ? spaceidx : cmdLine.length(); + const QString command = cmdLine.mid(0, spaceidx).toUpper(); + cmdLine.remove(0, spaceidx); + + using namespace Command::Internal; + using namespace Command::IRC; + + if (command == CTCP || command == CTCPREPLY) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord, &ICommand::prd_AnyWordToUpper, &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0] || !argv[1]) + print_notEnoughParameters(command); + else { if (command == CTCP) mp->cmd_ctcp(*argv[0], *argv[1], argv[2].value_or("")); else mp->cmd_ctcpreply(*argv[0], *argv[1], argv[2].value_or("")); } - return true; - } - - else if (command == ME) { - IWin* cw = status.getActiveWindow(); - - if (cw->getType() != IWin::Type::Channel && cw->getType() != IWin::Type::Private) { - print_invalidWindowTypeForCommand(command); - return true; - } - - CommandData argv(cmdLine, { &ICommand::prd_Message }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else { - const auto target = cw->getButtonText().toStdString(); - mp->cmd_me(target, argv[0].value_or("")); - } - return true; - } - - else if (command == ECHO) { - CommandData argv(cmdLine, { &ICommand::prd_Switch, &ICommand::prd_Switch, &ICommand::prd_Message }); - if (!argv[2]) { - print_notEnoughParameters(command); - return true; - } + return true; + } + + else if (command == ME) { + IWin* cw = status.getActiveWindow(); + + if (cw->getType() != IWin::Type::Channel && cw->getType() != IWin::Type::Private) { + print_invalidWindowTypeForCommand(command); + return true; + } + + CommandData argv(cmdLine, { &ICommand::prd_Message }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else { + const auto target = cw->getButtonText().toStdString(); + mp->cmd_me(target, argv[0].value_or("")); + } + return true; + } + + else if (command == ECHO) { + CommandData argv(cmdLine, { &ICommand::prd_Switch, &ICommand::prd_Switch, &ICommand::prd_Message }); + if (!argv[2]) { + print_notEnoughParameters(command); + return true; + } std::string arg1, arg2; - if (argv[0]) - arg1 = *argv[0]; - if (argv[1]) - arg2 = *argv[1]; - - mp->cmd_echo(arg1, arg2, *argv[2]); - return true; - } - - else if (command == QUERY) { - CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); - if (!connection.isOnline()) - print_notConnectedToServer(command); - else if (!argv[0]) - print_notEnoughParameters(command); - else - status.createPrivateWindow(argv[0]->c_str()); - return true; - } - - else if (command == MUTERESP) { - QStringList list = cmdLine.split(' ', QT_SPLIT_SKIP_EMPTY_PARTS); - if (list.isEmpty()) { - print_notEnoughParameters(command); - return true; - } - connection.setIgnoreVerbosity(list); - return true; - } - - else if (command == UNMUTERESP) { - QStringList list = cmdLine.split(' ', QT_SPLIT_SKIP_EMPTY_PARTS); - if (list.isEmpty()) { - print_notEnoughParameters(command); - return true; - } - connection.unsetIgnoreVerbosity(list); - return true; - } - - else if (command == CLEAR) { - auto& mdi = MdiManager::instance(); - mdi.currentWindow()->clear(); - return true; - } - - else if (command == QUOTE || command == RAW) { + if (argv[0]) + arg1 = *argv[0]; + if (argv[1]) + arg2 = *argv[1]; + + mp->cmd_echo(arg1, arg2, *argv[2]); + return true; + } + + else if (command == QUERY) { + CommandData argv(cmdLine, { &ICommand::prd_AnyWord }); + if (!connection.isOnline()) + print_notConnectedToServer(command); + else if (!argv[0]) + print_notEnoughParameters(command); + else + status.createPrivateWindow(argv[0]->c_str()); + return true; + } + + else if (command == MUTERESP) { + QStringList list = cmdLine.split(' ', QT_SPLIT_SKIP_EMPTY_PARTS); + if (list.isEmpty()) { + print_notEnoughParameters(command); + return true; + } + connection.setIgnoreVerbosity(list); + return true; + } + + else if (command == UNMUTERESP) { + QStringList list = cmdLine.split(' ', QT_SPLIT_SKIP_EMPTY_PARTS); + if (list.isEmpty()) { + print_notEnoughParameters(command); + return true; + } + connection.unsetIgnoreVerbosity(list); + return true; + } + + else if (command == CLEAR) { + auto& mdi = MdiManager::instance(); + mdi.currentWindow()->clear(); + return true; + } + + else if (command == QUOTE || command == RAW) { CommandData argv(cmdLine, { &ICommand::prd_Message }); if (!argv[0]) { print_notEnoughParameters(command); @@ -583,9 +583,9 @@ bool ICommand::tryParseInternal(QString cmdLine) connection.raw(*argv[0]); return true; - } + } - else if (command == SERVER) { + else if (command == SERVER) { CommandData argv(cmdLine, { &ICommand::prd_Switch, &ICommand::prd_AnyWord }); if (!argv[1]) { print_notEnoughParameters(command); @@ -607,92 +607,92 @@ bool ICommand::tryParseInternal(QString cmdLine) mp->cmd_server(ssl, newstatus, activate, host, port); - return true; - } + return true; + } - return false; + return false; } void ICommand::print_notEnoughParameters(const QString& command) { - const auto& mdi = MdiManager::instance(); - mdi.currentStatus()->printToActive(PrintType::ProgramInfo, tr("/%1: Not enough parameters.").arg(command.toLower())); + const auto& mdi = MdiManager::instance(); + mdi.currentStatus()->printToActive(PrintType::ProgramInfo, tr("/%1: Not enough parameters.").arg(command.toLower())); } void ICommand::print_invalidCommandSwitch(const QString& command) { - const auto& mdi = MdiManager::instance(); - mdi.currentStatus()->printToActive(PrintType::ProgramInfo, tr("/%1: Invalid command switch.").arg(command.toLower())); + const auto& mdi = MdiManager::instance(); + mdi.currentStatus()->printToActive(PrintType::ProgramInfo, tr("/%1: Invalid command switch.").arg(command.toLower())); } void ICommand::print_invalidWindowTypeForCommand(const QString& command) { - const auto& mdi = MdiManager::instance(); - mdi.currentStatus()->printToActive(PrintType::ProgramInfo, tr("/%1: Invalid window type for that command.").arg(command.toLower())); + const auto& mdi = MdiManager::instance(); + mdi.currentStatus()->printToActive(PrintType::ProgramInfo, tr("/%1: Invalid window type for that command.").arg(command.toLower())); } void ICommand::print_notConnectedToServer(const QString& command) { - const auto& mdi = MdiManager::instance(); - mdi.currentStatus()->printToActive(PrintType::ProgramInfo, tr("/%1: Not connected to a server.").arg(command.toLower())); + const auto& mdi = MdiManager::instance(); + mdi.currentStatus()->printToActive(PrintType::ProgramInfo, tr("/%1: Not connected to a server.").arg(command.toLower())); } std::optional ICommand::prd_AnyWord(int& idx, const QString& line) { - std::string ret; - std::string stdline = line.toStdString(); - for (; idx < stdline.size(); ++idx) { - const char c = stdline[idx]; - if (c == ' ') - break; - ret += c; - } - - if (ret.empty()) - return {}; - - return ret; + std::string ret; + std::string stdline = line.toStdString(); + for (; idx < stdline.size(); ++idx) { + const char c = stdline[idx]; + if (c == ' ') + break; + ret += c; + } + + if (ret.empty()) + return {}; + + return ret; } std::optional ICommand::prd_AnyWordToUpper(int& idx, const QString& line) { - auto ret = prd_AnyWord(idx, line); - if (ret) { - std::transform(ret->begin(), ret->end(), ret->begin(), - [](unsigned char c) -> unsigned char { return std::toupper(c); }); - } - return ret; + auto ret = prd_AnyWord(idx, line); + if (ret) { + std::transform(ret->begin(), ret->end(), ret->begin(), + [](unsigned char c) -> unsigned char { return std::toupper(c); }); + } + return ret; } std::optional ICommand::prd_OptionalChannel(int& idx, const QString& line) { - const auto& mdi = MdiManager::instance(); - const auto& isupport = mdi.currentStatus()->getConnection().isupport(); - const auto& chantypes = isupport.at("CHANTYPES"); + const auto& mdi = MdiManager::instance(); + const auto& isupport = mdi.currentStatus()->getConnection().isupport(); + const auto& chantypes = isupport.at("CHANTYPES"); - if (chantypes.find_first_of(line.toStdString()[idx]) == std::string::npos) - return std::nullopt; - return prd_AnyWord(idx, line); + if (chantypes.find_first_of(line.toStdString()[idx]) == std::string::npos) + return std::nullopt; + return prd_AnyWord(idx, line); } std::optional ICommand::prd_NotSwitch(int& idx, const QString& line) { - if (line[idx] == '-' || line[idx] == '+') - return std::nullopt; - return prd_AnyWord(idx, line); + if (line[idx] == '-' || line[idx] == '+') + return std::nullopt; + return prd_AnyWord(idx, line); } std::optional ICommand::prd_Switch(int& idx, const QString& line) { - if (line[idx] != '-' && line[idx] != '+') - return std::nullopt; - return prd_AnyWord(idx, line); + if (line[idx] != '-' && line[idx] != '+') + return std::nullopt; + return prd_AnyWord(idx, line); } std::optional ICommand::prd_Message(int& idx, const QString& line) { - QString ret = line.mid(idx); - if (ret.isEmpty()) - return std::nullopt; - return ret.toStdString(); + QString ret = line.mid(idx); + if (ret.isEmpty()) + return std::nullopt; + return ret.toStdString(); } diff --git a/ICommand/ICommand.h b/ICommand/ICommand.h index e077b95..a5bc126 100644 --- a/ICommand/ICommand.h +++ b/ICommand/ICommand.h @@ -20,34 +20,34 @@ struct ICommandPriv; class ICommand : public QObject { - Q_OBJECT + Q_OBJECT - friend struct ICommandPriv; + friend struct ICommandPriv; public: - explicit ICommand(IRC& connection_); - ~ICommand(); + explicit ICommand(IRC& connection_); + ~ICommand(); - void parse(QString text); - IRC& getConnection(); + void parse(QString text); + IRC& getConnection(); private: - bool tryParseIRC(QString cmdLine); - bool tryParseInternal(QString cmdLine); - void print_notEnoughParameters(const QString& command); - void print_invalidCommandSwitch(const QString& command); - void print_invalidWindowTypeForCommand(const QString& command); - void print_notConnectedToServer(const QString& command); - - /* Predicates for parsing commands */ - static std::optional prd_AnyWord(int& idx, const QString& line); - static std::optional prd_AnyWordToUpper(int& idx, const QString& line); - static std::optional prd_OptionalChannel(int& idx, const QString& line); - static std::optional prd_NotSwitch(int& idx, const QString& line); - static std::optional prd_Switch(int& idx, const QString& line); - static std::optional prd_Message(int& idx, const QString& line); - - std::unique_ptr mp; + bool tryParseIRC(QString cmdLine); + bool tryParseInternal(QString cmdLine); + void print_notEnoughParameters(const QString& command); + void print_invalidCommandSwitch(const QString& command); + void print_invalidWindowTypeForCommand(const QString& command); + void print_notConnectedToServer(const QString& command); + + /* Predicates for parsing commands */ + static std::optional prd_AnyWord(int& idx, const QString& line); + static std::optional prd_AnyWordToUpper(int& idx, const QString& line); + static std::optional prd_OptionalChannel(int& idx, const QString& line); + static std::optional prd_NotSwitch(int& idx, const QString& line); + static std::optional prd_Switch(int& idx, const QString& line); + static std::optional prd_Message(int& idx, const QString& line); + + std::unique_ptr mp; }; #endif // ICOMMAND_H diff --git a/ICommand/ICommandPriv.cpp b/ICommand/ICommandPriv.cpp index 8e5613a..790b9df 100644 --- a/ICommand/ICommandPriv.cpp +++ b/ICommand/ICommandPriv.cpp @@ -8,8 +8,8 @@ #include "ICommandPriv.h" ICommandPriv::ICommandPriv(ICommand& super_, IRC& connection_, IWinStatus& status_) - : super(super_) - , connection(connection_) - , status(status_) + : super(super_) + , connection(connection_) + , status(status_) {} diff --git a/ICommand/ICommandPriv.h b/ICommand/ICommandPriv.h index 311e7ae..57e20c0 100644 --- a/ICommand/ICommandPriv.h +++ b/ICommand/ICommandPriv.h @@ -19,19 +19,19 @@ constexpr char CTCPflag { 0x01 }; struct ICommandPriv { - ICommandPriv(ICommand& super_, IRC& connection_, IWinStatus& status_); + ICommandPriv(ICommand& super_, IRC& connection_, IWinStatus& status_); ICommand& super; IRC& connection; IWinStatus& status; - void cmd_kick(const std::string& channel, const std::string& nickname, const std::string& reason); - void cmd_privmsg(const std::string& target, const std::string& message); - void cmd_notice(const std::string& target, const std::string& message); + void cmd_kick(const std::string& channel, const std::string& nickname, const std::string& reason); + void cmd_privmsg(const std::string& target, const std::string& message); + void cmd_notice(const std::string& target, const std::string& message); - void cmd_ctcp(const std::string& target, const std::string& command, std::string message); + void cmd_ctcp(const std::string& target, const std::string& command, std::string message); void cmd_ctcpreply(const std::string& target, const std::string& command, const std::string& message); - void cmd_me(const std::string& target, const std::string& message); + void cmd_me(const std::string& target, const std::string& message); void cmd_echo(const std::string& arg1, const std::string& arg2, const std::string& text); void cmd_server(bool ssl, bool newstatus, bool activate, const std::string& host, const std::string& port); }; diff --git a/ICommand/Internal/me.cpp b/ICommand/Internal/me.cpp index 4f218c7..1a1e8c3 100644 --- a/ICommand/Internal/me.cpp +++ b/ICommand/Internal/me.cpp @@ -19,19 +19,19 @@ void ICommandPriv::cmd_me(const std::string& target, const std::string& message) IWin* cw = status.getActiveWindow(); if (cw->getType() == IWin::Type::Channel) { - auto channel = connection.getChannel( cw->getButtonText().toStdString() ); - auto& member = channel->getMember(mynick)->get(); - const std::string& mymodes = member.modes(); + auto channel = connection.getChannel( cw->getButtonText().toStdString() ); + auto& member = channel->getMember(mynick)->get(); + const std::string& mymodes = member.modes(); - if (!mymodes.empty()) { - std::string pf = connection.toMemberPrefix(mymodes); - if (!pf.empty()) - mynick.insert(mynick.begin(), pf[0]); - } - } + if (!mymodes.empty()) { + std::string pf = connection.toMemberPrefix(mymodes); + if (!pf.empty()) + mynick.insert(mynick.begin(), pf[0]); + } + } - if (!target.empty() && !message.empty()) - cw->print(PrintType::Action, QStringLiteral("%1 %2") - .arg(mynick.c_str()) - .arg(message.c_str())); + if (!target.empty() && !message.empty()) + cw->print(PrintType::Action, QStringLiteral("%1 %2") + .arg(mynick.c_str()) + .arg(message.c_str())); } diff --git a/IConfig/ColorConfig.cpp b/IConfig/ColorConfig.cpp index 1f64130..a2d9b56 100644 --- a/IConfig/ColorConfig.cpp +++ b/IConfig/ColorConfig.cpp @@ -21,360 +21,360 @@ constexpr auto* Text_AddPrefix_Short = "Add"; } ColorConfig::ColorConfig(QWidget* parent) - : QWidget(parent) - , colorDlg(this) + : QWidget(parent) + , colorDlg(this) { - addPrefixContainer = new QWidget(this); - addPrefixLayout = new QHBoxLayout; - btnAddPrefix = new QToolButton; - btnAddPrefix->setText(Text_AddPrefix_Full); - edAddPrefix = new QLineEdit; - edAddPrefix->setMaxLength(1); - edAddPrefix->setAlignment(Qt::AlignmentFlag::AlignCenter); - edAddPrefix->hide(); - addPrefixLayout->addWidget(edAddPrefix); - addPrefixLayout->addWidget(btnAddPrefix); - addPrefixContainer->setLayout(addPrefixLayout); - connect(btnAddPrefix, &QToolButton::clicked, this, &ColorConfig::addPrefixClicked); - connect(edAddPrefix, &QLineEdit::returnPressed, this, &ColorConfig::addPrefixClicked); - - ConfigMgr& conf = ConfigMgr::instance(); - palette = conf.color(); - prefixColor = conf.prefixColor(); - - textTypeMap = { - // Config key, Descriptive text - { "Action", "Action/role-play message" }, - { "CTCP", "CTCP message" }, - { "Highlight", "Highlighted message" }, - { "Invite", "Invite message" }, - { "Join", "Join message" }, - { "Kick", "Kick message" }, - { "Mode", "Mode message" }, - { "Nick", "Nick message" }, - { "Normal", "Normal message" }, - { "Notice", "Notice message" }, - { "OwnText", "Own message" }, - { "Part", "Part message" }, - { "ProgramInfo", "Program info" }, - { "Quit", "Quit message" }, - { "ServerInfo", "General server info" }, - { "Topic", "Topic message" }, - { "Wallops", "Wallops message" }, - { "Links", "Links / anchors" } - }; - - colorTypeMap = { - { "TextviewBackground", "Text view background" }, - { "InputBackground", "Text input background" }, - { "InputForeground", "Text input" }, - { "ListboxBackground", "Member list background" }, - { "ListboxForeground", "Member list default" } - }; - - connect(&colorDlg, &QColorDialog::currentColorChanged, - this, &ColorConfig::colorSelected); - - connect(&colorDlg, &QColorDialog::rejected, [this](){ - if (colorDlgItem.left(8) == "lbprefix") - setPrefixColor(colorDlgItem[9], originalColor); - else - palette.insert(colorDlgItem, originalColor); - repaint(); - }); + addPrefixContainer = new QWidget(this); + addPrefixLayout = new QHBoxLayout; + btnAddPrefix = new QToolButton; + btnAddPrefix->setText(Text_AddPrefix_Full); + edAddPrefix = new QLineEdit; + edAddPrefix->setMaxLength(1); + edAddPrefix->setAlignment(Qt::AlignmentFlag::AlignCenter); + edAddPrefix->hide(); + addPrefixLayout->addWidget(edAddPrefix); + addPrefixLayout->addWidget(btnAddPrefix); + addPrefixContainer->setLayout(addPrefixLayout); + connect(btnAddPrefix, &QToolButton::clicked, this, &ColorConfig::addPrefixClicked); + connect(edAddPrefix, &QLineEdit::returnPressed, this, &ColorConfig::addPrefixClicked); + + ConfigMgr& conf = ConfigMgr::instance(); + palette = conf.color(); + prefixColor = conf.prefixColor(); + + textTypeMap = { + // Config key, Descriptive text + { "Action", "Action/role-play message" }, + { "CTCP", "CTCP message" }, + { "Highlight", "Highlighted message" }, + { "Invite", "Invite message" }, + { "Join", "Join message" }, + { "Kick", "Kick message" }, + { "Mode", "Mode message" }, + { "Nick", "Nick message" }, + { "Normal", "Normal message" }, + { "Notice", "Notice message" }, + { "OwnText", "Own message" }, + { "Part", "Part message" }, + { "ProgramInfo", "Program info" }, + { "Quit", "Quit message" }, + { "ServerInfo", "General server info" }, + { "Topic", "Topic message" }, + { "Wallops", "Wallops message" }, + { "Links", "Links / anchors" } + }; + + colorTypeMap = { + { "TextviewBackground", "Text view background" }, + { "InputBackground", "Text input background" }, + { "InputForeground", "Text input" }, + { "ListboxBackground", "Member list background" }, + { "ListboxForeground", "Member list default" } + }; + + connect(&colorDlg, &QColorDialog::currentColorChanged, + this, &ColorConfig::colorSelected); + + connect(&colorDlg, &QColorDialog::rejected, [this](){ + if (colorDlgItem.left(8) == "lbprefix") + setPrefixColor(colorDlgItem[9], originalColor); + else + palette.insert(colorDlgItem, originalColor); + repaint(); + }); } void ColorConfig::save() { - ConfigMgr& conf = ConfigMgr::instance(); - conf.setColorPalette(palette); - conf.setPrefixColorPalette(prefixColor); - m_isChanged = false; + ConfigMgr& conf = ConfigMgr::instance(); + conf.setColorPalette(palette); + conf.setPrefixColorPalette(prefixColor); + m_isChanged = false; } bool ColorConfig::isChanged() const { - return m_isChanged; + return m_isChanged; } void ColorConfig::reset() { - ConfigMgr& conf = ConfigMgr::instance(); - palette = conf.color(); - prefixColor = conf.prefixColor(); - m_isChanged = false; - repaint(); + ConfigMgr& conf = ConfigMgr::instance(); + palette = conf.color(); + prefixColor = conf.prefixColor(); + m_isChanged = false; + repaint(); } void ColorConfig::paintEvent(QPaintEvent*) { - QPainter paint(this); - int w = width(); - int h = height(); + QPainter paint(this); + int w = width(); + int h = height(); - QColor frame(palette.value("TextviewBackground")); - frame.setRed(frame.red() ^ 255); - frame.setGreen(frame.green() ^ 255); - frame.setBlue(frame.blue() ^ 255); + QColor frame(palette.value("TextviewBackground")); + frame.setRed(frame.red() ^ 255); + frame.setGreen(frame.green() ^ 255); + frame.setBlue(frame.blue() ^ 255); - paint.fillRect(0, 0, w, h, frame); - w -= 2; - h -= 2; + paint.fillRect(0, 0, w, h, frame); + w -= 2; + h -= 2; - const int listboxW = 150; - const int inputH = 24; + const int listboxW = 150; + const int inputH = 24; - /* Text-view background */ - textViewBB = { 1, 1, w - listboxW, h - inputH }; - paint.fillRect(textViewBB, QColor(palette.value("TextviewBackground"))); + /* Text-view background */ + textViewBB = { 1, 1, w - listboxW, h - inputH }; + paint.fillRect(textViewBB, QColor(palette.value("TextviewBackground"))); - /* Member list background */ - listboxBB = { w - listboxW + 2, 1, listboxW - 1, h - inputH }; - paint.fillRect(listboxBB, QColor(palette.value("ListboxBackground"))); // Listbox + /* Member list background */ + listboxBB = { w - listboxW + 2, 1, listboxW - 1, h - inputH }; + paint.fillRect(listboxBB, QColor(palette.value("ListboxBackground"))); // Listbox - /* Input background */ - inputBB = { 1, h - inputH + 2, w, inputH - 1 }; - paint.fillRect(inputBB, QColor(palette.value("InputBackground"))); // Input + /* Input background */ + inputBB = { 1, h - inputH + 2, w, inputH - 1 }; + paint.fillRect(inputBB, QColor(palette.value("InputBackground"))); // Input - ConfigMgr& conf = ConfigMgr::instance(); - QFont font(conf.common("Font")); - paint.setFont(font); + ConfigMgr& conf = ConfigMgr::instance(); + QFont font(conf.common("Font")); + paint.setFont(font); - createMessageBoxTexts(paint); - createMemberListTexts(paint, listboxW); - createInputBoxTexts(paint, inputH); + createMessageBoxTexts(paint); + createMemberListTexts(paint, listboxW); + createInputBoxTexts(paint, inputH); } void ColorConfig::mouseReleaseEvent(QMouseEvent* evt) { - const int X = evt->x(); - const int Y = evt->y(); - - /* Check click for text item types */ - { - QHashIterator it(textTypeBB); - while (it.hasNext()) { - it.next(); - const QString& key = it.key(); - const QRect& val = it.value(); - if (val.contains(X, Y)) { - chooseColorFor(key); - return; - } - } - } - - /* Check click for listbox items */ - { - QHashIterator it(listboxItemBB); - while (it.hasNext()) { - it.next(); - const QString& key = it.key(); - const QRect& val = it.value(); - if (val.contains(X, Y)) { - chooseColorFor(key); - return; - } - } - } - - /* Check click for delete listbox item */ - { - QHashIterator it(prefixDeleteBB); - while (it.hasNext()) { - it.next(); - const QChar& key = it.key(); - const QRect& val = it.value(); - if (val.contains(X, Y)) { - askDeletePrefix(key); - return; - } - } - } - - if (inputTextBB.contains(X, Y)) - chooseColorFor("InputForeground"); - - else if (textViewBB.contains(X, Y)) - chooseColorFor("TextviewBackground"); - - else if (listboxBB.contains(X, Y)) - chooseColorFor("ListboxBackground"); - - else if (inputBB.contains(X, Y)) - chooseColorFor("InputBackground"); + const int X = evt->x(); + const int Y = evt->y(); + + /* Check click for text item types */ + { + QHashIterator it(textTypeBB); + while (it.hasNext()) { + it.next(); + const QString& key = it.key(); + const QRect& val = it.value(); + if (val.contains(X, Y)) { + chooseColorFor(key); + return; + } + } + } + + /* Check click for listbox items */ + { + QHashIterator it(listboxItemBB); + while (it.hasNext()) { + it.next(); + const QString& key = it.key(); + const QRect& val = it.value(); + if (val.contains(X, Y)) { + chooseColorFor(key); + return; + } + } + } + + /* Check click for delete listbox item */ + { + QHashIterator it(prefixDeleteBB); + while (it.hasNext()) { + it.next(); + const QChar& key = it.key(); + const QRect& val = it.value(); + if (val.contains(X, Y)) { + askDeletePrefix(key); + return; + } + } + } + + if (inputTextBB.contains(X, Y)) + chooseColorFor("InputForeground"); + + else if (textViewBB.contains(X, Y)) + chooseColorFor("TextviewBackground"); + + else if (listboxBB.contains(X, Y)) + chooseColorFor("ListboxBackground"); + + else if (inputBB.contains(X, Y)) + chooseColorFor("InputBackground"); } void ColorConfig::createMessageBoxTexts(QPainter& paint) { - const int itemIncr = 19; - int itemTop = itemIncr; - QPen originalPen = paint.pen(); - QFontMetrics fm(paint.fontMetrics()); + const int itemIncr = 19; + int itemTop = itemIncr; + QPen originalPen = paint.pen(); + QFontMetrics fm(paint.fontMetrics()); - textTypeBB.clear(); - QHashIterator it(textTypeMap); - QStringList sorted; + textTypeBB.clear(); + QHashIterator it(textTypeMap); + QStringList sorted; - while (it.hasNext()) - sorted << it.next().key(); + while (it.hasNext()) + sorted << it.next().key(); - std::sort(sorted.begin(), sorted.end(), - [this](const QString& left, const QString& right) { - QString leftText = descriptiveColorText(left); - QString rightText = descriptiveColorText(right); - return leftText < rightText; - }); + std::sort(sorted.begin(), sorted.end(), + [this](const QString& left, const QString& right) { + QString leftText = descriptiveColorText(left); + QString rightText = descriptiveColorText(right); + return leftText < rightText; + }); - for (const QString& key : sorted) { - const QString val = descriptiveColorText(key); + for (const QString& key : sorted) { + const QString val = descriptiveColorText(key); - paint.setPen(QColor(palette.value(key))); - paint.drawText(4, itemTop, val); + paint.setPen(QColor(palette.value(key))); + paint.drawText(4, itemTop, val); - QRect itemRect(4, itemTop - fm.ascent(), fm.width(val), fm.height()); - textTypeBB.insert(key, itemRect); + QRect itemRect(4, itemTop - fm.ascent(), fm.width(val), fm.height()); + textTypeBB.insert(key, itemRect); - itemTop += itemIncr; - } + itemTop += itemIncr; + } - paint.setPen(originalPen); + paint.setPen(originalPen); } void ColorConfig::createMemberListTexts(QPainter& paint, int listboxW) { - const int x = width() - listboxW + 4; - const int itemIncr = 20; - int itemTop = itemIncr; - QPen originalPen = paint.pen(); - - QFontMetrics fm(paint.fontMetrics()); - listboxItemBB.clear(); - prefixDeleteBB.clear(); - paint.setPen(QColor(palette.value("ListboxForeground"))); - paint.drawText(x, itemTop, "Default text"); - listboxItemBB.insert("ListboxForeground", QRect(x, itemTop - fm.ascent(), fm.width("Default text"), fm.height())); - itemTop += itemIncr; - - constexpr auto* DeleteLabel = "[X]"; - for (const auto& item : prefixColor) { - QString itemText = QStringLiteral("%1member").arg(item.first); - int itemTextWidth = fm.width(itemText); - paint.setPen(item.second); - paint.drawText(x, itemTop, itemText); - paint.drawText(x + itemTextWidth + 10, itemTop, DeleteLabel); - listboxItemBB.insert(QStringLiteral("lbprefix %1").arg(item.first), QRect(x, itemTop - fm.ascent(), itemTextWidth, fm.height())); - prefixDeleteBB.insert(item.first, QRect(x + itemTextWidth + 10, itemTop - fm.ascent(), fm.width(DeleteLabel), fm.height())); - - itemTop += itemIncr; - } - - paint.setPen(originalPen); - addPrefixContainer->move(x, itemTop); + const int x = width() - listboxW + 4; + const int itemIncr = 20; + int itemTop = itemIncr; + QPen originalPen = paint.pen(); + + QFontMetrics fm(paint.fontMetrics()); + listboxItemBB.clear(); + prefixDeleteBB.clear(); + paint.setPen(QColor(palette.value("ListboxForeground"))); + paint.drawText(x, itemTop, "Default text"); + listboxItemBB.insert("ListboxForeground", QRect(x, itemTop - fm.ascent(), fm.width("Default text"), fm.height())); + itemTop += itemIncr; + + constexpr auto* DeleteLabel = "[X]"; + for (const auto& item : prefixColor) { + QString itemText = QStringLiteral("%1member").arg(item.first); + int itemTextWidth = fm.width(itemText); + paint.setPen(item.second); + paint.drawText(x, itemTop, itemText); + paint.drawText(x + itemTextWidth + 10, itemTop, DeleteLabel); + listboxItemBB.insert(QStringLiteral("lbprefix %1").arg(item.first), QRect(x, itemTop - fm.ascent(), itemTextWidth, fm.height())); + prefixDeleteBB.insert(item.first, QRect(x + itemTextWidth + 10, itemTop - fm.ascent(), fm.width(DeleteLabel), fm.height())); + + itemTop += itemIncr; + } + + paint.setPen(originalPen); + addPrefixContainer->move(x, itemTop); } void ColorConfig::createInputBoxTexts(QPainter& paint, int inputH) { - QFontMetrics fm(paint.fontMetrics()); - const int fh = fm.height(); - const int y = height() - inputH + fh; - QPen originalPen = paint.pen(); + QFontMetrics fm(paint.fontMetrics()); + const int fh = fm.height(); + const int y = height() - inputH + fh; + QPen originalPen = paint.pen(); - paint.setPen(QColor(palette.value("InputForeground"))); - paint.drawText(4, y, "Input box text"); - inputTextBB = {4, y - fm.ascent(), fm.width("Input box text"), fm.height()}; + paint.setPen(QColor(palette.value("InputForeground"))); + paint.drawText(4, y, "Input box text"); + inputTextBB = {4, y - fm.ascent(), fm.width("Input box text"), fm.height()}; - paint.setPen(originalPen); + paint.setPen(originalPen); } QString ColorConfig::descriptiveColorText(const QString& key) const { - if (key.left(8) == "lbprefix") - return QStringLiteral("Prefix '%1'").arg(key[9]); + if (key.left(8) == "lbprefix") + return QStringLiteral("Prefix '%1'").arg(key[9]); - QString text = textTypeMap.value(key); - if (text.isEmpty()) - text = colorTypeMap.value(key); - return text; + QString text = textTypeMap.value(key); + if (text.isEmpty()) + text = colorTypeMap.value(key); + return text; } void ColorConfig::chooseColorFor(const QString& item) { - colorDlgItem = item; - if (colorDlgItem.left(8) == "lbprefix") - colorDlg.setCurrentColor(*getPrefixColor(colorDlgItem[9])); - else - colorDlg.setCurrentColor(QColor(palette.value(item))); - originalColor = colorDlg.currentColor().name(); - - colorDlg.setWindowTitle(QStringLiteral("Choose color for: %1").arg(descriptiveColorText(item))); - if (!colorDlg.isVisible()) - colorDlg.show(); + colorDlgItem = item; + if (colorDlgItem.left(8) == "lbprefix") + colorDlg.setCurrentColor(*getPrefixColor(colorDlgItem[9])); + else + colorDlg.setCurrentColor(QColor(palette.value(item))); + originalColor = colorDlg.currentColor().name(); + + colorDlg.setWindowTitle(QStringLiteral("Choose color for: %1").arg(descriptiveColorText(item))); + if (!colorDlg.isVisible()) + colorDlg.show(); } void ColorConfig::colorSelected(const QColor& color) { - if (colorDlgItem.left(8) == "lbprefix") - setPrefixColor(colorDlgItem[9], color); - else - palette.insert(colorDlgItem, color.name()); - m_isChanged = true; - repaint(); + if (colorDlgItem.left(8) == "lbprefix") + setPrefixColor(colorDlgItem[9], color); + else + palette.insert(colorDlgItem, color.name()); + m_isChanged = true; + repaint(); } std::optional ColorConfig::getPrefixColor(QChar prefix) { - for (const auto& item : prefixColor) - if (item.first == prefix) - return item.second; - return std::nullopt; + for (const auto& item : prefixColor) + if (item.first == prefix) + return item.second; + return std::nullopt; } void ColorConfig::setPrefixColor(QChar prefix, const QColor& color) { - for (auto& item : prefixColor) - if (item.first == prefix) - item.second = color; + for (auto& item : prefixColor) + if (item.first == prefix) + item.second = color; } void ColorConfig::addPrefixClicked() { - if (edAddPrefix->isVisible()) { - if (!edAddPrefix->text().isEmpty()) { - const QChar prefix = edAddPrefix->text()[0]; - if (getPrefixColor(prefix)) { - QMessageBox::information(this, tr("Prefix exists"), tr("The given prefix '%1' is already defined.").arg(prefix)); - return; - } - if (!prefix.isSpace() && !prefix.isLetter() && !prefix.isNumber()) { - prefixColor.push_back(std::make_pair(prefix, palette.value("ListboxForeground"))); - m_isChanged = true; - repaint(); - } - } - edAddPrefix->clear(); - edAddPrefix->hide(); - btnAddPrefix->setText(Text_AddPrefix_Full); - } - else { - edAddPrefix->show(); - btnAddPrefix->setText(Text_AddPrefix_Short); - } + if (edAddPrefix->isVisible()) { + if (!edAddPrefix->text().isEmpty()) { + const QChar prefix = edAddPrefix->text()[0]; + if (getPrefixColor(prefix)) { + QMessageBox::information(this, tr("Prefix exists"), tr("The given prefix '%1' is already defined.").arg(prefix)); + return; + } + if (!prefix.isSpace() && !prefix.isLetter() && !prefix.isNumber()) { + prefixColor.push_back(std::make_pair(prefix, palette.value("ListboxForeground"))); + m_isChanged = true; + repaint(); + } + } + edAddPrefix->clear(); + edAddPrefix->hide(); + btnAddPrefix->setText(Text_AddPrefix_Full); + } + else { + edAddPrefix->show(); + btnAddPrefix->setText(Text_AddPrefix_Short); + } } void ColorConfig::askDeletePrefix(QChar prefix) { - const QString title = tr("Delete prefix"); - const QString question = tr("Are you sure you want to delete the prefix '%1'?").arg(prefix); - if (QMessageBox::question(this, title, question) == QMessageBox::No) - return; - - for (int i = 0; i < prefixColor.count(); ++i) { - QChar p = prefixColor[i].first; - if (p == prefix) { - prefixColor.removeAt(i); - break; - } - } - repaint(); + const QString title = tr("Delete prefix"); + const QString question = tr("Are you sure you want to delete the prefix '%1'?").arg(prefix); + if (QMessageBox::question(this, title, question) == QMessageBox::No) + return; + + for (int i = 0; i < prefixColor.count(); ++i) { + QChar p = prefixColor[i].first; + if (p == prefix) { + prefixColor.removeAt(i); + break; + } + } + repaint(); } diff --git a/IConfig/ColorConfig.h b/IConfig/ColorConfig.h index 503249a..e5289cc 100644 --- a/IConfig/ColorConfig.h +++ b/IConfig/ColorConfig.h @@ -21,51 +21,51 @@ class ColorConfig : public QWidget { - Q_OBJECT + Q_OBJECT public: - explicit ColorConfig(QWidget* parent = nullptr); - void save(); - bool isChanged() const; - void reset(); + explicit ColorConfig(QWidget* parent = nullptr); + void save(); + bool isChanged() const; + void reset(); private: - void paintEvent(QPaintEvent*); - void mouseReleaseEvent(QMouseEvent *evt); - void createMessageBoxTexts(QPainter& paint); - void createMemberListTexts(QPainter& paint, int listboxW); - void createInputBoxTexts(QPainter& paint, int inputH); - void recalculateBB(); - QString descriptiveColorText(const QString& key) const; - void chooseColorFor(const QString& item); - void colorSelected(const QColor& color); - std::optional getPrefixColor(QChar prefix); - void setPrefixColor(QChar prefix, const QColor& color); - void addPrefixClicked(); - void askDeletePrefix(QChar prefix); + void paintEvent(QPaintEvent*); + void mouseReleaseEvent(QMouseEvent *evt); + void createMessageBoxTexts(QPainter& paint); + void createMemberListTexts(QPainter& paint, int listboxW); + void createInputBoxTexts(QPainter& paint, int inputH); + void recalculateBB(); + QString descriptiveColorText(const QString& key) const; + void chooseColorFor(const QString& item); + void colorSelected(const QColor& color); + std::optional getPrefixColor(QChar prefix); + void setPrefixColor(QChar prefix, const QColor& color); + void addPrefixClicked(); + void askDeletePrefix(QChar prefix); - QWidget* addPrefixContainer; - QHBoxLayout* addPrefixLayout; - QToolButton* btnAddPrefix; - QLineEdit* edAddPrefix; - QHash palette; + QWidget* addPrefixContainer; + QHBoxLayout* addPrefixLayout; + QToolButton* btnAddPrefix; + QLineEdit* edAddPrefix; + QHash palette; - QHash textTypeMap; - QHash colorTypeMap; - QVector> prefixColor; // Use vector for displaying prefixes in insertion order. + QHash textTypeMap; + QHash colorTypeMap; + QVector> prefixColor; // Use vector for displaying prefixes in insertion order. - QHash textTypeBB; - QHash listboxItemBB; - QHash prefixDeleteBB; - QRect textViewBB; - QRect inputBB; - QRect inputTextBB; - QRect listboxBB; + QHash textTypeBB; + QHash listboxItemBB; + QHash prefixDeleteBB; + QRect textViewBB; + QRect inputBB; + QRect inputTextBB; + QRect listboxBB; - QColorDialog colorDlg; - QString colorDlgItem; - QString originalColor; + QColorDialog colorDlg; + QString colorDlgItem; + QString originalColor; - bool m_isChanged{ false }; + bool m_isChanged{ false }; }; #endif // COLORCONFIG_H diff --git a/IConfig/IConfig.cpp b/IConfig/IConfig.cpp index 603b16f..81126f2 100644 --- a/IConfig/IConfig.cpp +++ b/IConfig/IConfig.cpp @@ -11,75 +11,75 @@ #include IConfig::IConfig(QWidget *parent) : - QDialog(parent), - ui(new Ui::IConfig) + QDialog(parent), + ui(new Ui::IConfig) { - ui->setupUi(this); + ui->setupUi(this); - layout = new QHBoxLayout(this); - servers = new IConfigServers; - options = new IConfigOptions; - logging = new IConfigLogging; + layout = new QHBoxLayout(this); + servers = new IConfigServers; + options = new IConfigOptions; + logging = new IConfigLogging; - layout->addWidget(servers); - layout->addWidget(options); - layout->addWidget(logging); - ui->frame->setLayout(layout); + layout->addWidget(servers); + layout->addWidget(options); + layout->addWidget(logging); + ui->frame->setLayout(layout); - connect(ui->toolServers, &QAbstractButton::released, [this](){ showSubDialog(SubDialogType::Servers); }); - connect(ui->toolOptions, &QAbstractButton::released, [this](){ showSubDialog(SubDialogType::Options); }); - connect(ui->toolLogging, &QAbstractButton::released, [this](){ showSubDialog(SubDialogType::Logging); }); + connect(ui->toolServers, &QAbstractButton::released, [this](){ showSubDialog(SubDialogType::Servers); }); + connect(ui->toolOptions, &QAbstractButton::released, [this](){ showSubDialog(SubDialogType::Options); }); + connect(ui->toolLogging, &QAbstractButton::released, [this](){ showSubDialog(SubDialogType::Logging); }); - showSubDialog(SubDialogType::Servers); + showSubDialog(SubDialogType::Servers); } IConfig::~IConfig() { - delete ui; + delete ui; } void IConfig::showDisconnectButton() { - ui->btnDisconnect->show(); + ui->btnDisconnect->show(); } void IConfig::hideDisconnectButton() { - ui->btnDisconnect->hide(); + ui->btnDisconnect->hide(); } void IConfig::showSubDialog(IConfig::SubDialogType dlg) { - servers->hide(); - options->hide(); - logging->hide(); - ui->toolServers->setChecked(false); - ui->toolOptions->setChecked(false); - ui->toolLogging->setChecked(false); - - switch (dlg) { - case SubDialogType::Servers: - servers->show(); - ui->toolServers->setChecked(true); - break; - case SubDialogType::Options: - options->show(); - ui->toolOptions->setChecked(true); - break; - case SubDialogType::Logging: - logging->show(); - ui->toolLogging->setChecked(true); - break; - } + servers->hide(); + options->hide(); + logging->hide(); + ui->toolServers->setChecked(false); + ui->toolOptions->setChecked(false); + ui->toolLogging->setChecked(false); + + switch (dlg) { + case SubDialogType::Servers: + servers->show(); + ui->toolServers->setChecked(true); + break; + case SubDialogType::Options: + options->show(); + ui->toolOptions->setChecked(true); + break; + case SubDialogType::Logging: + logging->show(); + ui->toolLogging->setChecked(true); + break; + } } void IConfig::saveAll() { - servers->save(); - options->save(); - logging->save(); + servers->save(); + options->save(); + logging->save(); - ConfigMgr::instance().save(); + ConfigMgr::instance().save(); } bool IConfig::askForSave() @@ -87,70 +87,70 @@ bool IConfig::askForSave() bool serversChanged = servers->isChanged(); bool optionsChanged = options->isChanged(); bool loggingChanged = logging->isChanged(); - if (serversChanged || optionsChanged || loggingChanged) { - auto btn = QMessageBox::question(this, tr("Changes made"), tr("Do you want to save the changes?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); - if (btn == QMessageBox::Yes) { - saveAll(); - } - else if (btn == QMessageBox::No) { - servers->reset(); - options->reset(); - logging->reset(); - } - else if (btn == QMessageBox::Cancel) { - return false; - } - } - return true; + if (serversChanged || optionsChanged || loggingChanged) { + auto btn = QMessageBox::question(this, tr("Changes made"), tr("Do you want to save the changes?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (btn == QMessageBox::Yes) { + saveAll(); + } + else if (btn == QMessageBox::No) { + servers->reset(); + options->reset(); + logging->reset(); + } + else if (btn == QMessageBox::Cancel) { + return false; + } + } + return true; } void IConfig::on_btnSave_clicked() { - saveAll(); + saveAll(); } void IConfig::on_btnSaveConnect_clicked() { - saveAll(); - ConfigMgr& conf = ConfigMgr::instance(); - if (conf.connection("Realname").isEmpty()) { - QMessageBox::information(this, tr("Missing field"), tr("Real name must be filled.")); - return; - } - - if (conf.connection("Username").isEmpty()) { - QMessageBox::information(this, tr("Missing field"), tr("Username/email must be filled.")); - return; - } - - if (conf.connection("Nickname").isEmpty()) { - QMessageBox::information(this, tr("Missing field"), tr("Nickname must be filled")); - return; - } - - if (!servers->connectToNewStatus()) - emit disconnectFromServer(); - emit connectToServer(servers->connectToNewStatus()); - servers->unsetConnectToNewStatus(); - close(); + saveAll(); + ConfigMgr& conf = ConfigMgr::instance(); + if (conf.connection("Realname").isEmpty()) { + QMessageBox::information(this, tr("Missing field"), tr("Real name must be filled.")); + return; + } + + if (conf.connection("Username").isEmpty()) { + QMessageBox::information(this, tr("Missing field"), tr("Username/email must be filled.")); + return; + } + + if (conf.connection("Nickname").isEmpty()) { + QMessageBox::information(this, tr("Missing field"), tr("Nickname must be filled")); + return; + } + + if (!servers->connectToNewStatus()) + emit disconnectFromServer(); + emit connectToServer(servers->connectToNewStatus()); + servers->unsetConnectToNewStatus(); + close(); } void IConfig::on_btnDisconnect_clicked() { - ui->btnDisconnect->hide(); - emit disconnectFromServer(); + ui->btnDisconnect->hide(); + emit disconnectFromServer(); } void IConfig::on_btnClose_clicked() { - servers->unsetConnectToNewStatus(); - close(); + servers->unsetConnectToNewStatus(); + close(); } void IConfig::closeEvent(QCloseEvent* evt) { - if (askForSave()) - evt->accept(); - else - evt->ignore(); + if (askForSave()) + evt->accept(); + else + evt->ignore(); } diff --git a/IConfig/IConfig.h b/IConfig/IConfig.h index 32a9aa6..52c7df9 100644 --- a/IConfig/IConfig.h +++ b/IConfig/IConfig.h @@ -22,40 +22,40 @@ class IConfig; class IConfig : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit IConfig(QWidget *parent = nullptr); - ~IConfig(); - void showDisconnectButton(); - void hideDisconnectButton(); + explicit IConfig(QWidget *parent = nullptr); + ~IConfig(); + void showDisconnectButton(); + void hideDisconnectButton(); private slots: - void on_btnSave_clicked(); - void on_btnSaveConnect_clicked(); - void on_btnDisconnect_clicked(); - void on_btnClose_clicked(); + void on_btnSave_clicked(); + void on_btnSaveConnect_clicked(); + void on_btnDisconnect_clicked(); + void on_btnClose_clicked(); private: - enum class SubDialogType { - Servers, - Options, - Logging - }; - void closeEvent(QCloseEvent* evt); - void showSubDialog(SubDialogType dlg); - void saveAll(); - bool askForSave(); - - Ui::IConfig* ui; - QHBoxLayout *layout; - IConfigServers* servers; - IConfigOptions* options; - IConfigLogging* logging; + enum class SubDialogType { + Servers, + Options, + Logging + }; + void closeEvent(QCloseEvent* evt); + void showSubDialog(SubDialogType dlg); + void saveAll(); + bool askForSave(); + + Ui::IConfig* ui; + QHBoxLayout *layout; + IConfigServers* servers; + IConfigOptions* options; + IConfigLogging* logging; signals: - void connectToServer(bool newServer); - void disconnectFromServer(); + void connectToServer(bool newServer); + void disconnectFromServer(); }; #endif // ICONFIG_H diff --git a/IConfig/IConfigLogging.cpp b/IConfig/IConfigLogging.cpp index 52761fc..207b4e8 100644 --- a/IConfig/IConfigLogging.cpp +++ b/IConfig/IConfigLogging.cpp @@ -13,95 +13,95 @@ #include IConfigLogging::IConfigLogging(QWidget *parent) : - QWidget(parent), - ui(new Ui::IConfigLogging) + QWidget(parent), + ui(new Ui::IConfigLogging) { - ui->setupUi(this); - ui->splitter->setStretchFactor(0, 1); - ui->splitter->setStretchFactor(1, 4); + ui->setupUi(this); + ui->splitter->setStretchFactor(0, 1); + ui->splitter->setStretchFactor(1, 4); - ConfigMgr& conf = ConfigMgr::instance(); - cf_Chnanels = conf.logging("Channels").toInt(); - cf_Privates = conf.logging("Privates").toInt(); - cf_Path = conf.logging("Path"); + ConfigMgr& conf = ConfigMgr::instance(); + cf_Chnanels = conf.logging("Channels").toInt(); + cf_Privates = conf.logging("Privates").toInt(); + cf_Path = conf.logging("Path"); - ui->chkChannels->setChecked(cf_Chnanels); - ui->chkPrivates->setChecked(cf_Privates); - ui->edPath->setText(cf_Path); + ui->chkChannels->setChecked(cf_Chnanels); + ui->chkPrivates->setChecked(cf_Privates); + ui->edPath->setText(cf_Path); } IConfigLogging::~IConfigLogging() { - delete ui; + delete ui; } bool IConfigLogging::isChanged() const { - return cf_Chnanels != ui->chkChannels->isChecked() - || cf_Privates != ui->chkPrivates->isChecked() - || cf_Path != ui->edPath->text(); + return cf_Chnanels != ui->chkChannels->isChecked() + || cf_Privates != ui->chkPrivates->isChecked() + || cf_Path != ui->edPath->text(); } void IConfigLogging::save() { - ConfigMgr& conf = ConfigMgr::instance(); - conf.setLogging("Channels", QString::number(ui->chkChannels->isChecked())); - conf.setLogging("Privates", QString::number(ui->chkPrivates->isChecked())); - conf.setLogging("Path", ui->edPath->text()); + ConfigMgr& conf = ConfigMgr::instance(); + conf.setLogging("Channels", QString::number(ui->chkChannels->isChecked())); + conf.setLogging("Privates", QString::number(ui->chkPrivates->isChecked())); + conf.setLogging("Path", ui->edPath->text()); - cf_Chnanels = conf.logging("Channels").toInt(); - cf_Privates = conf.logging("Privates").toInt(); - cf_Path = conf.logging("Path"); + cf_Chnanels = conf.logging("Channels").toInt(); + cf_Privates = conf.logging("Privates").toInt(); + cf_Path = conf.logging("Path"); } void IConfigLogging::reset() { - ui->chkChannels->setChecked(cf_Chnanels); - ui->chkPrivates->setChecked(cf_Privates); - ui->edPath->setText(cf_Path); + ui->chkChannels->setChecked(cf_Chnanels); + ui->chkPrivates->setChecked(cf_Privates); + ui->edPath->setText(cf_Path); } void IConfigLogging::showEvent(QShowEvent* evt) { - QWidget::showEvent(evt); - if (!ui->edPath->text().isEmpty()) - loadFiles(ui->edPath->text()); + QWidget::showEvent(evt); + if (!ui->edPath->text().isEmpty()) + loadFiles(ui->edPath->text()); } void IConfigLogging::on_btnBrowse_clicked() { - QString dirstr = QFileDialog::getExistingDirectory(this, tr("Log directory"), LOCAL_PATH); - loadFiles(dirstr); + QString dirstr = QFileDialog::getExistingDirectory(this, tr("Log directory"), LOCAL_PATH); + loadFiles(dirstr); } void IConfigLogging::loadFiles(const QString& path) { - ui->fileList->clear(); - ui->edPath->setText(path); - if (path.isEmpty()) - return; - QDir dir(path); - QStringList files = dir.entryList(QDir::Files, QDir::Name); - ui->fileList->addItems(files); + ui->fileList->clear(); + ui->edPath->setText(path); + if (path.isEmpty()) + return; + QDir dir(path); + QStringList files = dir.entryList(QDir::Files, QDir::Name); + ui->fileList->addItems(files); } void IConfigLogging::on_edPath_textChanged(const QString &arg1) { - loadFiles(ui->edPath->text()); + loadFiles(ui->edPath->text()); } void IConfigLogging::on_fileList_itemClicked(QListWidgetItem *item) { - if (!item) - return; + if (!item) + return; - QString filePath = ui->edPath->text() + "/" + item->text(); - QFile f(filePath); - if (!f.open(QIODevice::ReadOnly)) { - qWarning() << "Unable to open log file" << filePath; - return; - } - QByteArray data = f.readAll(); - f.close(); - ui->logView->setPlainText(data); + QString filePath = ui->edPath->text() + "/" + item->text(); + QFile f(filePath); + if (!f.open(QIODevice::ReadOnly)) { + qWarning() << "Unable to open log file" << filePath; + return; + } + QByteArray data = f.readAll(); + f.close(); + ui->logView->setPlainText(data); } diff --git a/IConfig/IConfigLogging.h b/IConfig/IConfigLogging.h index 44c10dc..b67c854 100644 --- a/IConfig/IConfigLogging.h +++ b/IConfig/IConfigLogging.h @@ -18,27 +18,27 @@ class IConfigLogging; class IConfigLogging : public QWidget { - Q_OBJECT + Q_OBJECT public: - explicit IConfigLogging(QWidget *parent = nullptr); - ~IConfigLogging(); - bool isChanged() const; - void save(); - void reset(); + explicit IConfigLogging(QWidget *parent = nullptr); + ~IConfigLogging(); + bool isChanged() const; + void save(); + void reset(); private slots: - void showEvent(QShowEvent* evt); - void on_btnBrowse_clicked(); - void on_edPath_textChanged(const QString &arg1); - void on_fileList_itemClicked(QListWidgetItem *item); + void showEvent(QShowEvent* evt); + void on_btnBrowse_clicked(); + void on_edPath_textChanged(const QString &arg1); + void on_fileList_itemClicked(QListWidgetItem *item); private: - void loadFiles(const QString& path); - Ui::IConfigLogging *ui; - bool cf_Chnanels; - bool cf_Privates; - QString cf_Path; + void loadFiles(const QString& path); + Ui::IConfigLogging *ui; + bool cf_Chnanels; + bool cf_Privates; + QString cf_Path; }; #endif // ICONFIGLOGGING_H diff --git a/IConfig/IConfigOptions.cpp b/IConfig/IConfigOptions.cpp index 659e2e4..9584a87 100644 --- a/IConfig/IConfigOptions.cpp +++ b/IConfig/IConfigOptions.cpp @@ -13,46 +13,46 @@ #include IConfigOptions::IConfigOptions(QWidget *parent) : - QWidget(parent), - ui(new Ui::IConfigOptions) + QWidget(parent), + ui(new Ui::IConfigOptions) { - ui->setupUi(this); - layout = new QVBoxLayout(ui->tabColors); - colorCfg = new ColorConfig; - { - QLabel* bgcolorhintlabel = new QLabel("Click on a text type to change its color.\nClick anywhere on the backgrounds to change background color."); - QFont labelFont = font(); - bgcolorhintlabel->setAlignment(Qt::AlignCenter); - labelFont.setPointSize(8); - bgcolorhintlabel->setFont(labelFont); - layout->addWidget(bgcolorhintlabel); - } - layout->addWidget(colorCfg); - colorCfg->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding); - ui->tabColors->setLayout(layout); + ui->setupUi(this); + layout = new QVBoxLayout(ui->tabColors); + colorCfg = new ColorConfig; + { + QLabel* bgcolorhintlabel = new QLabel("Click on a text type to change its color.\nClick anywhere on the backgrounds to change background color."); + QFont labelFont = font(); + bgcolorhintlabel->setAlignment(Qt::AlignCenter); + labelFont.setPointSize(8); + bgcolorhintlabel->setFont(labelFont); + layout->addWidget(bgcolorhintlabel); + } + layout->addWidget(colorCfg); + colorCfg->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding); + ui->tabColors->setLayout(layout); - /* Background opacity is not yet determined */ - ui->label_4->hide(); - ui->hsImageOpacity->hide(); + /* Background opacity is not yet determined */ + ui->label_4->hide(); + ui->hsImageOpacity->hide(); - /* Background scaling is not yet determined */ - ui->label_5->hide(); - ui->edImageScaling->hide(); + /* Background scaling is not yet determined */ + ui->label_5->hide(); + ui->edImageScaling->hide(); - reload(); - reset(); + reload(); + reset(); - cf_Font = ui->edFont->currentFont(); + cf_Font = ui->edFont->currentFont(); } IConfigOptions::~IConfigOptions() { - delete ui; + delete ui; } bool IConfigOptions::isChanged() const { - bool changed = cf_ShowOptions != ui->chkShowOptions->isChecked() + bool changed = cf_ShowOptions != ui->chkShowOptions->isChecked() || cf_Reconnect != ui->chkReconnect->isChecked() || cf_ReconnectDelay != ui->edReconnectDelay->value() || cf_RejoinChannelsOnConnect != ui->chkRejoinConnect->isChecked() @@ -75,10 +75,10 @@ bool IConfigOptions::isChanged() const || cf_SSLExpired != ui->chkSSLExpired->isChecked() || cf_SSLCNMismatch != ui->chkSSLCNMismatch->isChecked(); - if (changed) - return true; - else - return colorCfg->isChanged(); + if (changed) + return true; + else + return colorCfg->isChanged(); } void IConfigOptions::save() @@ -111,67 +111,67 @@ void IConfigOptions::save() void IConfigOptions::reset() { - ui->chkShowOptions->setChecked(cf_ShowOptions); - ui->chkReconnect->setChecked(cf_Reconnect); - ui->edReconnectDelay->setValue(cf_ReconnectDelay); - ui->chkRejoinConnect->setChecked(cf_RejoinChannelsOnConnect); - ui->chkWhoisActive->setChecked(cf_ShowWhoisActiveWindow); - ui->chkShowModeMsg->setChecked(cf_ShowModeInMessage); - ui->chkTrayNotify->setChecked(cf_TrayNotify); - ui->edTrayDelay->setValue(cf_TrayNotifyDelay); - ui->chkTimestamp->setChecked(cf_ShowTimestamp); - ui->edTimestamp->setText(cf_TimestampFormat); - ui->chkManualKeepalive->setChecked(cf_ManualKeepaliveEnabled); - ui->edManualKeepalive->setValue(cf_ManualKeepalive); - ui->edQuit->setText(cf_QuitMessage); - ui->edFont->setCurrentFont(cf_Font); - ui->edFontSize->setValue(cf_FontSize); - ui->chkEnableBgImage->setChecked(cf_BgImageEnabled); - ui->edImage->setText(cf_BgImagePath); - ui->hsImageOpacity->setValue(cf_BgImageOpacity); - ui->chkSSLSelfsigned->setChecked(cf_SSLSelfSigned); - ui->chkSSLExpired->setChecked(cf_SSLExpired); - ui->chkSSLCNMismatch->setChecked(cf_SSLCNMismatch); + ui->chkShowOptions->setChecked(cf_ShowOptions); + ui->chkReconnect->setChecked(cf_Reconnect); + ui->edReconnectDelay->setValue(cf_ReconnectDelay); + ui->chkRejoinConnect->setChecked(cf_RejoinChannelsOnConnect); + ui->chkWhoisActive->setChecked(cf_ShowWhoisActiveWindow); + ui->chkShowModeMsg->setChecked(cf_ShowModeInMessage); + ui->chkTrayNotify->setChecked(cf_TrayNotify); + ui->edTrayDelay->setValue(cf_TrayNotifyDelay); + ui->chkTimestamp->setChecked(cf_ShowTimestamp); + ui->edTimestamp->setText(cf_TimestampFormat); + ui->chkManualKeepalive->setChecked(cf_ManualKeepaliveEnabled); + ui->edManualKeepalive->setValue(cf_ManualKeepalive); + ui->edQuit->setText(cf_QuitMessage); + ui->edFont->setCurrentFont(cf_Font); + ui->edFontSize->setValue(cf_FontSize); + ui->chkEnableBgImage->setChecked(cf_BgImageEnabled); + ui->edImage->setText(cf_BgImagePath); + ui->hsImageOpacity->setValue(cf_BgImageOpacity); + ui->chkSSLSelfsigned->setChecked(cf_SSLSelfSigned); + ui->chkSSLExpired->setChecked(cf_SSLExpired); + ui->chkSSLCNMismatch->setChecked(cf_SSLCNMismatch); - colorCfg->reset(); + colorCfg->reset(); } void IConfigOptions::on_chkSSLExpired_toggled(bool checked) { - if (checked) - QMessageBox::warning(this, tr("Expired SSL certificates"), - tr("Allowing expired certificates is dangerous!\nThis option will revert after next connection.")); + if (checked) + QMessageBox::warning(this, tr("Expired SSL certificates"), + tr("Allowing expired certificates is dangerous!\nThis option will revert after next connection.")); } void IConfigOptions::reload() { - ConfigMgr& conf = ConfigMgr::instance(); - cf_ShowOptions = conf.common("ShowOptions").toInt(); - cf_Reconnect = conf.common("Reconnect").toInt(); - cf_ReconnectDelay = conf.common("ReconnectDelay").toInt(); - cf_RejoinChannelsOnConnect = conf.common("RejoinChannelsOnConnect").toInt(); - cf_ShowWhoisActiveWindow = conf.common("ShowWhoisActiveWindow").toInt(); - cf_ShowModeInMessage = conf.common("ShowModeInMessage").toInt(); - cf_TrayNotify = conf.common("TrayNotify").toInt(); - cf_TrayNotifyDelay = conf.common("TrayNotifyDelay").toInt(); - cf_ShowTimestamp = conf.common("ShowTimestamp").toInt(); + ConfigMgr& conf = ConfigMgr::instance(); + cf_ShowOptions = conf.common("ShowOptions").toInt(); + cf_Reconnect = conf.common("Reconnect").toInt(); + cf_ReconnectDelay = conf.common("ReconnectDelay").toInt(); + cf_RejoinChannelsOnConnect = conf.common("RejoinChannelsOnConnect").toInt(); + cf_ShowWhoisActiveWindow = conf.common("ShowWhoisActiveWindow").toInt(); + cf_ShowModeInMessage = conf.common("ShowModeInMessage").toInt(); + cf_TrayNotify = conf.common("TrayNotify").toInt(); + cf_TrayNotifyDelay = conf.common("TrayNotifyDelay").toInt(); + cf_ShowTimestamp = conf.common("ShowTimestamp").toInt(); cf_TimestampFormat = conf.common("TimestampFormat"); cf_ManualKeepaliveEnabled = conf.common("ManualKeepaliveEnabled").toInt(); cf_ManualKeepalive = conf.common("ManualKeepalive").toInt(); cf_QuitMessage = conf.common("QuitMessage"); - cf_Font = conf.common("Font"); - cf_FontSize = conf.common("FontSize").toInt(); - cf_BgImageEnabled = conf.common("BgImageEnabled").toInt(); - cf_BgImagePath = conf.common("BgImagePath"); - cf_BgImageOpacity = conf.common("BgImageOpacity").toInt(); - // TODO background image scaling combo box from config - cf_SSLSelfSigned = conf.common("SSLSelfsigned").toInt(); - cf_SSLExpired = conf.common("SSLExpired").toInt(); - cf_SSLCNMismatch = conf.common("SSLCNMismatch").toInt(); + cf_Font = conf.common("Font"); + cf_FontSize = conf.common("FontSize").toInt(); + cf_BgImageEnabled = conf.common("BgImageEnabled").toInt(); + cf_BgImagePath = conf.common("BgImagePath"); + cf_BgImageOpacity = conf.common("BgImageOpacity").toInt(); + // TODO background image scaling combo box from config + cf_SSLSelfSigned = conf.common("SSLSelfsigned").toInt(); + cf_SSLExpired = conf.common("SSLExpired").toInt(); + cf_SSLCNMismatch = conf.common("SSLCNMismatch").toInt(); } void IConfigOptions::on_btnImageBrowse_clicked() { - QString path = QFileDialog::getOpenFileName(this, tr("Choose background image"), LOCAL_PATH, tr("Image Files (*.png *.jpg *.bmp)")); - ui->edImage->setText(path); + QString path = QFileDialog::getOpenFileName(this, tr("Choose background image"), LOCAL_PATH, tr("Image Files (*.png *.jpg *.bmp)")); + ui->edImage->setText(path); } diff --git a/IConfig/IConfigOptions.h b/IConfig/IConfigOptions.h index 1f2c5e1..f0b98f1 100644 --- a/IConfig/IConfigOptions.h +++ b/IConfig/IConfigOptions.h @@ -19,46 +19,46 @@ class IConfigOptions; class IConfigOptions : public QWidget { - Q_OBJECT + Q_OBJECT public: - explicit IConfigOptions(QWidget *parent = nullptr); - ~IConfigOptions(); - bool isChanged() const; - void save(); - void reset(); + explicit IConfigOptions(QWidget *parent = nullptr); + ~IConfigOptions(); + bool isChanged() const; + void save(); + void reset(); private slots: - void on_chkSSLExpired_toggled(bool checked); - void on_btnImageBrowse_clicked(); + void on_chkSSLExpired_toggled(bool checked); + void on_btnImageBrowse_clicked(); private: - void reload(); - Ui::IConfigOptions *ui; - QVBoxLayout *layout; - ColorConfig *colorCfg; - bool cf_ShowOptions; - bool cf_Reconnect; - int cf_ReconnectDelay; - bool cf_RejoinChannelsOnConnect; - bool cf_ShowWhoisActiveWindow; - bool cf_ShowModeInMessage; - bool cf_TrayNotify; - int cf_TrayNotifyDelay; - bool cf_ShowTimestamp; - QString cf_TimestampFormat; + void reload(); + Ui::IConfigOptions *ui; + QVBoxLayout *layout; + ColorConfig *colorCfg; + bool cf_ShowOptions; + bool cf_Reconnect; + int cf_ReconnectDelay; + bool cf_RejoinChannelsOnConnect; + bool cf_ShowWhoisActiveWindow; + bool cf_ShowModeInMessage; + bool cf_TrayNotify; + int cf_TrayNotifyDelay; + bool cf_ShowTimestamp; + QString cf_TimestampFormat; bool cf_ManualKeepaliveEnabled; - int cf_ManualKeepalive; - QString cf_QuitMessage; - QFont cf_Font; - int cf_FontSize; - bool cf_BgImageEnabled; - QString cf_BgImagePath; - int cf_BgImageOpacity; - // TODO background image scaling combo box - bool cf_SSLSelfSigned; - bool cf_SSLExpired; - bool cf_SSLCNMismatch; + int cf_ManualKeepalive; + QString cf_QuitMessage; + QFont cf_Font; + int cf_FontSize; + bool cf_BgImageEnabled; + QString cf_BgImagePath; + int cf_BgImageOpacity; + // TODO background image scaling combo box + bool cf_SSLSelfSigned; + bool cf_SSLExpired; + bool cf_SSLCNMismatch; }; #endif // ICONFIGOPTIONS_H diff --git a/IConfig/IConfigServers.cpp b/IConfig/IConfigServers.cpp index 5c29469..b43358d 100644 --- a/IConfig/IConfigServers.cpp +++ b/IConfig/IConfigServers.cpp @@ -11,46 +11,46 @@ #include IConfigServers::IConfigServers(QWidget *parent) : - QWidget(parent), - ui(new Ui::IConfigServers) + QWidget(parent), + ui(new Ui::IConfigServers) { - ui->setupUi(this); - - ConfigMgr& conf = ConfigMgr::instance(); - cf_Realname = conf.connection("Realname"); - cf_Username = conf.connection("Username"); - cf_Nickname = conf.connection("Nickname"); - cf_AltNickame = conf.connection("AltNickname"); - cf_Server = conf.connection("Server"); - cf_Password = conf.connection("Password"); - cf_SSL = conf.connection("SSL").toInt(); - - ui->edRealName->setText(cf_Realname); - ui->edUsername->setText(cf_Username); - ui->edNickname->setText(cf_Nickname); - ui->edAltNickname->setText(cf_AltNickame); - ui->edServer->setText(cf_Server); - ui->edServerPassword->setText(cf_Password); - ui->chkSSL->setChecked(cf_SSL); - - editor = new ServerEditor(smodel, this); - ui->servers->setModel(&smodel); + ui->setupUi(this); + + ConfigMgr& conf = ConfigMgr::instance(); + cf_Realname = conf.connection("Realname"); + cf_Username = conf.connection("Username"); + cf_Nickname = conf.connection("Nickname"); + cf_AltNickame = conf.connection("AltNickname"); + cf_Server = conf.connection("Server"); + cf_Password = conf.connection("Password"); + cf_SSL = conf.connection("SSL").toInt(); + + ui->edRealName->setText(cf_Realname); + ui->edUsername->setText(cf_Username); + ui->edNickname->setText(cf_Nickname); + ui->edAltNickname->setText(cf_AltNickame); + ui->edServer->setText(cf_Server); + ui->edServerPassword->setText(cf_Password); + ui->chkSSL->setChecked(cf_SSL); + + editor = new ServerEditor(smodel, this); + ui->servers->setModel(&smodel); connect(editor, &ServerEditor::saveClicked, this, &IConfigServers::onServerEditorSaved); - QModelIndex sindex = smodel.indexFromHost(cf_Server); - if (sindex.isValid()) - ui->servers->selectionModel()->setCurrentIndex(sindex, QItemSelectionModel::Select | QItemSelectionModel::Rows); + QModelIndex sindex = smodel.indexFromHost(cf_Server); + if (sindex.isValid()) + ui->servers->selectionModel()->setCurrentIndex(sindex, QItemSelectionModel::Select | QItemSelectionModel::Rows); } IConfigServers::~IConfigServers() { - delete ui; + delete ui; } bool IConfigServers::isChanged() const { - return cf_Realname != ui->edRealName->text() + return cf_Realname != ui->edRealName->text() || cf_Username != ui->edUsername->text() || cf_Nickname != ui->edNickname->text() || cf_AltNickame != ui->edAltNickname->text() @@ -61,66 +61,66 @@ bool IConfigServers::isChanged() const bool IConfigServers::connectToNewStatus() const { - return ui->chkNewStatus->isChecked(); + return ui->chkNewStatus->isChecked(); } void IConfigServers::unsetConnectToNewStatus() { - ui->chkNewStatus->setChecked(false); + ui->chkNewStatus->setChecked(false); } void IConfigServers::save() { - ConfigMgr& conf = ConfigMgr::instance(); - conf.setConnection("Realname", ui->edRealName->text()); - conf.setConnection("Username", ui->edUsername->text()); - conf.setConnection("Nickname", ui->edNickname->text()); - conf.setConnection("AltNickname", ui->edAltNickname->text()); - conf.setConnection("Server", ui->edServer->text()); - conf.setConnection("Password", ui->edServerPassword->text()); - conf.setConnection("SSL", QString::number(ui->chkSSL->isChecked())); - - cf_Realname = conf.connection("Realname"); - cf_Username = conf.connection("Username"); - cf_Nickname = conf.connection("Nickname"); - cf_AltNickame = conf.connection("AltNickname"); - cf_Server = conf.connection("Server"); - cf_Password = conf.connection("Password"); - cf_SSL = conf.connection("SSL").toInt(); + ConfigMgr& conf = ConfigMgr::instance(); + conf.setConnection("Realname", ui->edRealName->text()); + conf.setConnection("Username", ui->edUsername->text()); + conf.setConnection("Nickname", ui->edNickname->text()); + conf.setConnection("AltNickname", ui->edAltNickname->text()); + conf.setConnection("Server", ui->edServer->text()); + conf.setConnection("Password", ui->edServerPassword->text()); + conf.setConnection("SSL", QString::number(ui->chkSSL->isChecked())); + + cf_Realname = conf.connection("Realname"); + cf_Username = conf.connection("Username"); + cf_Nickname = conf.connection("Nickname"); + cf_AltNickame = conf.connection("AltNickname"); + cf_Server = conf.connection("Server"); + cf_Password = conf.connection("Password"); + cf_SSL = conf.connection("SSL").toInt(); } void IConfigServers::reset() { - ui->edRealName->setText(cf_Realname); - ui->edUsername->setText(cf_Username); - ui->edNickname->setText(cf_Nickname); - ui->edAltNickname->setText(cf_AltNickame); - ui->edServer->setText(cf_Server); - ui->edServerPassword->setText(cf_Password); + ui->edRealName->setText(cf_Realname); + ui->edUsername->setText(cf_Username); + ui->edNickname->setText(cf_Nickname); + ui->edAltNickname->setText(cf_AltNickame); + ui->edServer->setText(cf_Server); + ui->edServerPassword->setText(cf_Password); } void IConfigServers::on_btnShowPassword_toggled(bool checked) { - ui->edServerPassword->setEchoMode(checked ? QLineEdit::Normal : QLineEdit::Password); + ui->edServerPassword->setEchoMode(checked ? QLineEdit::Normal : QLineEdit::Password); } void IConfigServers::on_btnEditServers_clicked() { - editor->show(); + editor->show(); } void IConfigServers::on_servers_clicked(const QModelIndex &index) { - auto spair = smodel.fromIndex(index); - QString details = smodel.details(spair.second, spair.first); - QString server; - QString password; + auto spair = smodel.fromIndex(index); + QString details = smodel.details(spair.second, spair.first); + QString server; + QString password; - if (details.contains('|')) { - password = details.split('|')[1]; - details.remove("|"+password); - } + if (details.contains('|')) { + password = details.split('|')[1]; + details.remove("|"+password); + } bool ssl = details[0] == '$'; if (ssl) @@ -128,8 +128,8 @@ void IConfigServers::on_servers_clicked(const QModelIndex &index) server = details; - ui->edServer->setText(server); - ui->edServerPassword->setText(password); + ui->edServer->setText(server); + ui->edServerPassword->setText(password); ui->chkSSL->setChecked(ssl); } diff --git a/IConfig/IConfigServers.h b/IConfig/IConfigServers.h index 9fe021a..8938003 100644 --- a/IConfig/IConfigServers.h +++ b/IConfig/IConfigServers.h @@ -18,34 +18,34 @@ class IConfigServers; class IConfigServers : public QWidget { - Q_OBJECT + Q_OBJECT public: - explicit IConfigServers(QWidget *parent = nullptr); - ~IConfigServers(); - bool isChanged() const; - bool connectToNewStatus() const; - void unsetConnectToNewStatus(); - void save(); - void reset(); + explicit IConfigServers(QWidget *parent = nullptr); + ~IConfigServers(); + bool isChanged() const; + bool connectToNewStatus() const; + void unsetConnectToNewStatus(); + void save(); + void reset(); private slots: - void on_btnShowPassword_toggled(bool checked); - void on_btnEditServers_clicked(); - void on_servers_clicked(const QModelIndex &index); + void on_btnShowPassword_toggled(bool checked); + void on_btnEditServers_clicked(); + void on_servers_clicked(const QModelIndex &index); void onServerEditorSaved(); private: - Ui::IConfigServers *ui; - ServerModel smodel; - ServerEditor *editor; - QString cf_Realname; - QString cf_Username; - QString cf_Nickname; - QString cf_AltNickame; - QString cf_Server; - QString cf_Password; - bool cf_SSL; + Ui::IConfigServers *ui; + ServerModel smodel; + ServerEditor *editor; + QString cf_Realname; + QString cf_Username; + QString cf_Nickname; + QString cf_AltNickame; + QString cf_Server; + QString cf_Password; + bool cf_SSL; }; #endif // ICONFIGSERVERS_H diff --git a/IConfig/ServerEditor.cpp b/IConfig/ServerEditor.cpp index dada276..996d2ac 100644 --- a/IConfig/ServerEditor.cpp +++ b/IConfig/ServerEditor.cpp @@ -12,291 +12,291 @@ #include ServerEditor::ServerEditor(ServerModel& model, QWidget* parent) - : QDialog(parent) - , ui(new Ui::ServerEditor) - , smodel(model) + : QDialog(parent) + , ui(new Ui::ServerEditor) + , smodel(model) { - ui->setupUi(this); - addMenu = new QMenu(this); - addServerAction = addMenu->addAction(tr("Server"), this, &ServerEditor::on_addServerAction_triggered); - addNetworkAction = addMenu->addAction(tr("Network"), this, &ServerEditor::on_addNetworkAction_triggered); - ui->btnAdd->setMenu(addMenu); - ui->serverView->setModel(&smodel); - ui->serverView->header()->setSectionResizeMode(QHeaderView::Interactive); - - QStringList networks = smodel.networkList(); - ui->edNetwork->addItem(""); - for (const QString& network : networks) { - if (network == "NONE") - continue; - ui->edNetwork->addItem(network); - } + ui->setupUi(this); + addMenu = new QMenu(this); + addServerAction = addMenu->addAction(tr("Server"), this, &ServerEditor::on_addServerAction_triggered); + addNetworkAction = addMenu->addAction(tr("Network"), this, &ServerEditor::on_addNetworkAction_triggered); + ui->btnAdd->setMenu(addMenu); + ui->serverView->setModel(&smodel); + ui->serverView->header()->setSectionResizeMode(QHeaderView::Interactive); + + QStringList networks = smodel.networkList(); + ui->edNetwork->addItem(""); + for (const QString& network : networks) { + if (network == "NONE") + continue; + ui->edNetwork->addItem(network); + } } ServerEditor::~ServerEditor() { - delete ui; + delete ui; } void ServerEditor::on_addServerAction_triggered() { - QString network = "NONE"; - if (editMode == EditMode::Network) { - QModelIndex current = ui->serverView->currentIndex(); - auto spair = smodel.fromIndex(current); - network = spair.first; - } - else if (editMode == EditMode::Server) { - QModelIndex current = ui->serverView->currentIndex(); - if (current.parent().isValid()) { - auto spair = smodel.fromIndex(current.parent()); - network = spair.first; - } - } - - QString name; - QString host; - for (int i = 1 ;; ++i) { - name = QStringLiteral("New server %1").arg(i); - host = QStringLiteral("host%1.name:6667").arg(i); - QString det = smodel.details(name); - if (det.isEmpty()) - break; - } - QModelIndex idx = smodel.addServer(name, host, network); - selectItem(idx); + QString network = "NONE"; + if (editMode == EditMode::Network) { + QModelIndex current = ui->serverView->currentIndex(); + auto spair = smodel.fromIndex(current); + network = spair.first; + } + else if (editMode == EditMode::Server) { + QModelIndex current = ui->serverView->currentIndex(); + if (current.parent().isValid()) { + auto spair = smodel.fromIndex(current.parent()); + network = spair.first; + } + } + + QString name; + QString host; + for (int i = 1 ;; ++i) { + name = QStringLiteral("New server %1").arg(i); + host = QStringLiteral("host%1.name:6667").arg(i); + QString det = smodel.details(name); + if (det.isEmpty()) + break; + } + QModelIndex idx = smodel.addServer(name, host, network); + selectItem(idx); } void ServerEditor::on_addNetworkAction_triggered() { - QString name; - QString host; - for (int i = 1 ;; ++i) { - name = QStringLiteral("New network %1").arg(i); - host = QStringLiteral("irc%1.host.name:6667").arg(i); - QString det = smodel.details("DEFAULT", name); - if (det.isEmpty()) - break; - } - QModelIndex idx = smodel.addNetwork(name, host); - ui->edNetwork->addItem(name); - selectItem(idx); + QString name; + QString host; + for (int i = 1 ;; ++i) { + name = QStringLiteral("New network %1").arg(i); + host = QStringLiteral("irc%1.host.name:6667").arg(i); + QString det = smodel.details("DEFAULT", name); + if (det.isEmpty()) + break; + } + QModelIndex idx = smodel.addNetwork(name, host); + ui->edNetwork->addItem(name); + selectItem(idx); } void ServerEditor::on_btnDel_clicked() { - if (editMode == EditMode::Off) - return; - - QModelIndex current = ui->serverView->currentIndex(); - auto spair = smodel.fromIndex(current); - QString network = spair.first; - QString name = spair.second; - - if (editMode == EditMode::Server) { - if (QMessageBox::question(this, tr("Delete server"), tr("Do you want to delete the server '%1'?").arg(name)) == QMessageBox::No) - return; - smodel.delServer(name, network); - } - - if (editMode == EditMode::Network) { - name = spair.first; - auto answer = QMessageBox::question(this, tr("Delete network"), tr("Do you want to delete the network '%1'?\nHitting 'Yes' will keep the servers as orphans.").arg(name), QMessageBox::Yes | QMessageBox::YesAll | QMessageBox::No); - if (answer == QMessageBox::No) - return; - bool keepServers = answer != QMessageBox::YesAll; - smodel.delNetwork(name, keepServers); - } - - ui->serverView->clearSelection(); - disableAll(); + if (editMode == EditMode::Off) + return; + + QModelIndex current = ui->serverView->currentIndex(); + auto spair = smodel.fromIndex(current); + QString network = spair.first; + QString name = spair.second; + + if (editMode == EditMode::Server) { + if (QMessageBox::question(this, tr("Delete server"), tr("Do you want to delete the server '%1'?").arg(name)) == QMessageBox::No) + return; + smodel.delServer(name, network); + } + + if (editMode == EditMode::Network) { + name = spair.first; + auto answer = QMessageBox::question(this, tr("Delete network"), tr("Do you want to delete the network '%1'?\nHitting 'Yes' will keep the servers as orphans.").arg(name), QMessageBox::Yes | QMessageBox::YesAll | QMessageBox::No); + if (answer == QMessageBox::No) + return; + bool keepServers = answer != QMessageBox::YesAll; + smodel.delNetwork(name, keepServers); + } + + ui->serverView->clearSelection(); + disableAll(); } void ServerEditor::on_btnShowPassword_toggled(bool checked) { - ui->edPassword->setEchoMode(checked ? QLineEdit::Normal : QLineEdit::Password); + ui->edPassword->setEchoMode(checked ? QLineEdit::Normal : QLineEdit::Password); } void ServerEditor::on_btnSave_clicked() { - if (editMode == EditMode::Off) - return; + if (editMode == EditMode::Off) + return; - if (ui->edName->text().isEmpty()) { - QMessageBox::information(this, tr("Field missing"), tr("No name is specified.")); - return; - } + if (ui->edName->text().isEmpty()) { + QMessageBox::information(this, tr("Field missing"), tr("No name is specified.")); + return; + } - if (ui->edHostname->text().isEmpty()) { - QMessageBox::information(this, tr("Field missing"), tr("No hostname is specified.")); - return; - } + if (ui->edHostname->text().isEmpty()) { + QMessageBox::information(this, tr("Field missing"), tr("No hostname is specified.")); + return; + } - if (editMode == EditMode::Server) - saveServerEdit(); + if (editMode == EditMode::Server) + saveServerEdit(); - else if (editMode == EditMode::Network) - saveNetworkEdit(); + else if (editMode == EditMode::Network) + saveNetworkEdit(); emit saveClicked(); } void ServerEditor::enableForServer() { - enableAll(); - ui->lbNetwork->show(); - ui->edNetwork->show(); - editMode = EditMode::Server; + enableAll(); + ui->lbNetwork->show(); + ui->edNetwork->show(); + editMode = EditMode::Server; } void ServerEditor::enableForNetwork() { - enableAll(); - ui->lbNetwork->hide(); - ui->edNetwork->hide(); - editMode = EditMode::Network; + enableAll(); + ui->lbNetwork->hide(); + ui->edNetwork->hide(); + editMode = EditMode::Network; } void ServerEditor::enableAll() { - ui->edName->setEnabled(true); - ui->edHostname->setEnabled(true); - ui->edPort->setEnabled(true); - ui->edPassword->setEnabled(true); - ui->btnShowPassword->setEnabled(true); - ui->btnShowPassword->setChecked(false); - ui->edNetwork->setEnabled(true); - ui->btnSave->setEnabled(true); + ui->edName->setEnabled(true); + ui->edHostname->setEnabled(true); + ui->edPort->setEnabled(true); + ui->edPassword->setEnabled(true); + ui->btnShowPassword->setEnabled(true); + ui->btnShowPassword->setChecked(false); + ui->edNetwork->setEnabled(true); + ui->btnSave->setEnabled(true); } void ServerEditor::disableAll() { - ui->edName->clear(); - ui->edHostname->clear(); - ui->edPort->setValue(6667); - ui->edPassword->clear(); - ui->btnShowPassword->setChecked(false); - ui->edNetwork->clearEditText(); - - ui->edName->setEnabled(false); - ui->edHostname->setEnabled(false); - ui->edPort->setEnabled(false); - ui->edPassword->setEnabled(false); - ui->btnShowPassword->setEnabled(false); - ui->edNetwork->setEnabled(false); - ui->btnSave->setEnabled(false); - ui->lbNetwork->show(); - ui->edNetwork->show(); - - editMode = EditMode::Off; + ui->edName->clear(); + ui->edHostname->clear(); + ui->edPort->setValue(6667); + ui->edPassword->clear(); + ui->btnShowPassword->setChecked(false); + ui->edNetwork->clearEditText(); + + ui->edName->setEnabled(false); + ui->edHostname->setEnabled(false); + ui->edPort->setEnabled(false); + ui->edPassword->setEnabled(false); + ui->btnShowPassword->setEnabled(false); + ui->edNetwork->setEnabled(false); + ui->btnSave->setEnabled(false); + ui->lbNetwork->show(); + ui->edNetwork->show(); + + editMode = EditMode::Off; } void ServerEditor::saveNetworkEdit() { - qDebug() << "Save network"; - - QModelIndex current = ui->serverView->currentIndex(); - auto spair = smodel.fromIndex(current); - QString network = spair.first; - - /* Network name changed */ - if (network != ui->edName->text()) { - QString newNetwork = ui->edName->text(); - if (ui->edNetwork->findText(newNetwork) > -1) { - QMessageBox::information(this, tr("Duplicate network name"), tr("The specified network name already exist.")); - return; - } - smodel.renameNetwork(network, newNetwork); - int networkIdx = ui->edNetwork->findText(network); - ui->edNetwork->setItemText(networkIdx, newNetwork); - network = newNetwork; - } - - QString details = ui->edHostname->text() + ":" + QString::number(ui->edPort->value()); - QString password = ui->edPassword->text(); - if (!password.isEmpty()) - details += "|" + password; - smodel.setNetworkServer(network, details); + qDebug() << "Save network"; + + QModelIndex current = ui->serverView->currentIndex(); + auto spair = smodel.fromIndex(current); + QString network = spair.first; + + /* Network name changed */ + if (network != ui->edName->text()) { + QString newNetwork = ui->edName->text(); + if (ui->edNetwork->findText(newNetwork) > -1) { + QMessageBox::information(this, tr("Duplicate network name"), tr("The specified network name already exist.")); + return; + } + smodel.renameNetwork(network, newNetwork); + int networkIdx = ui->edNetwork->findText(network); + ui->edNetwork->setItemText(networkIdx, newNetwork); + network = newNetwork; + } + + QString details = ui->edHostname->text() + ":" + QString::number(ui->edPort->value()); + QString password = ui->edPassword->text(); + if (!password.isEmpty()) + details += "|" + password; + smodel.setNetworkServer(network, details); } void ServerEditor::saveServerEdit() { - qDebug() << "Save server"; - QModelIndex current = ui->serverView->currentIndex(); - auto spair = smodel.fromIndex(current); + qDebug() << "Save server"; + QModelIndex current = ui->serverView->currentIndex(); + auto spair = smodel.fromIndex(current); - QString name = ui->edName->text(); - QString host = ui->edHostname->text(); - QString port = QString::number(ui->edPort->value()); - QString password = ui->edPassword->text(); - QString network = ui->edNetwork->currentText(); + QString name = ui->edName->text(); + QString host = ui->edHostname->text(); + QString port = QString::number(ui->edPort->value()); + QString password = ui->edPassword->text(); + QString network = ui->edNetwork->currentText(); if (ui->chkSSL->isChecked()) host.prepend('$'); - if (ui->edNetwork->currentIndex() == 0) - network = "NONE"; + if (ui->edNetwork->currentIndex() == 0) + network = "NONE"; if (spair.first != network) { - /* New network */ - if (network != "NONE" && ui->edNetwork->findText(network) == -1) { - bool ok = false; - QString hostname = QInputDialog::getText(this, tr("New network"), tr("Set hostname:port for the new network %1").arg(network), QLineEdit::Normal, "", &ok); - if (!ok || hostname.isEmpty()) - return; - - smodel.addNetwork(network, hostname); - ui->edNetwork->addItem(network); - } - - QString details = smodel.details(spair.second, spair.first); - smodel.delServer(spair.second, spair.first); - QModelIndex idx = smodel.addServer(spair.second, details, network); - selectItem(idx); - } - - smodel.setServer(spair.second, host + ":" + port, password, network); - if (spair.second != name) { - QString details = smodel.details(spair.second, network); - smodel.delServer(spair.second, network); - smodel.resetModel(); - QModelIndex idx = smodel.addServer(name, details, network); - selectItem(idx); - } + /* New network */ + if (network != "NONE" && ui->edNetwork->findText(network) == -1) { + bool ok = false; + QString hostname = QInputDialog::getText(this, tr("New network"), tr("Set hostname:port for the new network %1").arg(network), QLineEdit::Normal, "", &ok); + if (!ok || hostname.isEmpty()) + return; + + smodel.addNetwork(network, hostname); + ui->edNetwork->addItem(network); + } + + QString details = smodel.details(spair.second, spair.first); + smodel.delServer(spair.second, spair.first); + QModelIndex idx = smodel.addServer(spair.second, details, network); + selectItem(idx); + } + + smodel.setServer(spair.second, host + ":" + port, password, network); + if (spair.second != name) { + QString details = smodel.details(spair.second, network); + smodel.delServer(spair.second, network); + smodel.resetModel(); + QModelIndex idx = smodel.addServer(name, details, network); + selectItem(idx); + } } void ServerEditor::selectItem(const QModelIndex& index) { - ui->serverView->clearSelection(); - ui->serverView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select | QItemSelectionModel::Rows); - on_serverView_clicked(index); + ui->serverView->clearSelection(); + ui->serverView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select | QItemSelectionModel::Rows); + on_serverView_clicked(index); } void ServerEditor::on_serverView_clicked(const QModelIndex &index) { - if (!index.isValid()) { - disableAll(); - return; - } - - auto spair = smodel.fromIndex(index); - if (spair.first.isEmpty()) { - disableAll(); - return; - } - - QString name; - if (spair.second == "DEFAULT") { - name = spair.first; - enableForNetwork(); - } - else { - name = spair.second; - enableForServer(); - } - - QString details = smodel.details(spair.second, spair.first); - QString host, port, password; + if (!index.isValid()) { + disableAll(); + return; + } + + auto spair = smodel.fromIndex(index); + if (spair.first.isEmpty()) { + disableAll(); + return; + } + + QString name; + if (spair.second == "DEFAULT") { + name = spair.first; + enableForNetwork(); + } + else { + name = spair.second; + enableForServer(); + } + + QString details = smodel.details(spair.second, spair.first); + QString host, port, password; // Value format: $host:port|password // Presence of '$' determines if it's an SSL server. @@ -306,25 +306,25 @@ void ServerEditor::on_serverView_clicked(const QModelIndex &index) details = details.mid(1); if (details.contains('|')) { - password = details.split('|')[1]; - details = details.remove("|"+password); - } + password = details.split('|')[1]; + details = details.remove("|"+password); + } if (details.contains(':')) { - port = details.split(':')[1]; - details = details.remove(":"+port); - } + port = details.split(':')[1]; + details = details.remove(":"+port); + } host = details; - ui->edName->setText(name); - ui->edHostname->setText(host); - ui->edPort->setValue(port.toInt()); - ui->edPassword->setText(password); + ui->edName->setText(name); + ui->edHostname->setText(host); + ui->edPort->setValue(port.toInt()); + ui->edPassword->setText(password); ui->chkSSL->setChecked(ssl); - int networkUiIndex = ui->edNetwork->findText(spair.first); - if (networkUiIndex == -1) - networkUiIndex = 0; - ui->edNetwork->setCurrentIndex(networkUiIndex); + int networkUiIndex = ui->edNetwork->findText(spair.first); + if (networkUiIndex == -1) + networkUiIndex = 0; + ui->edNetwork->setCurrentIndex(networkUiIndex); } diff --git a/IConfig/ServerEditor.h b/IConfig/ServerEditor.h index a837892..eaa1a30 100644 --- a/IConfig/ServerEditor.h +++ b/IConfig/ServerEditor.h @@ -18,45 +18,45 @@ class ServerEditor; class ServerEditor : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit ServerEditor(ServerModel& model, QWidget *parent = nullptr); - ~ServerEditor(); + explicit ServerEditor(ServerModel& model, QWidget *parent = nullptr); + ~ServerEditor(); signals: void saveClicked(); private slots: - void on_addServerAction_triggered(); - void on_addNetworkAction_triggered(); - void on_btnDel_clicked(); - void on_btnShowPassword_toggled(bool checked); - void on_btnSave_clicked(); - void on_serverView_clicked(const QModelIndex &index); + void on_addServerAction_triggered(); + void on_addNetworkAction_triggered(); + void on_btnDel_clicked(); + void on_btnShowPassword_toggled(bool checked); + void on_btnSave_clicked(); + void on_serverView_clicked(const QModelIndex &index); private: - enum class EditMode { - Off, - Server, - Network - } editMode = EditMode::Off; - - void enableForServer(); - void enableForNetwork(); - void enableAll(); - void disableAll(); - - void saveNetworkEdit(); - void saveServerEdit(); - - void selectItem(const QModelIndex& index); - - Ui::ServerEditor* ui; - QMenu* addMenu; - QAction* addServerAction; - QAction* addNetworkAction; - ServerModel& smodel; + enum class EditMode { + Off, + Server, + Network + } editMode = EditMode::Off; + + void enableForServer(); + void enableForNetwork(); + void enableAll(); + void disableAll(); + + void saveNetworkEdit(); + void saveServerEdit(); + + void selectItem(const QModelIndex& index); + + Ui::ServerEditor* ui; + QMenu* addMenu; + QAction* addServerAction; + QAction* addNetworkAction; + ServerModel& smodel; }; #endif // SERVEREDITOR_H diff --git a/IConfig/ServerMgr.cpp b/IConfig/ServerMgr.cpp index 8d79754..28908e2 100644 --- a/IConfig/ServerMgr.cpp +++ b/IConfig/ServerMgr.cpp @@ -11,16 +11,16 @@ ServerMgr::ServerMgr(QObject *parent) : QObject(parent), - ini( QString(LOCAL_PATH+"/servers.ini").toStdString() ) + ini( QString(LOCAL_PATH+"/servers.ini").toStdString() ) { } QStringList ServerMgr::networkList() { - int count = ini.count(); + int count = ini.count(); QStringList r; - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { const auto name = QString::fromStdString( ini.section(i) ); r.push_back(name); } @@ -32,12 +32,12 @@ QHash ServerMgr::serverList(const QString& network) { const auto networkStr = network.toStdString(); - int count = ini.count(networkStr); + int count = ini.count(networkStr); QHash r; - for (int i = 0; i < count; i++) { - const auto servername = QString::fromStdString( ini.item(networkStr, i) ); - const auto serverdetails = QString::fromStdString( ini.read(networkStr, i) ); + for (int i = 0; i < count; i++) { + const auto servername = QString::fromStdString( ini.item(networkStr, i) ); + const auto serverdetails = QString::fromStdString( ini.read(networkStr, i) ); r.insert(servername, serverdetails); } @@ -46,48 +46,48 @@ QHash ServerMgr::serverList(const QString& network) QString ServerMgr::defaultServer(const QString& network) { - return QString::fromStdString( ini.read(network.toStdString(), "DEFAULT") ); + return QString::fromStdString( ini.read(network.toStdString(), "DEFAULT") ); } bool ServerMgr::addNetwork(const QString& name) { const auto nameStr = name.toStdString(); - if (nameStr == "NONE" || ini.exist(nameStr)) - return false; + if (nameStr == "NONE" || ini.exist(nameStr)) + return false; - ini.write(nameStr, "DEFAULT", "server.name"); - return true; + ini.write(nameStr, "DEFAULT", "server.name"); + return true; } bool ServerMgr::renameNetwork(const QString& o_name, const QString& n_name) { - if ((o_name == "NONE") || (n_name == "NONE")) - return false; + if ((o_name == "NONE") || (n_name == "NONE")) + return false; - auto err = ini.rename(o_name.toStdString(), n_name.toStdString()); - return err == IniFile::Error::NoError; + auto err = ini.rename(o_name.toStdString(), n_name.toStdString()); + return err == IniFile::Error::NoError; } void ServerMgr::delNetwork(const QString& name, bool keep_servers) { // If servers=true, we will keep the servers by moving them to the NONE section. - const auto nameStr = name.toStdString(); - if (! ini.exist(nameStr)) + const auto nameStr = name.toStdString(); + if (! ini.exist(nameStr)) return; if (keep_servers) { - int max = ini.count(nameStr); - for (int i = 0; i < max; i++) { - auto item = fmt::format("{}_{}", name.toStdString(), ini.item(nameStr, i)); - auto value = ini.read(nameStr, i); + int max = ini.count(nameStr); + for (int i = 0; i < max; i++) { + auto item = fmt::format("{}_{}", name.toStdString(), ini.item(nameStr, i)); + auto value = ini.read(nameStr, i); - ini.write("NONE", item, value); + ini.write("NONE", item, value); } } - ini.remove(nameStr); + ini.remove(nameStr); } bool ServerMgr::addServer(const QString& name, const QString& host, const QString& pw, const QString& network) @@ -105,29 +105,29 @@ bool ServerMgr::addServer(const QString& name, const QString& host, const QStrin const auto networkStr = network.toStdString(); - if (!ini.exist(networkStr) && networkStr != "NONE") + if (!ini.exist(networkStr) && networkStr != "NONE") return false; - ini.write(networkStr, name.toStdString(), details.toStdString()); + ini.write(networkStr, name.toStdString(), details.toStdString()); return true; } void ServerMgr::delServer(const QString& name, const QString& network) { - ini.remove(network.toStdString(), name.toStdString()); + ini.remove(network.toStdString(), name.toStdString()); } bool ServerMgr::hasNetwork(const QString& name) { - return ini.exist(name.toStdString()); + return ini.exist(name.toStdString()); } bool ServerMgr::hasServer(const QString& name, const QString& network) { - return ini.exist(network.toStdString(), name.toStdString()); + return ini.exist(network.toStdString(), name.toStdString()); } QString ServerMgr::getServerDetails(const QString& name, const QString& network) { - return QString::fromStdString( ini.read(network.toStdString(), name.toStdString()) ); + return QString::fromStdString( ini.read(network.toStdString(), name.toStdString()) ); } diff --git a/IConfig/ServerMgr.h b/IConfig/ServerMgr.h index 4562269..dd61dfa 100644 --- a/IConfig/ServerMgr.h +++ b/IConfig/ServerMgr.h @@ -24,7 +24,7 @@ class ServerMgr : public QObject Q_OBJECT public: - explicit ServerMgr(QObject *parent = nullptr); + explicit ServerMgr(QObject *parent = nullptr); // All networks in a string list (Also counts in the NONE network) QStringList networkList(); @@ -36,9 +36,9 @@ public: QString defaultServer(const QString& network); // Add new network to servers.ini - returns false if network exist - bool addNetwork(const QString& name); + bool addNetwork(const QString& name); - // Rename a network - returns false if new network name already exist + // Rename a network - returns false if new network name already exist bool renameNetwork(const QString& o_name, const QString& n_name); // Delete network diff --git a/IConfig/ServerModel.cpp b/IConfig/ServerModel.cpp index e2ee3fa..898d25e 100644 --- a/IConfig/ServerModel.cpp +++ b/IConfig/ServerModel.cpp @@ -17,43 +17,43 @@ ServerModel::ServerModel(QObject *parent) : QModelIndex ServerModel::indexFromHost(QString hostname) { - return hostmap.value(hostname, QModelIndex()); + return hostmap.value(hostname, QModelIndex()); } QPair ServerModel::fromIndex(const QModelIndex& index) { - /* Locate netmap */ - { - QHashIterator it(netmap); - while (it.hasNext()) { - const QString& network = it.next().key(); - const QModelIndex& iidx = it.value(); - if (index == iidx || index == iidx.siblingAtColumn(1)) - return { network, "DEFAULT" }; - - for (int i = 0 ;; ++i) { - QModelIndex cidx = iidx.child(i, 0); - if (!cidx.isValid()) - break; - QString name = cidx.data().toString(); - if (index == cidx || index == cidx.siblingAtColumn(1)) - return { network, name }; - } - } - } - - /* Locate nonemap */ - { - QHashIterator it(hostmap); - while (it.hasNext()) { - it.next(); - const QModelIndex& iidx = it.value(); - if (index == iidx || index == iidx.siblingAtColumn(1)) - return { "NONE", iidx.data().toString() }; - } - } - - return {}; + /* Locate netmap */ + { + QHashIterator it(netmap); + while (it.hasNext()) { + const QString& network = it.next().key(); + const QModelIndex& iidx = it.value(); + if (index == iidx || index == iidx.siblingAtColumn(1)) + return { network, "DEFAULT" }; + + for (int i = 0 ;; ++i) { + QModelIndex cidx = iidx.child(i, 0); + if (!cidx.isValid()) + break; + QString name = cidx.data().toString(); + if (index == cidx || index == cidx.siblingAtColumn(1)) + return { network, name }; + } + } + } + + /* Locate nonemap */ + { + QHashIterator it(hostmap); + while (it.hasNext()) { + it.next(); + const QModelIndex& iidx = it.value(); + if (index == iidx || index == iidx.siblingAtColumn(1)) + return { "NONE", iidx.data().toString() }; + } + } + + return {}; } QModelIndex ServerModel::addNetwork(QString name, QString server) @@ -69,10 +69,10 @@ QModelIndex ServerModel::addNetwork(QString name, QString server) hostmap.insert(server, pname->index()); netmap.insert(name, pname->index()); - if (smgr.addNetwork(name)) - smgr.addServer("DEFAULT", server, "", name); + if (smgr.addNetwork(name)) + smgr.addServer("DEFAULT", server, "", name); - return pname->index(); + return pname->index(); } void ServerModel::setNetworkServer(QString name, QString server) @@ -83,7 +83,7 @@ void ServerModel::setNetworkServer(QString name, QString server) QStandardItem *item = itemFromIndex(serverIndex); item->setText(server); - smgr.addServer("DEFAULT", server, "", name); + smgr.addServer("DEFAULT", server, "", name); } void ServerModel::renameNetwork(QString name, QString newname) @@ -97,40 +97,40 @@ void ServerModel::renameNetwork(QString name, QString newname) netmap.remove(name); netmap.insert(newname, current); - smgr.renameNetwork(name, newname); + smgr.renameNetwork(name, newname); } void ServerModel::delNetwork(QString name, bool keepServers) { - smgr.delNetwork(name, keepServers); - resetModel(); + smgr.delNetwork(name, keepServers); + resetModel(); } QModelIndex ServerModel::addServer(QString name, QString server, QString network) { - QStandardItem *parent; + QStandardItem *parent; - if (network.length() == 0) - network = "NONE"; + if (network.length() == 0) + network = "NONE"; - if (network == "NONE") - parent = invisibleRootItem(); - else - parent = itemFromIndex( netmap.value(network) ); + if (network == "NONE") + parent = invisibleRootItem(); + else + parent = itemFromIndex( netmap.value(network) ); - QStandardItem *sname = new QStandardItem(QIcon(":/options/gfx/server.png"), name); - QStandardItem *shost = new QStandardItem(server); - QList list; - list << sname << shost; + QStandardItem *sname = new QStandardItem(QIcon(":/options/gfx/server.png"), name); + QStandardItem *shost = new QStandardItem(server); + QList list; + list << sname << shost; - parent->appendRow(list); - hostmap.insert(server, indexFromItem(sname)); - if (network == "NONE") - nonemap.insert(name, indexFromItem(sname)); + parent->appendRow(list); + hostmap.insert(server, indexFromItem(sname)); + if (network == "NONE") + nonemap.insert(name, indexFromItem(sname)); - smgr.addServer(name, server, "", network); + smgr.addServer(name, server, "", network); - return indexFromItem(sname); + return indexFromItem(sname); } void ServerModel::setServer(QString name, QString server, QString password, QString network) @@ -178,7 +178,7 @@ void ServerModel::setServer(QString name, QString server, QString password, QStr serverItem->setText(host); hostmap.insert(host, nameIndex); - smgr.addServer(name, server, password, network); + smgr.addServer(name, server, password, network); } void ServerModel::renameServer(QString name, QString newname, QString network) @@ -221,9 +221,9 @@ void ServerModel::renameServer(QString name, QString newname, QString network) QStandardItem *item = itemFromIndex(serverIndex); item->setText(newname); - QString details = smgr.getServerDetails(name, network); - smgr.delServer(name, network); - smgr.addServer(name, details, "", network); + QString details = smgr.getServerDetails(name, network); + smgr.delServer(name, network); + smgr.addServer(name, details, "", network); } void ServerModel::delServer(QString name, QString network) @@ -263,7 +263,7 @@ void ServerModel::delServer(QString name, QString network) int row = current.row(); removeRow(row, current.parent()); - smgr.delServer(name, network); + smgr.delServer(name, network); } void ServerModel::resetModel() @@ -279,90 +279,88 @@ void ServerModel::resetModel() setHorizontalHeaderItem(0, i); setHorizontalHeaderLabels(l); - hostmap.clear(); - netmap.clear(); - nonemap.clear(); + hostmap.clear(); + netmap.clear(); + nonemap.clear(); - QStringList netlist = smgr.networkList(); + QStringList netlist = smgr.networkList(); - if (netlist.contains("NONE")) { // "None" network is a section with servers not assigned to a network. - QHash sl = smgr.serverList("NONE"); - QHashIterator i(sl); - while (i.hasNext()) { - i.next(); - // Key: Server name - // Value: host:port|pass - QString name = i.key(); - QString detail = i.value(); + if (netlist.contains("NONE")) { // "None" network is a section with servers not assigned to a network. + QHash sl = smgr.serverList("NONE"); + QHashIterator i(sl); + while (i.hasNext()) { + i.next(); + // Key: Server name + // Value: host:port|pass + QString name = i.key(); + QString detail = i.value(); - QString host; // hostname with port, e.g. irc.network.org:6667 - host = detail.split('|')[0]; + QString host; // hostname with port, e.g. irc.network.org:6667 + host = detail.split('|')[0]; - if (host[0] == '$') + if (host[0] == '$') host = host.mid(1); - QStandardItem *itemname = new QStandardItem(QIcon(":/options/gfx/server.png"), name); - QStandardItem *itemhost = new QStandardItem(host); - QList list; - list << itemname << itemhost; + QStandardItem *itemname = new QStandardItem(QIcon(":/options/gfx/server.png"), name); + QStandardItem *itemhost = new QStandardItem(host); + QList list; + list << itemname << itemhost; - root->appendRow(list); - hostmap.insert(host, indexFromItem(itemname)); - nonemap.insert(name, indexFromItem(itemname)); - - } - } - - for (int i = 0; i <= netlist.count()-1; ++i) { + root->appendRow(list); + hostmap.insert(host, indexFromItem(itemname)); + nonemap.insert(name, indexFromItem(itemname)); + } + } + for (int i = 0; i <= netlist.count()-1; ++i) { if (netlist[i] == "NONE") continue; // The "None" network already taken care of - ignore. - QString data = smgr.defaultServer(netlist[i]); - QString host = data.split('|')[0]; - - QStandardItem *pname = new QStandardItem(QIcon(":/options/gfx/network.png"), netlist[i]); // parent name - QStandardItem *phost = new QStandardItem(host); // parent host - QList list; - list << pname << phost; - - root->appendRow(list); - hostmap.insert(host, pname->index()); - netmap.insert(netlist[i], pname->index()); - - QHash sl = smgr.serverList(netlist[i]); - QHashIterator sli(sl); - while (sli.hasNext()) { - sli.next(); - // Key: Server name - // Value: host:port|pass - QString name = sli.key(); - if (name == "DEFAULT") - continue; // The default value already taken care of, it's the address of parent item. - QString detail = sli.value(); - QString host; // hostname with port, e.g. irc.network.org:6667 - host = detail.split('|')[0]; - - if (host[0] == '$') - host = host.mid(1); - - QStandardItem *itemname = new QStandardItem(QIcon(":/options/gfx/server.png"), name); // parent name - QStandardItem *itemhost = new QStandardItem(host); // parent host - QList list; - list << itemname << itemhost; - - pname->appendRow(list); - hostmap.insert(host, indexFromItem(itemname)); - } - } + QString data = smgr.defaultServer(netlist[i]); + QString host = data.split('|')[0]; + + QStandardItem *pname = new QStandardItem(QIcon(":/options/gfx/network.png"), netlist[i]); // parent name + QStandardItem *phost = new QStandardItem(host); // parent host + QList list; + list << pname << phost; + + root->appendRow(list); + hostmap.insert(host, pname->index()); + netmap.insert(netlist[i], pname->index()); + + QHash sl = smgr.serverList(netlist[i]); + QHashIterator sli(sl); + while (sli.hasNext()) { + sli.next(); + // Key: Server name + // Value: host:port|pass + QString name = sli.key(); + if (name == "DEFAULT") + continue; // The default value already taken care of, it's the address of parent item. + QString detail = sli.value(); + QString host; // hostname with port, e.g. irc.network.org:6667 + host = detail.split('|')[0]; + + if (host[0] == '$') + host = host.mid(1); + + QStandardItem *itemname = new QStandardItem(QIcon(":/options/gfx/server.png"), name); // parent name + QStandardItem *itemhost = new QStandardItem(host); // parent host + QList list; + list << itemname << itemhost; + + pname->appendRow(list); + hostmap.insert(host, indexFromItem(itemname)); + } + } } QStringList ServerModel::networkList() { - return smgr.networkList(); + return smgr.networkList(); } QString ServerModel::details(QString name, QString network) { - return smgr.getServerDetails(name, network); + return smgr.getServerDetails(name, network); } diff --git a/IConfig/ServerModel.h b/IConfig/ServerModel.h index fd149ac..a44d822 100644 --- a/IConfig/ServerModel.h +++ b/IConfig/ServerModel.h @@ -23,21 +23,21 @@ class ServerModel : public QStandardItemModel Q_OBJECT public: - explicit ServerModel(QObject *parent = nullptr); + explicit ServerModel(QObject *parent = nullptr); QModelIndex indexFromHost(QString hostname); // Hostname:Port - QPair fromIndex(const QModelIndex& index); + QPair fromIndex(const QModelIndex& index); - QModelIndex addNetwork(QString name, QString server); + QModelIndex addNetwork(QString name, QString server); void setNetworkServer(QString name, QString server = ""); void renameNetwork(QString name, QString newname); - void delNetwork(QString name, bool keepServers); - QModelIndex addServer(QString name, QString server, QString network = "NONE"); - void setServer(QString name, QString server, QString password, QString network = "NONE"); + void delNetwork(QString name, bool keepServers); + QModelIndex addServer(QString name, QString server, QString network = "NONE"); + void setServer(QString name, QString server, QString password, QString network = "NONE"); void renameServer(QString name, QString newname, QString network = "NONE"); void delServer(QString name, QString network = "NONE"); void resetModel(); - QStringList networkList(); - QString details(QString name, QString network = "NONE"); + QStringList networkList(); + QString details(QString name, QString network = "NONE"); private: ServerMgr smgr; diff --git a/IRCClient/Commands.h b/IRCClient/Commands.h index f6c42e3..22d12fa 100644 --- a/IRCClient/Commands.h +++ b/IRCClient/Commands.h @@ -10,66 +10,66 @@ namespace Command { namespace IRC { - constexpr auto* PASS = "PASS"; - constexpr auto* NICK = "NICK"; - constexpr auto* USER = "USER"; - constexpr auto* OPER = "OPER"; - constexpr auto* MODE = "MODE"; - constexpr auto* QUIT = "QUIT"; - constexpr auto* SQUIT = "SQUIT"; - constexpr auto* JOIN = "JOIN"; - constexpr auto* PART = "PART"; - constexpr auto* TOPIC = "TOPIC"; - constexpr auto* NAMES = "NAMES"; - constexpr auto* LIST = "LIST"; - constexpr auto* INVITE = "INVITE"; - constexpr auto* KICK = "KICK"; - constexpr auto* PRIVMSG = "PRIVMSG"; - constexpr auto* NOTICE = "NOTICE"; - constexpr auto* MOTD = "MOTD"; - constexpr auto* LUSERS = "LUSERS"; - constexpr auto* VERSION = "VERSION"; - constexpr auto* STATS = "STATS"; - constexpr auto* LINKS = "LINKS"; - constexpr auto* TIME = "TIME"; - constexpr auto* CONNECT = "CONNECT"; - constexpr auto* TRACE = "TRACE"; - constexpr auto* ADMIN = "ADMIN"; - constexpr auto* INFO = "INFO"; - constexpr auto* SERVLIST = "SERVLIST"; - constexpr auto* SQUERY = "SQUERY"; - constexpr auto* WHO = "WHO"; - constexpr auto* WHOIS = "WHOIS"; - constexpr auto* WHOWAS = "WHOWAS"; - constexpr auto* KILL = "KILL"; - constexpr auto* PING = "PING"; - constexpr auto* PONG = "PONG"; - constexpr auto* ERROR_ = "ERROR"; // Environment for msvc already defines ERROR as a macro of sorts... - constexpr auto* AWAY = "AWAY"; - constexpr auto* REHASH = "REHASH"; - constexpr auto* DIE = "DIE"; - constexpr auto* RESTART = "RESTART"; - constexpr auto* SUMMON = "SUMMON"; - constexpr auto* USERS = "USERS"; - constexpr auto* WALLOPS = "WALLOPS"; - constexpr auto* USERHOST = "USERHOST"; - constexpr auto* ISON = "ISON"; + constexpr auto* PASS = "PASS"; + constexpr auto* NICK = "NICK"; + constexpr auto* USER = "USER"; + constexpr auto* OPER = "OPER"; + constexpr auto* MODE = "MODE"; + constexpr auto* QUIT = "QUIT"; + constexpr auto* SQUIT = "SQUIT"; + constexpr auto* JOIN = "JOIN"; + constexpr auto* PART = "PART"; + constexpr auto* TOPIC = "TOPIC"; + constexpr auto* NAMES = "NAMES"; + constexpr auto* LIST = "LIST"; + constexpr auto* INVITE = "INVITE"; + constexpr auto* KICK = "KICK"; + constexpr auto* PRIVMSG = "PRIVMSG"; + constexpr auto* NOTICE = "NOTICE"; + constexpr auto* MOTD = "MOTD"; + constexpr auto* LUSERS = "LUSERS"; + constexpr auto* VERSION = "VERSION"; + constexpr auto* STATS = "STATS"; + constexpr auto* LINKS = "LINKS"; + constexpr auto* TIME = "TIME"; + constexpr auto* CONNECT = "CONNECT"; + constexpr auto* TRACE = "TRACE"; + constexpr auto* ADMIN = "ADMIN"; + constexpr auto* INFO = "INFO"; + constexpr auto* SERVLIST = "SERVLIST"; + constexpr auto* SQUERY = "SQUERY"; + constexpr auto* WHO = "WHO"; + constexpr auto* WHOIS = "WHOIS"; + constexpr auto* WHOWAS = "WHOWAS"; + constexpr auto* KILL = "KILL"; + constexpr auto* PING = "PING"; + constexpr auto* PONG = "PONG"; + constexpr auto* ERROR_ = "ERROR"; // Environment for msvc already defines ERROR as a macro of sorts... + constexpr auto* AWAY = "AWAY"; + constexpr auto* REHASH = "REHASH"; + constexpr auto* DIE = "DIE"; + constexpr auto* RESTART = "RESTART"; + constexpr auto* SUMMON = "SUMMON"; + constexpr auto* USERS = "USERS"; + constexpr auto* WALLOPS = "WALLOPS"; + constexpr auto* USERHOST = "USERHOST"; + constexpr auto* ISON = "ISON"; } namespace Extension { - constexpr auto* ACCOUNT = "ACCOUNT"; + constexpr auto* ACCOUNT = "ACCOUNT"; } namespace IRCv3 { - constexpr auto* CAP = "CAP"; - constexpr auto* LS = "LS"; - constexpr auto* LIST = "LIST"; - constexpr auto* REQ = "REQ"; - constexpr auto* ACK = "ACK"; - constexpr auto* NAK = "NAK"; - constexpr auto* END = "END"; - constexpr auto* NEW = "NEW"; - constexpr auto* DEL = "DEL"; + constexpr auto* CAP = "CAP"; + constexpr auto* LS = "LS"; + constexpr auto* LIST = "LIST"; + constexpr auto* REQ = "REQ"; + constexpr auto* ACK = "ACK"; + constexpr auto* NAK = "NAK"; + constexpr auto* END = "END"; + constexpr auto* NEW = "NEW"; + constexpr auto* DEL = "DEL"; } // namespace IRCv3 } // namespace command diff --git a/IRCClient/DCC.cpp b/IRCClient/DCC.cpp index f39b8fc..14ac5ce 100644 --- a/IRCClient/DCC.cpp +++ b/IRCClient/DCC.cpp @@ -14,201 +14,201 @@ using asio::ip::tcp; struct DCCPriv { - DCCPriv(DCC& super_, IRCBase& ircctx_, DCC::Direction dir_, asio::io_context& ioctx_, const std::string& ip_, const std::string& port_) - : super(super_) - , ircctx(ircctx_) - , direction(dir_) - , ioctx(ioctx_) - , ip(ip_) - , port(port_) - , resolver(ioctx_) - , acceptor(ioctx_) - , endpoint(tcp::v4(), std::stoi(port_)) - , socket(ioctx_) - {} - - DCC& super; - IRCBase& ircctx; - - bool pending{ true }; - const DCC::Direction direction; - asio::io_context& ioctx; - std::string ip; // Only used when Direction=Target, and describes the Initiator's IP. - std::string port; - - tcp::resolver resolver; // for outbound connection (we act as a Target) - tcp::acceptor acceptor; // for inbound connection (we act as an Initiator) - - tcp::resolver::results_type resolverResults; - asio::ip::tcp::endpoint endpoint; - tcp::socket socket; - - asio::streambuf readbuf; - - DCC::CallbackRead cbRead; - DCC::CallbackConnected cbCon; - DCC::CallbackDisconnected cbDiscon; - - void connected(const asio::error_code& ec) - { - super.onConnected(); - - asio::streambuf::mutable_buffers_type mutableBuf{ readbuf.prepare(16384) }; - socket.async_receive(mutableBuf, - [this](const asio::error_code& ec, std::size_t rl){ - readbuf.commit(rl); - read(ec); - }); - } - - void disconnected(const asio::error_code& ec) - { - super.onDisconnected(SystemErrorToIRCError(ec)); - } - - void read(const asio::error_code& ec) - { - if (ec) { - disconnected(ec); - return; - } - - std::istream is(&readbuf); - super.onRead(is); - - asio::streambuf::mutable_buffers_type mutableBuf{ readbuf.prepare(16384) }; - socket.async_receive(mutableBuf, - [this](const asio::error_code& ec, std::size_t rl){ - readbuf.commit(rl); - read(ec); - }); - } - - void writeFinished(const asio::error_code& ec, std::size_t bytes_transferred) - { - std::cout << "DCC wrote " << bytes_transferred << " bytes." << std::endl; - if (!ec) return; // No errors. - std::cerr << fmt::format("'- DCC write error: {} ({})", SystemErrorToIRCError(ec), ec.message()) << std::endl; - } + DCCPriv(DCC& super_, IRCBase& ircctx_, DCC::Direction dir_, asio::io_context& ioctx_, const std::string& ip_, const std::string& port_) + : super(super_) + , ircctx(ircctx_) + , direction(dir_) + , ioctx(ioctx_) + , ip(ip_) + , port(port_) + , resolver(ioctx_) + , acceptor(ioctx_) + , endpoint(tcp::v4(), std::stoi(port_)) + , socket(ioctx_) + {} + + DCC& super; + IRCBase& ircctx; + + bool pending{ true }; + const DCC::Direction direction; + asio::io_context& ioctx; + std::string ip; // Only used when Direction=Target, and describes the Initiator's IP. + std::string port; + + tcp::resolver resolver; // for outbound connection (we act as a Target) + tcp::acceptor acceptor; // for inbound connection (we act as an Initiator) + + tcp::resolver::results_type resolverResults; + asio::ip::tcp::endpoint endpoint; + tcp::socket socket; + + asio::streambuf readbuf; + + DCC::CallbackRead cbRead; + DCC::CallbackConnected cbCon; + DCC::CallbackDisconnected cbDiscon; + + void connected(const asio::error_code& ec) + { + super.onConnected(); + + asio::streambuf::mutable_buffers_type mutableBuf{ readbuf.prepare(16384) }; + socket.async_receive(mutableBuf, + [this](const asio::error_code& ec, std::size_t rl){ + readbuf.commit(rl); + read(ec); + }); + } + + void disconnected(const asio::error_code& ec) + { + super.onDisconnected(SystemErrorToIRCError(ec)); + } + + void read(const asio::error_code& ec) + { + if (ec) { + disconnected(ec); + return; + } + + std::istream is(&readbuf); + super.onRead(is); + + asio::streambuf::mutable_buffers_type mutableBuf{ readbuf.prepare(16384) }; + socket.async_receive(mutableBuf, + [this](const asio::error_code& ec, std::size_t rl){ + readbuf.commit(rl); + read(ec); + }); + } + + void writeFinished(const asio::error_code& ec, std::size_t bytes_transferred) + { + std::cout << "DCC wrote " << bytes_transferred << " bytes." << std::endl; + if (!ec) return; // No errors. + std::cerr << fmt::format("'- DCC write error: {} ({})", SystemErrorToIRCError(ec), ec.message()) << std::endl; + } }; DCC::DCC(IRCBase& ircctx, asio::io_context& ioctx, const std::string& port) - : mp(std::make_unique(*this, ircctx, Direction::Initiator, ioctx, "", port)) + : mp(std::make_unique(*this, ircctx, Direction::Initiator, ioctx, "", port)) { - mp->acceptor.open(mp->endpoint.protocol()); - mp->acceptor.bind(mp->endpoint); - mp->acceptor.listen(1); - mp->acceptor.async_accept(mp->socket, [this](const asio::error_code& ec){ - if (ec) - mp->disconnected(ec); - else - mp->connected(ec); - }); + mp->acceptor.open(mp->endpoint.protocol()); + mp->acceptor.bind(mp->endpoint); + mp->acceptor.listen(1); + mp->acceptor.async_accept(mp->socket, [this](const asio::error_code& ec){ + if (ec) + mp->disconnected(ec); + else + mp->connected(ec); + }); } DCC::DCC(IRCBase& ircctx, asio::io_context& ioctx, const std::string& ip, const std::string& port) - : mp(std::make_unique(*this, ircctx, Direction::Target, ioctx, ip, port)) + : mp(std::make_unique(*this, ircctx, Direction::Target, ioctx, ip, port)) {} DCC::DCC(DCC&& other) noexcept - : mp(std::move(other.mp)) + : mp(std::move(other.mp)) {} DCC::~DCC() { - try { - if (mp->socket.is_open()) { - mp->socket.shutdown(asio::socket_base::shutdown_both); - mp->socket.close(); - } - if (mp->direction == Direction::Initiator) - mp->acceptor.close(); - } - catch(const asio::system_error& e) { - // Properly log e.what() or e.code() maybe? - std::cerr << fmt::format("~DCC() caught exception ({}): {}\n IP={}, Port={}, Direction={}", - e.code().value(), e.what(), mp->ip, mp->port, mp->direction) << std::endl; - } + try { + if (mp->socket.is_open()) { + mp->socket.shutdown(asio::socket_base::shutdown_both); + mp->socket.close(); + } + if (mp->direction == Direction::Initiator) + mp->acceptor.close(); + } + catch(const asio::system_error& e) { + // Properly log e.what() or e.code() maybe? + std::cerr << fmt::format("~DCC() caught exception ({}): {}\n IP={}, Port={}, Direction={}", + e.code().value(), e.what(), mp->ip, mp->port, mp->direction) << std::endl; + } } bool DCC::isPending() const { - return mp->pending; + return mp->pending; } IRCError DCC::accept() { - if (mp->direction == Direction::Initiator) - return IRCError::DCC_NotATarget; // Only usable if we are a Target... + if (mp->direction == Direction::Initiator) + return IRCError::DCC_NotATarget; // Only usable if we are a Target... - mp->resolverResults = mp->resolver.resolve(mp->ip, mp->port); + mp->resolverResults = mp->resolver.resolve(mp->ip, mp->port); - asio::async_connect(mp->socket, mp->resolverResults, - [this](const asio::error_code& ec, const tcp::endpoint&) { - if (ec) - mp->disconnected(ec); - else - mp->connected(ec); - }); + asio::async_connect(mp->socket, mp->resolverResults, + [this](const asio::error_code& ec, const tcp::endpoint&) { + if (ec) + mp->disconnected(ec); + else + mp->connected(ec); + }); - mp->pending = false; - return IRCError::NoError; + mp->pending = false; + return IRCError::NoError; } DCC::Direction DCC::direction() const { - return mp->direction; + return mp->direction; } void DCC::write(const ByteString& data) { - mp->socket.async_send(asio::buffer(data), - [this](const asio::error_code& ec, std::size_t bytes_transferred){ - mp->writeFinished(ec, bytes_transferred); - }); + mp->socket.async_send(asio::buffer(data), + [this](const asio::error_code& ec, std::size_t bytes_transferred){ + mp->writeFinished(ec, bytes_transferred); + }); } IRCBase& DCC::context() { - return mp->ircctx; + return mp->ircctx; } const IRCBase& DCC::context() const { - return mp->ircctx; + return mp->ircctx; } void DCC::callbackRead(DCC::CallbackRead&& cb) { - mp->cbRead = std::move(cb); + mp->cbRead = std::move(cb); } void DCC::callbackConnected(DCC::CallbackConnected&& cb) { - mp->cbCon = std::move(cb); + mp->cbCon = std::move(cb); } void DCC::callbackDisconnected(DCC::CallbackDisconnected&& cb) { - mp->cbDiscon = std::move(cb); + mp->cbDiscon = std::move(cb); } void DCC::onRead(std::istream& is) { - if (mp->cbRead) - mp->cbRead(is); + if (mp->cbRead) + mp->cbRead(is); } void DCC::onConnected() { - if (mp->cbCon) - mp->cbCon(); + if (mp->cbCon) + mp->cbCon(); } void DCC::onDisconnected(IRCError e) { - if (mp->cbDiscon) - mp->cbDiscon(e); + if (mp->cbDiscon) + mp->cbDiscon(e); } diff --git a/IRCClient/DCC.h b/IRCClient/DCC.h index 86812ff..0c24aa6 100644 --- a/IRCClient/DCC.h +++ b/IRCClient/DCC.h @@ -20,61 +20,61 @@ class IRCBase; struct DCCPriv; class DCC { - friend struct IRCBasePriv; - friend struct DCCPriv; + friend struct IRCBasePriv; + friend struct DCCPriv; public: - using CallbackRead = std::function; - using CallbackConnected = std::function; - using CallbackDisconnected = std::function; - using ByteString = std::basic_string; + using CallbackRead = std::function; + using CallbackConnected = std::function; + using CallbackDisconnected = std::function; + using ByteString = std::basic_string; - /* - * Initiator acts as the server, and the target is the client - */ - enum class Direction { - Initiator, - Target - }; + /* + * Initiator acts as the server, and the target is the client + */ + enum class Direction { + Initiator, + Target + }; - ~DCC(); - DCC(DCC&& other) noexcept; + ~DCC(); + DCC(DCC&& other) noexcept; - //! Constructs an Initiator (server) - DCC(IRCBase& ircctx, asio::io_context& ioctx, const std::string& port); + //! Constructs an Initiator (server) + DCC(IRCBase& ircctx, asio::io_context& ioctx, const std::string& port); - //! Constructs a Target (client) - DCC(IRCBase& ircctx, asio::io_context& ioctx, const std::string& ip, const std::string& port); + //! Constructs a Target (client) + DCC(IRCBase& ircctx, asio::io_context& ioctx, const std::string& ip, const std::string& port); - [[nodiscard]] bool isPending() const; - IRCError accept(); + [[nodiscard]] bool isPending() const; + IRCError accept(); - [[nodiscard]] Direction direction() const; + [[nodiscard]] Direction direction() const; - void write(const ByteString& data); + void write(const ByteString& data); - IRCBase& context(); - const IRCBase& context() const; + IRCBase& context(); + const IRCBase& context() const; - /* - * Callbacks used by 'users' of this class. - */ - void callbackRead(CallbackRead&& cb); - void callbackConnected(CallbackConnected&& cb); - void callbackDisconnected(CallbackDisconnected&& cb); + /* + * Callbacks used by 'users' of this class. + */ + void callbackRead(CallbackRead&& cb); + void callbackConnected(CallbackConnected&& cb); + void callbackDisconnected(CallbackDisconnected&& cb); protected: - /* - * Use these to read data in a custom derivative of DCC. - * If you re-implement any of these, make sure to forward the - * calls to this base class at the end of your function. - */ - virtual void onRead(std::istream& is); - virtual void onConnected(); - virtual void onDisconnected(IRCError e); + /* + * Use these to read data in a custom derivative of DCC. + * If you re-implement any of these, make sure to forward the + * calls to this base class at the end of your function. + */ + virtual void onRead(std::istream& is); + virtual void onConnected(); + virtual void onDisconnected(IRCError e); private: - std::unique_ptr mp; + std::unique_ptr mp; }; #endif // DCC_H diff --git a/IRCClient/IRCBase.cpp b/IRCClient/IRCBase.cpp index b09e6bb..03ec6ab 100644 --- a/IRCClient/IRCBase.cpp +++ b/IRCClient/IRCBase.cpp @@ -20,125 +20,125 @@ #include IRCBase::IRCBase() - : mp(new IRCBasePriv(*this)) + : mp(new IRCBasePriv(*this)) {} IRCBase::IRCBase(IRCBase&& other) noexcept - : mp(std::move(other.mp)) + : mp(std::move(other.mp)) {} IRCBase::~IRCBase() = default; bool IRCBase::poll() { - asio::error_code ioctxerr; - bool ioDidSomething = false; - try { - ioDidSomething = mp->ioctx.poll_one(ioctxerr) > 0; - } - catch (const std::system_error& e) { - mp->lastError = SystemErrorToIRCError(e); - mp->disconnectHandler(); - return false; - } + asio::error_code ioctxerr; + bool ioDidSomething = false; + try { + ioDidSomething = mp->ioctx.poll_one(ioctxerr) > 0; + } + catch (const std::system_error& e) { + mp->lastError = SystemErrorToIRCError(e); + mp->disconnectHandler(); + return false; + } - if (ioctxerr.value() != 0) - std::cout << fmt::format("IOCTX err {}: {}", ioctxerr.value(), ioctxerr.message()) << std::endl; - return ioDidSomething; + if (ioctxerr.value() != 0) + std::cout << fmt::format("IOCTX err {}: {}", ioctxerr.value(), ioctxerr.message()) << std::endl; + return ioDidSomething; } const std::string& IRCBase::getHostname() const { - return mp->hostname; + return mp->hostname; } IRCError IRCBase::setHostname(const std::string& hostname, bool SSL) { - if (isOnline()) - return IRCError::CannotChangeWhenConnected; - mp->useSSL = SSL; - mp->hostname = hostname; - return IRCError::NoError; + if (isOnline()) + return IRCError::CannotChangeWhenConnected; + mp->useSSL = SSL; + mp->hostname = hostname; + return IRCError::NoError; } const std::string& IRCBase::getPort() const { - return mp->port; + return mp->port; } IRCError IRCBase::setPort(const std::string& port) { - if (isOnline()) - return IRCError::CannotChangeWhenConnected; - mp->port = port; - return IRCError::NoError; + if (isOnline()) + return IRCError::CannotChangeWhenConnected; + mp->port = port; + return IRCError::NoError; } const std::string& IRCBase::getRealname() const { - return mp->realname; + return mp->realname; } IRCError IRCBase::setRealname(const std::string& realname) { - if (isOnline()) - return IRCError::CannotChangeWhenConnected; - mp->realname = realname; - return IRCError::NoError; + if (isOnline()) + return IRCError::CannotChangeWhenConnected; + mp->realname = realname; + return IRCError::NoError; } const std::string& IRCBase::getIdent() const { - return mp->ident; + return mp->ident; } IRCError IRCBase::setIdent(const std::string& ident) { - if (isOnline()) - return IRCError::CannotChangeWhenConnected; - mp->ident = ident; - return IRCError::NoError; + if (isOnline()) + return IRCError::CannotChangeWhenConnected; + mp->ident = ident; + return IRCError::NoError; } const std::string& IRCBase::getNickname() const { - return mp->nickname; + return mp->nickname; } void IRCBase::setNickname(const std::string& nickname) { - if (mp->isConnected) { + if (mp->isConnected) { if (!isOnline()) mp->nickname = nickname; mp->write(Command::IRC::NICK, nickname); } - else - mp->nickname = nickname; + else + mp->nickname = nickname; } const std::string& IRCBase::getPassword() const { - return mp->password; + return mp->password; } void IRCBase::setPassword(const std::string& password) { - mp->password = password; + mp->password = password; } void IRCBase::exceptSSL_SelfSigned(bool except) { - mp->sslExcept.selfSigned = except; + mp->sslExcept.selfSigned = except; } void IRCBase::exceptSSL_CNMismatch(bool except) { - mp->sslExcept.CNMismactch = except; + mp->sslExcept.CNMismactch = except; } void IRCBase::exceptSSL_Expired(bool except) { - mp->sslExcept.expired = except; + mp->sslExcept.expired = except; } void IRCBase::command(const std::string& command, const std::vector& args, const std::string& msg) @@ -146,10 +146,10 @@ void IRCBase::command(const std::string& command, const std::vector if (!mp->isConnected) return; - if (msg.empty()) - mp->writeNoMsg(command, args); - else - mp->write(command, args, msg); + if (msg.empty()) + mp->writeNoMsg(command, args); + else + mp->write(command, args, msg); } void IRCBase::command(const std::string& command, const std::string& msg) @@ -157,7 +157,7 @@ void IRCBase::command(const std::string& command, const std::string& msg) if (!mp->isConnected) return; - mp->write(command, msg); + mp->write(command, msg); } void IRCBase::raw(const std::string& data) @@ -165,7 +165,7 @@ void IRCBase::raw(const std::string& data) if (!mp->isConnected) return; - mp->writeNoMsg(data, {}); + mp->writeNoMsg(data, {}); } void IRCBase::ctcpRequest(const std::string& target, const std::string& command, const std::string& message) @@ -180,54 +180,54 @@ void IRCBase::ctcpResponse(const std::string& target, const std::string& command void IRCBase::setManualKeepalive(std::chrono::seconds freq) { - mp->keepaliveFreq = freq; - if (mp->isOnline) { - if (freq > std::chrono::seconds(0)) - mp->startKeepaliveTimer(); - else - mp->stopKeepaliveTimer(); - } + mp->keepaliveFreq = freq; + if (mp->isOnline) { + if (freq > std::chrono::seconds(0)) + mp->startKeepaliveTimer(); + else + mp->stopKeepaliveTimer(); + } } std::chrono::milliseconds IRCBase::getManualKeepaliveFreq() const { - return mp->keepaliveFreq; + return mp->keepaliveFreq; } asio::io_context& IRCBase::getIOCTX() { - return mp->ioctx; + return mp->ioctx; } std::string IRCBase::toMemberPrefix(const std::string& modes) const { // PREFIX=(qaohv)~&@%+ - const auto& prefixdef = mp->isupport.at("PREFIX"); // PREFIX is always present. + const auto& prefixdef = mp->isupport.at("PREFIX"); // PREFIX is always present. - const auto prefixmodes = prefixdef.substr(1, prefixdef.find_first_of(')') - 1); - const auto prefix = prefixdef.substr(prefixdef.find_first_of(')') + 1); + const auto prefixmodes = prefixdef.substr(1, prefixdef.find_first_of(')') - 1); + const auto prefix = prefixdef.substr(prefixdef.find_first_of(')') + 1); - std::string ret; + std::string ret; - for (const char m : modes) { - // Only accept a-zA-Z - if (!(m > 'a' && m < 'z' || m > 'A' && m < 'Z')) { // De Morgan pls halp - ret += ':'; - continue; - } + for (const char m : modes) { + // Only accept a-zA-Z + if (!(m > 'a' && m < 'z' || m > 'A' && m < 'Z')) { // De Morgan pls halp + ret += ':'; + continue; + } - const auto ctpos = prefixmodes.find_first_of(m); - if (ctpos == std::string::npos) - ret += ':'; - else - ret += prefix[ctpos]; - } + const auto ctpos = prefixmodes.find_first_of(m); + if (ctpos == std::string::npos) + ret += ':'; + else + ret += prefix[ctpos]; + } - return ret; + return ret; } bool IRCBase::isChannelSymbol(char c) { - return mp->isChannelSymbol(c); + return mp->isChannelSymbol(c); } char IRCBase::channelModeGroup(char m) const @@ -237,180 +237,180 @@ char IRCBase::channelModeGroup(char m) const IRCError IRCBase::tryConnect() { - if (isOnline()) - return IRCError::AlreadyConnected; + if (isOnline()) + return IRCError::AlreadyConnected; - if (mp->hostname.empty()) - return IRCError::HostNotSet; + if (mp->hostname.empty()) + return IRCError::HostNotSet; - if (mp->port.empty()) - return IRCError::PortNotSet; + if (mp->port.empty()) + return IRCError::PortNotSet; - if (mp->ident.empty()) - return IRCError::IdentNotSet; + if (mp->ident.empty()) + return IRCError::IdentNotSet; - if (mp->nickname.empty()) - return IRCError::NicknameNotSet; + if (mp->nickname.empty()) + return IRCError::NicknameNotSet; - if (mp->realname.empty()) - return IRCError::RealnameNotSet; + if (mp->realname.empty()) + return IRCError::RealnameNotSet; - try { + try { mp->sslExceptions.clear(); - mp->ioctx.restart(); - mp->endpoints = mp->resolver.resolve(mp->hostname, mp->port); - if (mp->endpoints.empty()) - return IRCError::CannotResolveAddress; - - if (mp->useSSL) { - mp->sslsock.emplace(mp->ioctx, mp->sslctx); - - mp->sslsock->set_verify_mode(asio::ssl::verify_peer); - mp->sslsock->set_verify_callback([this](bool preverified, asio::ssl::verify_context& vc){ - if (preverified) - return true; - - X509* cert = X509_STORE_CTX_get_current_cert(vc.native_handle()); - mp->lastError = mp->verify_X509(cert); - if (mp->lastError != IRCError::NoError) { - onConnectionError(mp->lastError); - return false; - } - else - return true; - }); - - asio::async_connect(mp->sslsock->lowest_layer(), mp->endpoints, - [this](const asio::error_code& ec, const tcp::endpoint&) { - std::cout << "ssl connect error: " << ec.value() << " " << ec.message() << std::endl; - mp->lastError = SystemErrorToIRCError(ec); - if (ec) { - onConnectionError(mp->lastError); - return; - } - mp->sslsock->async_handshake(asio::ssl::stream_base::client, - [this](asio::error_code ec) { - mp->lastError = SystemErrorToIRCError(ec); - if (ec) { - onConnectionError(mp->lastError); - return; - } - // TODO error codes! - std::cout << "ssl handshake error: " << ec.value() << " " << ec.message() << std::endl; - mp->connected(ec); - }); - }); - } - else { - mp->sock.emplace(mp->ioctx); - asio::async_connect(mp->sock.value(), mp->endpoints, - [this](const asio::error_code& ec, const tcp::endpoint&) { - mp->lastError = SystemErrorToIRCError(ec); - if (ec) { - onConnectionError(mp->lastError); - return; - } - mp->connected(ec); - } - ); - } - } - catch (const std::system_error& e) { - return SystemErrorToIRCError(e); - } - - return IRCError::NoError; + mp->ioctx.restart(); + mp->endpoints = mp->resolver.resolve(mp->hostname, mp->port); + if (mp->endpoints.empty()) + return IRCError::CannotResolveAddress; + + if (mp->useSSL) { + mp->sslsock.emplace(mp->ioctx, mp->sslctx); + + mp->sslsock->set_verify_mode(asio::ssl::verify_peer); + mp->sslsock->set_verify_callback([this](bool preverified, asio::ssl::verify_context& vc){ + if (preverified) + return true; + + X509* cert = X509_STORE_CTX_get_current_cert(vc.native_handle()); + mp->lastError = mp->verify_X509(cert); + if (mp->lastError != IRCError::NoError) { + onConnectionError(mp->lastError); + return false; + } + else + return true; + }); + + asio::async_connect(mp->sslsock->lowest_layer(), mp->endpoints, + [this](const asio::error_code& ec, const tcp::endpoint&) { + std::cout << "ssl connect error: " << ec.value() << " " << ec.message() << std::endl; + mp->lastError = SystemErrorToIRCError(ec); + if (ec) { + onConnectionError(mp->lastError); + return; + } + mp->sslsock->async_handshake(asio::ssl::stream_base::client, + [this](asio::error_code ec) { + mp->lastError = SystemErrorToIRCError(ec); + if (ec) { + onConnectionError(mp->lastError); + return; + } + // TODO error codes! + std::cout << "ssl handshake error: " << ec.value() << " " << ec.message() << std::endl; + mp->connected(ec); + }); + }); + } + else { + mp->sock.emplace(mp->ioctx); + asio::async_connect(mp->sock.value(), mp->endpoints, + [this](const asio::error_code& ec, const tcp::endpoint&) { + mp->lastError = SystemErrorToIRCError(ec); + if (ec) { + onConnectionError(mp->lastError); + return; + } + mp->connected(ec); + } + ); + } + } + catch (const std::system_error& e) { + return SystemErrorToIRCError(e); + } + + return IRCError::NoError; } IRCError IRCBase::disconnectFromServer(const std::string& quitMessage) { - if (!mp->isConnected) - return IRCError::NotConnected; + if (!mp->isConnected) + return IRCError::NotConnected; - if (mp->isOnline) { - mp->write(Command::IRC::QUIT, quitMessage); - // TODO Quit timeout; if we never get disconnected by server, we forcefully must do so. - } - else { - if (mp->useSSL) - mp->sslsock->lowest_layer().close(); - else - mp->sock->close(); - } + if (mp->isOnline) { + mp->write(Command::IRC::QUIT, quitMessage); + // TODO Quit timeout; if we never get disconnected by server, we forcefully must do so. + } + else { + if (mp->useSSL) + mp->sslsock->lowest_layer().close(); + else + mp->sock->close(); + } - if (mp->keepaliveFreq > std::chrono::seconds(0)) - mp->stopKeepaliveTimer(); + if (mp->keepaliveFreq > std::chrono::seconds(0)) + mp->stopKeepaliveTimer(); - return IRCError::NoError; + return IRCError::NoError; } IRCError IRCBase::lastErrorCode() const { - return mp->lastError; + return mp->lastError; } bool IRCBase::isOnline() const { - return mp->isOnline; + return mp->isOnline; } bool IRCBase::isConnected() const { - return mp->isConnected; + return mp->isConnected; } bool IRCBase::isSSL() const { - return mp->useSSL; + return mp->useSSL; } const std::vector& IRCBase::clientV3Support() { - return V3Support; + return V3Support; } const std::vector& IRCBase::registeredV3Support() const { - return mp->registeredV3support; + return mp->registeredV3support; } const std::vector& IRCBase::serverV3Support() const { - return mp->serverV3support; + return mp->serverV3support; } const std::unordered_map& IRCBase::isupport() const { - return mp->isupport; + return mp->isupport; } const std::vector>& IRCBase::channels() const { - return mp->channels; + return mp->channels; } std::shared_ptr IRCBase::getChannel(const std::string& name) const { - for (auto chanp : mp->channels) - if (strEquals(chanp->name(), name)) - return chanp; - return nullptr; + for (auto chanp : mp->channels) + if (strEquals(chanp->name(), name)) + return chanp; + return nullptr; } std::shared_ptr IRCBase::getMember(const std::string& nickname) const { - for (auto memp : mp->allMembers) - if (strEquals(memp->prefix().toString(), nickname)) - return memp; - return nullptr; + for (auto memp : mp->allMembers) + if (strEquals(memp->prefix().toString(), nickname)) + return memp; + return nullptr; } std::pair, IRCError> IRCBase::initiateDCC(const std::string& /*port*/) { - return std::pair, IRCError>(); + return std::pair, IRCError>(); } IRCError IRCBase::declineDCC(std::shared_ptr /*dcc*/) { - return IRCError::NetworkUnreachable; + return IRCError::NetworkUnreachable; } diff --git a/IRCClient/IRCBase.h b/IRCClient/IRCBase.h index 24abf70..43ed0e3 100644 --- a/IRCClient/IRCBase.h +++ b/IRCClient/IRCBase.h @@ -25,61 +25,61 @@ class DCC; struct IRCBasePriv; class IRCBase { - friend struct IRCBasePriv; + friend struct IRCBasePriv; public: - IRCBase(); - ~IRCBase(); + IRCBase(); + ~IRCBase(); - IRCBase(IRCBase&& other) noexcept; - IRCBase(const IRCBase&) = delete; - IRCBase& operator=(const IRCBase&) = delete; + IRCBase(IRCBase&& other) noexcept; + IRCBase(const IRCBase&) = delete; + IRCBase& operator=(const IRCBase&) = delete; - bool poll(); + bool poll(); - [[nodiscard]] const std::string& getHostname() const; - IRCError setHostname(const std::string& hostname, bool SSL = false); + [[nodiscard]] const std::string& getHostname() const; + IRCError setHostname(const std::string& hostname, bool SSL = false); - [[nodiscard]] const std::string& getPort() const; - IRCError setPort(const std::string& port); + [[nodiscard]] const std::string& getPort() const; + IRCError setPort(const std::string& port); - [[nodiscard]] const std::string& getRealname() const; - IRCError setRealname(const std::string& realname); + [[nodiscard]] const std::string& getRealname() const; + IRCError setRealname(const std::string& realname); - [[nodiscard]] const std::string& getIdent() const; - IRCError setIdent(const std::string& ident); + [[nodiscard]] const std::string& getIdent() const; + IRCError setIdent(const std::string& ident); - [[nodiscard]] const std::string& getNickname() const; - void setNickname(const std::string& nickname); + [[nodiscard]] const std::string& getNickname() const; + void setNickname(const std::string& nickname); - [[nodiscard]] const std::string& getPassword() const; - void setPassword(const std::string& password); + [[nodiscard]] const std::string& getPassword() const; + void setPassword(const std::string& password); - void exceptSSL_SelfSigned(bool except); - void exceptSSL_CNMismatch(bool except); - void exceptSSL_Expired(bool except); + void exceptSSL_SelfSigned(bool except); + void exceptSSL_CNMismatch(bool except); + void exceptSSL_Expired(bool except); - void command(const std::string& command, const std::vector& args, const std::string& msg = ""); - void command(const std::string& command, const std::string& msg); - void raw(const std::string& data); + void command(const std::string& command, const std::vector& args, const std::string& msg = ""); + void command(const std::string& command, const std::string& msg); + void raw(const std::string& data); - void ctcpRequest(const std::string& target, const std::string& command, const std::string& message = ""); + void ctcpRequest(const std::string& target, const std::string& command, const std::string& message = ""); void ctcpResponse(const std::string& target, const std::string& command, const std::string& message = ""); - //! Set to >0 to enable, =0 to disable. - void setManualKeepalive(std::chrono::seconds freq = std::chrono::seconds(30)); + //! Set to >0 to enable, =0 to disable. + void setManualKeepalive(std::chrono::seconds freq = std::chrono::seconds(30)); - [[nodiscard]] std::chrono::milliseconds getManualKeepaliveFreq() const; + [[nodiscard]] std::chrono::milliseconds getManualKeepaliveFreq() const; - [[nodiscard]] asio::io_context& getIOCTX(); + [[nodiscard]] asio::io_context& getIOCTX(); - /** - * Takes a string of modes (letters like ohv), in their intended order - * and converts each letter to its corresponding display prefix (ie. @%+). - * For mode (letters) that isn't valid, a colon ':' is placed in-stead (since - * those can't naturally exist with the IRC protocol.) - */ - [[nodiscard]] std::string toMemberPrefix(const std::string& modes) const; + /** + * Takes a string of modes (letters like ohv), in their intended order + * and converts each letter to its corresponding display prefix (ie. @%+). + * For mode (letters) that isn't valid, a colon ':' is placed in-stead (since + * those can't naturally exist with the IRC protocol.) + */ + [[nodiscard]] std::string toMemberPrefix(const std::string& modes) const; bool isChannelSymbol(char c); @@ -97,81 +97,81 @@ public: */ [[nodiscard]] char channelModeGroup(char m) const; - [[nodiscard]] IRCError tryConnect(); - [[nodiscard]] IRCError disconnectFromServer(const std::string& quitMessage = ""); - [[nodiscard]] IRCError lastErrorCode() const; + [[nodiscard]] IRCError tryConnect(); + [[nodiscard]] IRCError disconnectFromServer(const std::string& quitMessage = ""); + [[nodiscard]] IRCError lastErrorCode() const; - [[nodiscard]] bool isOnline() const; - [[nodiscard]] bool isConnected() const; - [[nodiscard]] bool isSSL() const; + [[nodiscard]] bool isOnline() const; + [[nodiscard]] bool isConnected() const; + [[nodiscard]] bool isSSL() const; - [[nodiscard]] static const std::vector& clientV3Support(); - [[nodiscard]] const std::vector& registeredV3Support() const; - [[nodiscard]] const std::vector& serverV3Support() const; - [[nodiscard]] const std::unordered_map& isupport() const; + [[nodiscard]] static const std::vector& clientV3Support(); + [[nodiscard]] const std::vector& registeredV3Support() const; + [[nodiscard]] const std::vector& serverV3Support() const; + [[nodiscard]] const std::unordered_map& isupport() const; - [[nodiscard]] const std::vector>& channels() const; - [[nodiscard]] std::shared_ptr getChannel(const std::string& name) const; - [[nodiscard]] std::shared_ptr getMember(const std::string& nickname) const; + [[nodiscard]] const std::vector>& channels() const; + [[nodiscard]] std::shared_ptr getChannel(const std::string& name) const; + [[nodiscard]] std::shared_ptr getMember(const std::string& nickname) const; - std::pair, IRCError> initiateDCC(const std::string& port); // Creates a DCC initiator (tcp server) - IRCError declineDCC(std::shared_ptr dcc); + std::pair, IRCError> initiateDCC(const std::string& port); // Creates a DCC initiator (tcp server) + IRCError declineDCC(std::shared_ptr dcc); protected: - virtual void onConnected() {} - virtual void onConnectedWithSSLExceptions(const std::vector& codes) {} - virtual void onDisconnected() {} - virtual void onRegistered() {} - virtual void onConnectionError(IRCError e) {} - - /* - * To correctly implement and get all data from a standard IRC server, - * the following virtuals must be implemented. - */ - virtual void onMsgNick(const IRCPrefix& sender, const std::string& newNickname, const std::vector& channelsAffected) = 0; - virtual void onMsgMode(const IRCPrefix& sender, const std::string& target, const std::string& modes, const std::vector& args) = 0; - virtual void onMsgQuit(const IRCPrefix& sender, const std::string& message, const std::vector& channelsAffected) = 0; - virtual void onMsgJoin(const IRCPrefix& sender, const std::string& target) = 0; - virtual void onMsgPart(const IRCPrefix& sender, const std::string& target, const std::string& message) = 0; - virtual void onMsgTopic(const IRCPrefix& sender, const std::string& target, const std::string& topic) = 0; - virtual void onMsgInvite(const IRCPrefix& sender, const std::string& target) = 0; - virtual void onMsgKick(const IRCPrefix& sender, const std::string& target, const std::string& who, const std::string& reason) = 0; - virtual void onMsgPrivmsg(const IRCPrefix& sender, const std::string& target, const std::string& message) = 0; - virtual void onMsgNotice(const IRCPrefix& sender, const std::string& target, const std::string& message) = 0; - virtual void onMsgKill(const IRCPrefix& sender, const std::string& reason) = 0; - virtual void onMsgPing(const std::string& message) = 0; - virtual void onMsgPong(const std::string& message) = 0; - virtual void onMsgError(const std::string& message) = 0; - virtual void onMsgWallops(const IRCPrefix& sender, const std::string& message) = 0; - virtual void onMsgNumeric(const IRCPrefix& sender, const std::string& num, const std::vector& args, const std::string& message) = 0; - - /* - * CTCP/DCC isn't really a part of the IRC standard so these are optional. - */ - virtual void onMsgCTCPRequest(const IRCPrefix& sender, const std::string& target, const std::string& command, const std::string& message) {}; - virtual void onMsgCTCPResponse(const IRCPrefix& sender, const std::string& target, const std::string& command, const std::string& message) {}; - virtual void onMsgDCCRequest(std::shared_ptr dcc, const IRCPrefix& sender, const std::string& target, const std::string& type, const std::string& message) {}; - - /* - * Optional IRCv3 extensions to implement. - */ - virtual void v3onMsgAway(const IRCPrefix& sender, const std::string& message, const std::vector& channelsAffected) {}; - virtual void v3onMsgAccountLogin(const IRCPrefix& sender, const std::string& useraccount) {} - virtual void v3onMsgAccountLogout(const IRCPrefix& sender) {} - - /* - * Required IRCv3 extensions to implement. - */ - virtual void v3onMsgJoin(const IRCPrefix& sender, const std::string& channel, const std::string& useraccount, const std::string& realname) = 0; - - /* - * Catch-all handler. If the message parser cannot match for any of the commands, it will turn up here. - * Optional to implement. - */ - virtual void onMsgUnhandled(const IRCPrefix& sender, const std::string& command, const std::vector& args, const std::string& message) {} + virtual void onConnected() {} + virtual void onConnectedWithSSLExceptions(const std::vector& codes) {} + virtual void onDisconnected() {} + virtual void onRegistered() {} + virtual void onConnectionError(IRCError e) {} + + /* + * To correctly implement and get all data from a standard IRC server, + * the following virtuals must be implemented. + */ + virtual void onMsgNick(const IRCPrefix& sender, const std::string& newNickname, const std::vector& channelsAffected) = 0; + virtual void onMsgMode(const IRCPrefix& sender, const std::string& target, const std::string& modes, const std::vector& args) = 0; + virtual void onMsgQuit(const IRCPrefix& sender, const std::string& message, const std::vector& channelsAffected) = 0; + virtual void onMsgJoin(const IRCPrefix& sender, const std::string& target) = 0; + virtual void onMsgPart(const IRCPrefix& sender, const std::string& target, const std::string& message) = 0; + virtual void onMsgTopic(const IRCPrefix& sender, const std::string& target, const std::string& topic) = 0; + virtual void onMsgInvite(const IRCPrefix& sender, const std::string& target) = 0; + virtual void onMsgKick(const IRCPrefix& sender, const std::string& target, const std::string& who, const std::string& reason) = 0; + virtual void onMsgPrivmsg(const IRCPrefix& sender, const std::string& target, const std::string& message) = 0; + virtual void onMsgNotice(const IRCPrefix& sender, const std::string& target, const std::string& message) = 0; + virtual void onMsgKill(const IRCPrefix& sender, const std::string& reason) = 0; + virtual void onMsgPing(const std::string& message) = 0; + virtual void onMsgPong(const std::string& message) = 0; + virtual void onMsgError(const std::string& message) = 0; + virtual void onMsgWallops(const IRCPrefix& sender, const std::string& message) = 0; + virtual void onMsgNumeric(const IRCPrefix& sender, const std::string& num, const std::vector& args, const std::string& message) = 0; + + /* + * CTCP/DCC isn't really a part of the IRC standard so these are optional. + */ + virtual void onMsgCTCPRequest(const IRCPrefix& sender, const std::string& target, const std::string& command, const std::string& message) {}; + virtual void onMsgCTCPResponse(const IRCPrefix& sender, const std::string& target, const std::string& command, const std::string& message) {}; + virtual void onMsgDCCRequest(std::shared_ptr dcc, const IRCPrefix& sender, const std::string& target, const std::string& type, const std::string& message) {}; + + /* + * Optional IRCv3 extensions to implement. + */ + virtual void v3onMsgAway(const IRCPrefix& sender, const std::string& message, const std::vector& channelsAffected) {}; + virtual void v3onMsgAccountLogin(const IRCPrefix& sender, const std::string& useraccount) {} + virtual void v3onMsgAccountLogout(const IRCPrefix& sender) {} + + /* + * Required IRCv3 extensions to implement. + */ + virtual void v3onMsgJoin(const IRCPrefix& sender, const std::string& channel, const std::string& useraccount, const std::string& realname) = 0; + + /* + * Catch-all handler. If the message parser cannot match for any of the commands, it will turn up here. + * Optional to implement. + */ + virtual void onMsgUnhandled(const IRCPrefix& sender, const std::string& command, const std::vector& args, const std::string& message) {} private: - std::unique_ptr mp; + std::unique_ptr mp; }; #endif // IRCBASE_H diff --git a/IRCClient/IRCBasePriv.h b/IRCClient/IRCBasePriv.h index fec6353..48e2186 100644 --- a/IRCClient/IRCBasePriv.h +++ b/IRCClient/IRCBasePriv.h @@ -28,20 +28,20 @@ constexpr bool DumpReadData = true; constexpr bool DumpWriteData = true; const std::vector V3Support { - "account-notify", - "extended-join", - "away-notify", - "invite-notify", - "multi-prefix", - "userhost-in-names"/*, - "server-time", - "batch" -*/ - /* - * TODO https://ircv3.net/irc/ - * chghost - * sasl - */ + "account-notify", + "extended-join", + "away-notify", + "invite-notify", + "multi-prefix", + "userhost-in-names"/*, + "server-time", + "batch" + */ + /* + * TODO https://ircv3.net/irc/ + * chghost + * sasl + */ }; } // end anonymous namespace diff --git a/IRCClient/IRCChannel.cpp b/IRCClient/IRCChannel.cpp index 94409cf..b201837 100644 --- a/IRCClient/IRCChannel.cpp +++ b/IRCClient/IRCChannel.cpp @@ -11,24 +11,24 @@ #include IRCChannel::IRCChannel(const std::string& name, IRCBase& owner) - : m_name(name) - , m_owner(&owner) + : m_name(name) + , m_owner(&owner) {} const std::string& IRCChannel::name() const { - return m_name; + return m_name; } std::optional IRCChannel::getMember(const std::string& nickname) { - auto it = std::find_if(m_members.begin(), m_members.end(), - [&nickname](const IRCMemberEntry& entry){ - return entry.member()->prefix().nickname() == nickname; - }); + auto it = std::find_if(m_members.begin(), m_members.end(), + [&nickname](const IRCMemberEntry& entry){ + return entry.member()->prefix().nickname() == nickname; + }); - return it == m_members.end() ? std::nullopt - : std::make_optional(*it); + return it == m_members.end() ? std::nullopt + : std::make_optional(*it); } IRCMemberEntry& IRCChannel::addMember(std::shared_ptr member) @@ -48,55 +48,55 @@ IRCMemberEntry& IRCChannel::addMember(std::shared_ptr member) void IRCChannel::delMember(std::shared_ptr member) { - auto newEnd = std::remove_if(m_members.begin(), m_members.end(), + auto newEnd = std::remove_if(m_members.begin(), m_members.end(), [&member](const IRCMemberEntry& e){ - return member->prefix() == e.member()->prefix(); + return member->prefix() == e.member()->prefix(); }); - m_members.erase(newEnd, m_members.end()); + m_members.erase(newEnd, m_members.end()); } const std::vector& IRCChannel::members() const { - return m_members; + return m_members; } void IRCChannel::setTopic(const std::string& topic) { - m_topic = topic; + m_topic = topic; } const std::string& IRCChannel::topic() const { - return m_topic; + return m_topic; } const std::unordered_map& IRCChannel::modes() const { - return m_modes; + return m_modes; } void IRCChannel::setMode(char m, const std::string& parameter) { - /* - * Note that if a mode requiring an argument is already set, - * the server will always send an 'unset' before setting a new value. - * But let's use insert_or_assign anyway. - */ - m_modes.insert_or_assign(m, parameter); + /* + * Note that if a mode requiring an argument is already set, + * the server will always send an 'unset' before setting a new value. + * But let's use insert_or_assign anyway. + */ + m_modes.insert_or_assign(m, parameter); } void IRCChannel::delMode(char m) { - m_modes.erase(m); + m_modes.erase(m); } bool IRCChannel::isPopulating() const { - return m_populating; + return m_populating; } void IRCChannel::donePopulating() { - m_populating = false; + m_populating = false; } diff --git a/IRCClient/IRCChannel.h b/IRCClient/IRCChannel.h index 8c56d6f..02cdfa7 100644 --- a/IRCClient/IRCChannel.h +++ b/IRCClient/IRCChannel.h @@ -23,33 +23,33 @@ using IRCMemberEntryRef = std::reference_wrapper; class IRCChannel { public: - IRCChannel(const std::string& name, IRCBase& owner); - ~IRCChannel() = default; + IRCChannel(const std::string& name, IRCBase& owner); + ~IRCChannel() = default; - const std::string& name() const; + const std::string& name() const; - std::optional getMember(const std::string& nickname); - IRCMemberEntry& addMember(std::shared_ptr member); - void delMember(std::shared_ptr member); - const std::vector& members() const; + std::optional getMember(const std::string& nickname); + IRCMemberEntry& addMember(std::shared_ptr member); + void delMember(std::shared_ptr member); + const std::vector& members() const; - void setTopic(const std::string& topic); - const std::string& topic() const; + void setTopic(const std::string& topic); + const std::string& topic() const; - const std::unordered_map& modes() const; - void setMode(char m, const std::string& parameter = ""); - void delMode(char m); + const std::unordered_map& modes() const; + void setMode(char m, const std::string& parameter = ""); + void delMode(char m); - bool isPopulating() const; - void donePopulating(); + bool isPopulating() const; + void donePopulating(); private: - std::string m_name; - std::vector m_members; - std::string m_topic; - std::unordered_map m_modes; - bool m_populating{ true }; - IRCBase* m_owner; // TODO use reference? + std::string m_name; + std::vector m_members; + std::string m_topic; + std::unordered_map m_modes; + bool m_populating{ true }; + IRCBase* m_owner; // TODO use reference? }; diff --git a/IRCClient/IRCError.cpp b/IRCClient/IRCError.cpp index 5a9c384..6b4708c 100644 --- a/IRCClient/IRCError.cpp +++ b/IRCClient/IRCError.cpp @@ -15,114 +15,114 @@ std::string lastAsioErrorMessage; std::string IRCErrorToString(IRCError e) { - switch (e) { - case IRCError::NoError: - return "No error"; - case IRCError::NotConnected: - return "Not connected"; - case IRCError::AlreadyConnected: - return "Already connected"; - case IRCError::CannotResolveAddress: - return "Cannot resolve address"; - case IRCError::BrokenPipe: - return "Broken pipe"; - case IRCError::ConnectionAborted: - return "Connection aborted"; - case IRCError::ConnectionRefused: - return "Connection refused"; - case IRCError::ConnectionReset: - return "Connection reset"; - case IRCError::HostUnreachable: - return "Host unreachable"; - case IRCError::NetworkDown: - return "Network down"; - case IRCError::NetworkReset: - return "Network reset"; - case IRCError::NetworkUnreachable: - return "Network unreachable"; - case IRCError::NoDescriptors: - return "No file descriptors left"; - case IRCError::TimedOut: - return "Timed out"; - case IRCError::EndOfFile: - return "EOF"; - case IRCError::SSL_SelfSigned: - return "SSL: Self-signed certificate"; - case IRCError::SSL_CN_Mismatch: - return "SSL: (CN) Hostname mismatch"; - case IRCError::SSL_CN_Missing: - return "SSL: (CN) Hostname missing"; - case IRCError::SSL_CN_WildcardIllegal: - return "SSL: (CN) Illegal wildcard usage"; - case IRCError::SSL_NotYetValid: - return "SSL: Certificate not yet valid"; - case IRCError::SSL_Expired: - return "SSL: Certificate expired"; - case IRCError::CannotChangeWhenConnected: - return "Cannot change this setting when connected"; - case IRCError::HostNotSet: - return "Hostname is not set"; - case IRCError::PortNotSet: - return "Port number is not set"; - case IRCError::IdentNotSet: - return "Ident/username is not set"; - case IRCError::NicknameNotSet: - return "Nickname is not set"; - case IRCError::RealnameNotSet: - return "Real name is not set"; - case IRCError::DCC_NotATarget: - return "DCC: We are not a DCC target"; - case IRCError::DCC_TimedOut: - return "DCC: Request timed out"; + switch (e) { + case IRCError::NoError: + return "No error"; + case IRCError::NotConnected: + return "Not connected"; + case IRCError::AlreadyConnected: + return "Already connected"; + case IRCError::CannotResolveAddress: + return "Cannot resolve address"; + case IRCError::BrokenPipe: + return "Broken pipe"; + case IRCError::ConnectionAborted: + return "Connection aborted"; + case IRCError::ConnectionRefused: + return "Connection refused"; + case IRCError::ConnectionReset: + return "Connection reset"; + case IRCError::HostUnreachable: + return "Host unreachable"; + case IRCError::NetworkDown: + return "Network down"; + case IRCError::NetworkReset: + return "Network reset"; + case IRCError::NetworkUnreachable: + return "Network unreachable"; + case IRCError::NoDescriptors: + return "No file descriptors left"; + case IRCError::TimedOut: + return "Timed out"; + case IRCError::EndOfFile: + return "EOF"; + case IRCError::SSL_SelfSigned: + return "SSL: Self-signed certificate"; + case IRCError::SSL_CN_Mismatch: + return "SSL: (CN) Hostname mismatch"; + case IRCError::SSL_CN_Missing: + return "SSL: (CN) Hostname missing"; + case IRCError::SSL_CN_WildcardIllegal: + return "SSL: (CN) Illegal wildcard usage"; + case IRCError::SSL_NotYetValid: + return "SSL: Certificate not yet valid"; + case IRCError::SSL_Expired: + return "SSL: Certificate expired"; + case IRCError::CannotChangeWhenConnected: + return "Cannot change this setting when connected"; + case IRCError::HostNotSet: + return "Hostname is not set"; + case IRCError::PortNotSet: + return "Port number is not set"; + case IRCError::IdentNotSet: + return "Ident/username is not set"; + case IRCError::NicknameNotSet: + return "Nickname is not set"; + case IRCError::RealnameNotSet: + return "Real name is not set"; + case IRCError::DCC_NotATarget: + return "DCC: We are not a DCC target"; + case IRCError::DCC_TimedOut: + return "DCC: Request timed out"; case IRCError::UnhandledException: return "Unhandled exception"; - } + } - /* - * Compiler complains even if all cases are covered... - * I don't wanna use a 'default' so that my IDE and tools can pick up on missing enumerations. - * A return here would suffice. - */ - return fmt::format("Uncaught error code {}", e); + /* + * Compiler complains even if all cases are covered... + * I don't wanna use a 'default' so that my IDE and tools can pick up on missing enumerations. + * A return here would suffice. + */ + return fmt::format("Uncaught error code {}", e); } IRCError SystemErrorToIRCError(const std::system_error& e) { - switch (e.code().value()) { - case 0: - return IRCError::NoError; - case asio::error::host_not_found: - return IRCError::CannotResolveAddress; - case asio::error::broken_pipe: - return IRCError::BrokenPipe; - case asio::error::connection_aborted: - return IRCError::ConnectionAborted; - case asio::error::connection_refused: - return IRCError::ConnectionRefused; - case asio::error::connection_reset: - return IRCError::ConnectionReset; - case asio::error::host_unreachable: - return IRCError::HostUnreachable; - case asio::error::network_down: - return IRCError::NetworkDown; - case asio::error::network_reset: - return IRCError::NetworkReset; - case asio::error::network_unreachable: - return IRCError::NetworkUnreachable; - case asio::error::no_descriptors: - return IRCError::NoDescriptors; - case asio::error::timed_out: - return IRCError::TimedOut; - case asio::error::eof: - return IRCError::EndOfFile; + switch (e.code().value()) { + case 0: + return IRCError::NoError; + case asio::error::host_not_found: + return IRCError::CannotResolveAddress; + case asio::error::broken_pipe: + return IRCError::BrokenPipe; + case asio::error::connection_aborted: + return IRCError::ConnectionAborted; + case asio::error::connection_refused: + return IRCError::ConnectionRefused; + case asio::error::connection_reset: + return IRCError::ConnectionReset; + case asio::error::host_unreachable: + return IRCError::HostUnreachable; + case asio::error::network_down: + return IRCError::NetworkDown; + case asio::error::network_reset: + return IRCError::NetworkReset; + case asio::error::network_unreachable: + return IRCError::NetworkUnreachable; + case asio::error::no_descriptors: + return IRCError::NoDescriptors; + case asio::error::timed_out: + return IRCError::TimedOut; + case asio::error::eof: + return IRCError::EndOfFile; /* * A 'default' here is needed since asio::error has a few errors I don't care about, or is able to care for... */ - default: - lastAsioErrorCode = e.code().value(); - lastAsioErrorMessage = e.code().message(); - std::cerr << fmt::format("Unhandled exception {}: {}", lastAsioErrorCode, lastAsioErrorMessage) << std::endl; - return IRCError::UnhandledException; - } + default: + lastAsioErrorCode = e.code().value(); + lastAsioErrorMessage = e.code().message(); + std::cerr << fmt::format("Unhandled exception {}: {}", lastAsioErrorCode, lastAsioErrorMessage) << std::endl; + return IRCError::UnhandledException; + } } diff --git a/IRCClient/IRCError.h b/IRCClient/IRCError.h index 9427ed5..bff9054 100644 --- a/IRCClient/IRCError.h +++ b/IRCClient/IRCError.h @@ -16,42 +16,42 @@ extern std::string lastAsioErrorMessage; enum class IRCError { - NoError, - - NotConnected, - AlreadyConnected, - - CannotResolveAddress, - BrokenPipe, - ConnectionAborted, - ConnectionRefused, - ConnectionReset, - HostUnreachable, - NetworkDown, - NetworkReset, - NetworkUnreachable, - NoDescriptors, - TimedOut, - EndOfFile, - - SSL_SelfSigned, - SSL_CN_Mismatch, - SSL_CN_Missing, - SSL_CN_WildcardIllegal, - SSL_NotYetValid, - SSL_Expired, - - CannotChangeWhenConnected, - HostNotSet, - PortNotSet, - IdentNotSet, - NicknameNotSet, - RealnameNotSet, - - DCC_NotATarget, - DCC_TimedOut, - - UnhandledException + NoError, + + NotConnected, + AlreadyConnected, + + CannotResolveAddress, + BrokenPipe, + ConnectionAborted, + ConnectionRefused, + ConnectionReset, + HostUnreachable, + NetworkDown, + NetworkReset, + NetworkUnreachable, + NoDescriptors, + TimedOut, + EndOfFile, + + SSL_SelfSigned, + SSL_CN_Mismatch, + SSL_CN_Missing, + SSL_CN_WildcardIllegal, + SSL_NotYetValid, + SSL_Expired, + + CannotChangeWhenConnected, + HostNotSet, + PortNotSet, + IdentNotSet, + NicknameNotSet, + RealnameNotSet, + + DCC_NotATarget, + DCC_TimedOut, + + UnhandledException }; std::string IRCErrorToString(IRCError e); diff --git a/IRCClient/IRCMember.cpp b/IRCClient/IRCMember.cpp index 0b13fe3..5b9819d 100644 --- a/IRCClient/IRCMember.cpp +++ b/IRCClient/IRCMember.cpp @@ -10,51 +10,51 @@ #include IRCMember::IRCMember(const IRCPrefix& prefix) - : m_prefix(prefix) + : m_prefix(prefix) {} IRCMember::IRCMember(const std::string& nickname) - : m_prefix(IRCPrefix::fromNickname(nickname)) + : m_prefix(IRCPrefix::fromNickname(nickname)) {} const IRCPrefix& IRCMember::prefix() const { - return m_prefix; + return m_prefix; } void IRCMember::setPrefix(const IRCPrefix& prefix) { - m_prefix = prefix; + m_prefix = prefix; } const std::vector>& IRCMember::channels() { - return m_channels; + return m_channels; } void IRCMember::addChannel(std::weak_ptr channel) { - auto it = std::find_if(m_channels.begin(), m_channels.end(), + auto it = std::find_if(m_channels.begin(), m_channels.end(), [channel](const std::weak_ptr& p){ return p.lock()->name() == channel.lock()->name(); - }); + }); - if (it == m_channels.end()) - m_channels.emplace_back(channel); + if (it == m_channels.end()) + m_channels.emplace_back(channel); } void IRCMember::delChannel(std::weak_ptr channel) { - auto it = std::find_if(m_channels.begin(), m_channels.end(), + auto it = std::find_if(m_channels.begin(), m_channels.end(), [channel](const std::weak_ptr& p){ return p.lock()->name() == channel.lock()->name(); }); if (it != m_channels.end()) - m_channels.erase(it); + m_channels.erase(it); } void IRCMember::setNickname(const std::string& nickname) { - m_prefix.setNickname(nickname); + m_prefix.setNickname(nickname); } diff --git a/IRCClient/IRCMember.h b/IRCClient/IRCMember.h index ee63e3d..ed97e58 100644 --- a/IRCClient/IRCMember.h +++ b/IRCClient/IRCMember.h @@ -18,20 +18,20 @@ class IRCChannel; class IRCMember { public: - explicit IRCMember(const IRCPrefix& prefix); - explicit IRCMember(const std::string& nickname); + explicit IRCMember(const IRCPrefix& prefix); + explicit IRCMember(const std::string& nickname); - const IRCPrefix& prefix() const; - void setPrefix(const IRCPrefix& prefix); - const std::vector>& channels(); - void addChannel(std::weak_ptr channel); - void delChannel(std::weak_ptr channel); + const IRCPrefix& prefix() const; + void setPrefix(const IRCPrefix& prefix); + const std::vector>& channels(); + void addChannel(std::weak_ptr channel); + void delChannel(std::weak_ptr channel); - void setNickname(const std::string& nickname); + void setNickname(const std::string& nickname); private: - IRCPrefix m_prefix; - std::vector> m_channels; + IRCPrefix m_prefix; + std::vector> m_channels; }; #endif // IRCMEMBER_H diff --git a/IRCClient/IRCMemberEntry.cpp b/IRCClient/IRCMemberEntry.cpp index c72bfb5..f711b8b 100644 --- a/IRCClient/IRCMemberEntry.cpp +++ b/IRCClient/IRCMemberEntry.cpp @@ -10,54 +10,54 @@ #include IRCMemberEntry::IRCMemberEntry(std::shared_ptr member, IRCBase& owner) - : m_member(member) - , m_owner(&owner) + : m_member(member) + , m_owner(&owner) {} std::shared_ptr IRCMemberEntry::member() const { - return m_member; + return m_member; } const std::string& IRCMemberEntry::modes() const { - return m_modes; + return m_modes; } void IRCMemberEntry::addMode(char m) { - // Note: "PREFIX" is always present. - // Value example: (ohv)@%+ - // Value is ordered with most significant first. - const std::string& prefix = m_owner->isupport().find("PREFIX")->second; + // Note: "PREFIX" is always present. + // Value example: (ohv)@%+ + // Value is ordered with most significant first. + const std::string& prefix = m_owner->isupport().find("PREFIX")->second; - // Just interested in the mode letters (ie. ohv) - const std::string validModes(prefix.begin() + 1, std::find(prefix.begin(), prefix.end(), ')')); - auto order = [validModes](const char m) -> int { - auto ret = validModes.find(m); - return ret != std::string::npos ? static_cast(ret) - : -1; - }; + // Just interested in the mode letters (ie. ohv) + const std::string validModes(prefix.begin() + 1, std::find(prefix.begin(), prefix.end(), ')')); + auto order = [validModes](const char m) -> int { + auto ret = validModes.find(m); + return ret != std::string::npos ? static_cast(ret) + : -1; + }; - auto mOrd = order(m); - if (mOrd < 0) - return; + auto mOrd = order(m); + if (mOrd < 0) + return; - auto it = m_modes.begin(); - for (auto& mode : m_modes) { - if (mode == m) - return; - else if (order(mode) >= mOrd) - break; - else - ++it; - } - m_modes.insert(it, m); + auto it = m_modes.begin(); + for (auto& mode : m_modes) { + if (mode == m) + return; + else if (order(mode) >= mOrd) + break; + else + ++it; + } + m_modes.insert(it, m); } void IRCMemberEntry::delMode(char m) { - auto pos = m_modes.find_first_of(m); + auto pos = m_modes.find_first_of(m); /* * Out-of-bounds can happen due to an IRC protocol bug. For example, where you join a channel which has @@ -66,6 +66,6 @@ void IRCMemberEntry::delMode(char m) * IRCv3 implements a fix for this which this client support, but not all servers do. * When a member then removes the unknown mode, we get this situation below; */ - if (pos != std::string::npos) + if (pos != std::string::npos) m_modes.erase(pos, 1); } diff --git a/IRCClient/IRCMemberEntry.h b/IRCClient/IRCMemberEntry.h index 1582b36..6da3e88 100644 --- a/IRCClient/IRCMemberEntry.h +++ b/IRCClient/IRCMemberEntry.h @@ -17,19 +17,19 @@ class IRCBase; class IRCMemberEntry { public: - IRCMemberEntry(std::shared_ptr member, IRCBase& owner); - ~IRCMemberEntry() = default; + IRCMemberEntry(std::shared_ptr member, IRCBase& owner); + ~IRCMemberEntry() = default; - [[nodiscard]] std::shared_ptr member() const; + [[nodiscard]] std::shared_ptr member() const; - [[nodiscard]] const std::string& modes() const; - void addMode(char m); - void delMode(char m); + [[nodiscard]] const std::string& modes() const; + void addMode(char m); + void delMode(char m); private: - std::shared_ptr m_member; - std::string m_modes; - IRCBase* m_owner; // can't be reference since we store IRCMemberEntry in a vector, requiring assignment operator. + std::shared_ptr m_member; + std::string m_modes; + IRCBase* m_owner; // can't be reference since we store IRCMemberEntry in a vector, requiring assignment operator. }; #endif // IRCMEMBERENTRY_H diff --git a/IRCClient/IRCPrefix.cpp b/IRCClient/IRCPrefix.cpp index 59b775f..6da243c 100644 --- a/IRCClient/IRCPrefix.cpp +++ b/IRCClient/IRCPrefix.cpp @@ -11,107 +11,107 @@ IRCPrefix::IRCPrefix(const std::string& prefix) { - auto atIt = std::find(prefix.begin(), prefix.end(), '@'); - if (atIt != prefix.end()) { - // nickname!user@host - m_type = Type::user; - auto exclmIt = std::find(prefix.begin(), prefix.end(), '!'); - m_nickname = std::string(prefix.begin(), exclmIt); - m_user = std::string(exclmIt + 1, atIt); - m_host = std::string(atIt + 1, prefix.end()); - } - else { - m_type = Type::server; - m_servername = prefix; - } + auto atIt = std::find(prefix.begin(), prefix.end(), '@'); + if (atIt != prefix.end()) { + // nickname!user@host + m_type = Type::user; + auto exclmIt = std::find(prefix.begin(), prefix.end(), '!'); + m_nickname = std::string(prefix.begin(), exclmIt); + m_user = std::string(exclmIt + 1, atIt); + m_host = std::string(atIt + 1, prefix.end()); + } + else { + m_type = Type::server; + m_servername = prefix; + } } IRCPrefix::IRCPrefix(const IRCPrefix& other) - : m_servername(other.m_servername) - , m_nickname(other.m_nickname) - , m_user(other.m_user) - , m_host(other.m_host) - , m_type(other.m_type) + : m_servername(other.m_servername) + , m_nickname(other.m_nickname) + , m_user(other.m_user) + , m_host(other.m_host) + , m_type(other.m_type) {} IRCPrefix::IRCPrefix(IRCPrefix&& other) noexcept - : m_servername(std::move(other.m_servername)) - , m_nickname(std::move(other.m_nickname)) - , m_user(std::move(other.m_user)) - , m_host(std::move(other.m_host)) - , m_type(std::move(other.m_type)) + : m_servername(std::move(other.m_servername)) + , m_nickname(std::move(other.m_nickname)) + , m_user(std::move(other.m_user)) + , m_host(std::move(other.m_host)) + , m_type(std::move(other.m_type)) {} IRCPrefix::IRCPrefix(IRCPrefix::Type t) - : m_type(t) + : m_type(t) {} IRCPrefix& IRCPrefix::operator=(const IRCPrefix& other) { - m_servername = other.m_servername; - m_nickname = other.m_nickname; - m_user = other.m_user; - m_host = other.m_host; - m_type = other.m_type; - return *this; + m_servername = other.m_servername; + m_nickname = other.m_nickname; + m_user = other.m_user; + m_host = other.m_host; + m_type = other.m_type; + return *this; } const std::string& IRCPrefix::toString() const { - if (m_type == Type::server) - return m_servername; - else - return m_nickname; + if (m_type == Type::server) + return m_servername; + else + return m_nickname; } const std::string& IRCPrefix::servername() const { - return m_servername; + return m_servername; } const std::string& IRCPrefix::nickname() const { - return m_nickname; + return m_nickname; } const std::string& IRCPrefix::user() const { - return m_user; + return m_user; } const std::string& IRCPrefix::host() const { - return m_host; + return m_host; } void IRCPrefix::setNickname(const std::string& nickname) { - m_nickname = nickname; + m_nickname = nickname; } void IRCPrefix::setHost(const std::string& host) { - m_host = host; + m_host = host; } std::string IRCPrefix::composite() const { - if (m_type == Type::server) - return m_servername; - else - return fmt::format("{}!{}@{}", m_nickname, m_user, m_host); + if (m_type == Type::server) + return m_servername; + else + return fmt::format("{}!{}@{}", m_nickname, m_user, m_host); } IRCPrefix::Type IRCPrefix::type() const { - return m_type; + return m_type; } IRCPrefix IRCPrefix::fromNickname(const std::string& nickname) { - IRCPrefix p(Type::user); - p.m_nickname = nickname; - return p; + IRCPrefix p(Type::user); + p.m_nickname = nickname; + return p; } bool IRCPrefix::operator!=(const IRCPrefix& other) diff --git a/IRCClient/IRCPrefix.h b/IRCClient/IRCPrefix.h index de3cda1..64b02a4 100644 --- a/IRCClient/IRCPrefix.h +++ b/IRCClient/IRCPrefix.h @@ -13,51 +13,51 @@ class IRCPrefix { public: - explicit IRCPrefix(const std::string& prefix); - IRCPrefix(const IRCPrefix& other); - IRCPrefix(IRCPrefix&& other) noexcept; - IRCPrefix() = delete; - ~IRCPrefix() = default; + explicit IRCPrefix(const std::string& prefix); + IRCPrefix(const IRCPrefix& other); + IRCPrefix(IRCPrefix&& other) noexcept; + IRCPrefix() = delete; + ~IRCPrefix() = default; - IRCPrefix& operator=(const IRCPrefix& other); + IRCPrefix& operator=(const IRCPrefix& other); bool operator!=(const IRCPrefix& other); bool operator==(const IRCPrefix& other); - [[nodiscard]] const std::string& toString() const; //!< Returns either a servername or nickname. + [[nodiscard]] const std::string& toString() const; //!< Returns either a servername or nickname. - [[nodiscard]] const std::string& servername() const; - [[nodiscard]] const std::string& nickname() const; - [[nodiscard]] const std::string& user() const; - [[nodiscard]] const std::string& host() const; + [[nodiscard]] const std::string& servername() const; + [[nodiscard]] const std::string& nickname() const; + [[nodiscard]] const std::string& user() const; + [[nodiscard]] const std::string& host() const; - void setNickname(const std::string& nickname); - void setHost(const std::string& host); + void setNickname(const std::string& nickname); + void setHost(const std::string& host); - [[nodiscard]] std::string composite() const; + [[nodiscard]] std::string composite() const; - enum class Type - { - server, - user - }; + enum class Type + { + server, + user + }; - [[nodiscard]] Type type() const; + [[nodiscard]] Type type() const; - [[nodiscard]] static IRCPrefix fromNickname(const std::string& nickname); + [[nodiscard]] static IRCPrefix fromNickname(const std::string& nickname); private: - explicit IRCPrefix(Type t); + explicit IRCPrefix(Type t); - // Used for :irc.server.name prefix - std::string m_servername; + // Used for :irc.server.name prefix + std::string m_servername; - /* Used for :nickname!user@host prefix */ - std::string m_nickname; - std::string m_user; - std::string m_host; + /* Used for :nickname!user@host prefix */ + std::string m_nickname; + std::string m_user; + std::string m_host; - Type m_type; + Type m_type; }; bool operator!=(const IRCPrefix& lhs, const IRCPrefix& rhs); diff --git a/IRCClient/Utilities.cpp b/IRCClient/Utilities.cpp index 4c5ffde..babd9bf 100644 --- a/IRCClient/Utilities.cpp +++ b/IRCClient/Utilities.cpp @@ -12,21 +12,21 @@ std::pair FormatCTCPLine(std::string line) { - /* Clean away the CTCP byte flags */ - if (line[0] == CTCPflag) - line.erase(line.begin()); + /* Clean away the CTCP byte flags */ + if (line[0] == CTCPflag) + line.erase(line.begin()); - auto endIt = std::find(line.begin(), line.end(), CTCPflag); - if (endIt != line.end()) - line.pop_back(); + auto endIt = std::find(line.begin(), line.end(), CTCPflag); + if (endIt != line.end()) + line.pop_back(); - auto cmdIt = std::find(line.begin(), line.end(), ' '); - std::string cmd(line.begin(), cmdIt); - std::string ctcpMsg; - if (cmdIt != line.end()) - ctcpMsg = std::string(cmdIt + 1, line.end()); + auto cmdIt = std::find(line.begin(), line.end(), ' '); + std::string cmd(line.begin(), cmdIt); + std::string ctcpMsg; + if (cmdIt != line.end()) + ctcpMsg = std::string(cmdIt + 1, line.end()); - return std::make_pair(cmd, ctcpMsg); + return std::make_pair(cmd, ctcpMsg); } /*! @@ -35,80 +35,80 @@ std::pair FormatCTCPLine(std::string line) */ bool singleWildcardMatch(const std::string& str, const std::string& wc) { - if (str.empty() || wc.empty()) - return false; - - auto wcit = std::find(wc.begin(), wc.end(), '*'); - if (wcit == wc.end()) - return str == wc; - - /* - * Since we only support a single wildcard we only need to match the left side and right side - * of the asterisk (wildcard) against the target string 'str'. - * Also if the "end" of left match is equal to the "begin" of right match, it's a mismatch. - */ - - bool hasLeft, hasRight { false }; - auto leftEnd = str.end(); - auto rightBegin = str.end(); - - /* Left side */ - if (wcit != wc.begin()) { - std::string wildls(wc.begin(), wcit); - auto strmatch = str.substr(0, wildls.length()); - if (wildls != strmatch) - return false; - leftEnd = str.begin() + wildls.length(); - hasLeft = true; - } - - /* Right side */ - if (wcit != wc.end() - 1) { - std::string wildrs(wcit + 1, wc.end()); - auto mpos = str.find(wildrs); - if (mpos == std::string::npos) - return false; - auto strmatch = str.substr(mpos); - if (wildrs != strmatch) - return false; - rightBegin = str.begin() + mpos; - hasRight = true; - } - - // Avoid matching "left*right" with "leftright" - return !(hasLeft && hasRight && leftEnd == rightBegin); + if (str.empty() || wc.empty()) + return false; + + auto wcit = std::find(wc.begin(), wc.end(), '*'); + if (wcit == wc.end()) + return str == wc; + + /* + * Since we only support a single wildcard we only need to match the left side and right side + * of the asterisk (wildcard) against the target string 'str'. + * Also if the "end" of left match is equal to the "begin" of right match, it's a mismatch. + */ + + bool hasLeft, hasRight { false }; + auto leftEnd = str.end(); + auto rightBegin = str.end(); + + /* Left side */ + if (wcit != wc.begin()) { + std::string wildls(wc.begin(), wcit); + auto strmatch = str.substr(0, wildls.length()); + if (wildls != strmatch) + return false; + leftEnd = str.begin() + wildls.length(); + hasLeft = true; + } + + /* Right side */ + if (wcit != wc.end() - 1) { + std::string wildrs(wcit + 1, wc.end()); + auto mpos = str.find(wildrs); + if (mpos == std::string::npos) + return false; + auto strmatch = str.substr(mpos); + if (wildrs != strmatch) + return false; + rightBegin = str.begin() + mpos; + hasRight = true; + } + + // Avoid matching "left*right" with "leftright" + return !(hasLeft && hasRight && leftEnd == rightBegin); } std::string longIpToNormal(const std::string& longip) { - try { - unsigned ip = std::stoul(longip); - unsigned a = (ip & 0xFF000000u) >> 24u; - unsigned b = (ip & 0x00FF0000u) >> 16u; - unsigned c = (ip & 0x0000FF00u) >> 8u; - unsigned d = ip & 0x000000FFu; - return fmt::format("{}.{}.{}.{}", a, b, c, d); - } - catch (...) { - return "0.0.0.0"; - } + try { + unsigned ip = std::stoul(longip); + unsigned a = (ip & 0xFF000000u) >> 24u; + unsigned b = (ip & 0x00FF0000u) >> 16u; + unsigned c = (ip & 0x0000FF00u) >> 8u; + unsigned d = ip & 0x000000FFu; + return fmt::format("{}.{}.{}.{}", a, b, c, d); + } + catch (...) { + return "0.0.0.0"; + } } std::string normalIpToLong(const std::string& normalip) { - std::stringstream ss(normalip); - std::string p; - std::vector parts; - while (getline(ss, p, '.')) - parts.emplace_back(std::stoul(p)); - - uint32_t ret = parts[0]; - for (int i = 1; i < 4; ++i) { - ret <<= 8u; - ret |= parts[i]; - } - - return std::to_string(ret); + std::stringstream ss(normalip); + std::string p; + std::vector parts; + while (getline(ss, p, '.')) + parts.emplace_back(std::stoul(p)); + + uint32_t ret = parts[0]; + for (int i = 1; i < 4; ++i) { + ret <<= 8u; + ret |= parts[i]; + } + + return std::to_string(ret); } std::string concatenateModes(const std::unordered_map& modes) diff --git a/IWin/IWin.cpp b/IWin/IWin.cpp index f3480b0..6feb173 100644 --- a/IWin/IWin.cpp +++ b/IWin/IWin.cpp @@ -12,40 +12,40 @@ const QString IWin::InvalidWindowTypeString { "Invalid" }; std::unordered_map IWin::TypeString = { { IWin::Type::Undefined, "Undefined" }, - { IWin::Type::Status, "Status" }, - { IWin::Type::Channel, "Channel" }, - { IWin::Type::Private, "Private" }, - { IWin::Type::Custom, "Custom" } + { IWin::Type::Status, "Status" }, + { IWin::Type::Channel, "Channel" }, + { IWin::Type::Private, "Private" }, + { IWin::Type::Custom, "Custom" } }; IWin::Type IWin::getType() const { - return m_type; + return m_type; } IWin* IWin::getStatusParent() { - return (m_type == Type::Status) ? this : m_parent; + return (m_type == Type::Status) ? this : m_parent; } const QString& IWin::getButtonText() const { - return m_buttonText; + return m_buttonText; } void IWin::setButtonText(const QString& text) { - m_buttonText = text; + m_buttonText = text; } IWin::IWin(Type type, IWin* parentWindow) - : m_type(type) - , m_parent(parentWindow) + : m_type(type) + , m_parent(parentWindow) { } void IWin::closeEvent(QCloseEvent*) { - emit aboutToClose(this); + emit aboutToClose(this); } diff --git a/IWin/IWin.h b/IWin/IWin.h index 0df090d..1e4a511 100644 --- a/IWin/IWin.h +++ b/IWin/IWin.h @@ -16,44 +16,44 @@ class IWin : public QWidget { - Q_OBJECT + Q_OBJECT public: - enum class Type - { - Undefined, - Status, - Channel, - Private, - Custom - }; - static const QString InvalidWindowTypeString; - static std::unordered_map TypeString; - - Type getType() const; - IWin* getParent() const { return m_parent; } - IWin* getStatusParent(); - - virtual bool print(PrintType ptype, const QString& text) = 0; - virtual void refreshWindowTitle() = 0; - virtual void clear() = 0; - - const QString& getButtonText() const; - void setButtonText(const QString& text); - bool operator==(const IWin& other); // TODO implementation + enum class Type + { + Undefined, + Status, + Channel, + Private, + Custom + }; + static const QString InvalidWindowTypeString; + static std::unordered_map TypeString; + + Type getType() const; + IWin* getParent() const { return m_parent; } + IWin* getStatusParent(); + + virtual bool print(PrintType ptype, const QString& text) = 0; + virtual void refreshWindowTitle() = 0; + virtual void clear() = 0; + + const QString& getButtonText() const; + void setButtonText(const QString& text); + bool operator==(const IWin& other); // TODO implementation protected: - explicit IWin(Type type, IWin* parentWindow = nullptr); - void closeEvent(QCloseEvent*) override; + explicit IWin(Type type, IWin* parentWindow = nullptr); + void closeEvent(QCloseEvent*) override; private: - Type m_type; - QString m_buttonText; - IWin* m_parent{ nullptr }; - bool m_firstShow{ true }; + Type m_type; + QString m_buttonText; + IWin* m_parent{ nullptr }; + bool m_firstShow{ true }; signals: - void aboutToClose(IWin* who); + void aboutToClose(IWin* who); }; #endif // IWIN_H diff --git a/IWin/IWinChannel.cpp b/IWin/IWinChannel.cpp index c9fdb72..95abebf 100644 --- a/IWin/IWinChannel.cpp +++ b/IWin/IWinChannel.cpp @@ -18,162 +18,162 @@ #include IWinChannel::IWinChannel(IWinStatus* statusParent, const QString& channelName) - : IWin(IWin::Type::Channel, statusParent) - , status(statusParent) - , connection(statusParent->getConnection()) + : IWin(IWin::Type::Channel, statusParent) + , status(statusParent) + , connection(statusParent->getConnection()) { - setButtonText(channelName); + setButtonText(channelName); - splitter = new QSplitter(); - v_layout = new QVBoxLayout(); - view = new IIRCView(); - listbox = new IListWidget(); - input = new ILineEdit([this](int a, QString& b){ return tabComplete(a,b); }); + splitter = new QSplitter(); + v_layout = new QVBoxLayout(); + view = new IIRCView(); + listbox = new IListWidget(); + input = new ILineEdit([this](int a, QString& b){ return tabComplete(a,b); }); - v_layout->setMargin(0); - v_layout->setSpacing(2); + 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); + 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); + 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); + nlControl = new NicklistController(listbox, connection, channelName, this); + connect(&connection, &IRC::memberListReloaded, + this, &IWinChannel::memberListReloaded); connect(&connection, &IRC::memberListReset, this, &IWinChannel::memberListReset); - connect(&connection, &IRC::memberListClearedForAll, - this, &IWinChannel::memberListCleared); + connect(&connection, &IRC::memberListClearedForAll, + this, &IWinChannel::memberListCleared); - connect(&connection, &IRC::memberAdded, - this, &IWinChannel::memberListAdd); + connect(&connection, &IRC::memberAdded, + this, &IWinChannel::memberListAdd); - connect(&connection, &IRC::memberChanged, - this, &IWinChannel::memberListUpdateMember); + connect(&connection, &IRC::memberChanged, + this, &IWinChannel::memberListUpdateMember); - connect(&connection, &IRC::memberRemoved, - this, &IWinChannel::memberListRemoveMember); + connect(&connection, &IRC::memberRemoved, + this, &IWinChannel::memberListRemoveMember); - connect(input, &ILineEdit::newLine, - this, &IWinChannel::newLine); + connect(input, &ILineEdit::newLine, + this, &IWinChannel::newLine); - connect(listbox, &IListWidget::itemDoubleClicked, - this, &IWinChannel::listboxDoubleclick); + 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(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()); + 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; + 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)); + 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); - }); + 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); + view->print(ptype, text); MdiManager::instance().highlight(this, HL_Activity); - 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; + 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(); - std::string modes = concatenateModes(chan->modes()); + auto chan = connection.getChannel(getButtonText().toStdString()); + const auto& topic = chan->topic(); + std::string modes = concatenateModes(chan->modes()); - QString title = getButtonText(); - if (!modes.empty()) - title += QStringLiteral(" (+%1)").arg(QString::fromStdString(modes)); + QString title = getButtonText(); + if (!modes.empty()) + title += QStringLiteral(" (+%1)").arg(QString::fromStdString(modes)); - if (!topic.empty()) - title += QStringLiteral(": %1").arg(QString::fromStdString(topic)); + if (!topic.empty()) + title += QStringLiteral(": %1").arg(QString::fromStdString(topic)); - setWindowTitle(title); + setWindowTitle(title); } void IWinChannel::resetNicklist() { - nlControl->clear(); + nlControl->clear(); } void IWinChannel::newLine(const QString& line) { - InputHandler inHndl(connection); - inHndl.parse(*this, line); + InputHandler inHndl(connection); + inHndl.parse(*this, line); } void IWinChannel::listboxDoubleclick(QListWidgetItem* item) { - if (!item) - return; + if (!item) + return; - QString nickname = item->text(); - if (isUserModePrefix(nickname[0])) - nickname = nickname.mid(1); + QString nickname = item->text(); + if (isUserModePrefix(nickname[0])) + nickname = nickname.mid(1); - input->setFocus(); - IWin* subwin = status->createPrivateWindow(nickname); - subwin->refreshWindowTitle(); + 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(); + 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) @@ -181,7 +181,7 @@ void IWinChannel::closeEvent(QCloseEvent* evt) if (listbox->count() > 0) connection.command(Command::IRC::PART, { getButtonText().toStdString() }, ""); - IWin::closeEvent(evt); + IWin::closeEvent(evt); } int IWinChannel::tabComplete(int index, QString& pattern) @@ -224,8 +224,8 @@ Retry: void IWinChannel::memberListReloaded(const QString& channel) { - if (channel != getButtonText()) return; - nlControl->reload(); + if (channel != getButtonText()) return; + nlControl->reload(); } void IWinChannel::memberListReset(const QString& channel) @@ -236,22 +236,22 @@ void IWinChannel::memberListReset(const QString& channel) void IWinChannel::memberListCleared() { - nlControl->clear(); + nlControl->clear(); } void IWinChannel::memberListAdd(const QString& channel, const IRCMemberEntry& member) { - if (channel != getButtonText()) return; - nlControl->addMember(member); + if (channel != getButtonText()) return; + nlControl->addMember(member); } void IWinChannel::memberListUpdateMember(const QString& nickname, const IRCMemberEntry& member) { - nlControl->updateMember(nickname, member); + nlControl->updateMember(nickname, member); } void IWinChannel::memberListRemoveMember(const QString& channel, const IRCMemberEntry& member) { - if (channel != getButtonText()) return; - nlControl->removeMember(member); + if (channel != getButtonText()) return; + nlControl->removeMember(member); } diff --git a/IWin/IWinChannel.h b/IWin/IWinChannel.h index 5d8de45..6680fa3 100644 --- a/IWin/IWinChannel.h +++ b/IWin/IWinChannel.h @@ -24,44 +24,44 @@ class IWinStatus; class IWinChannel : public IWin { - Q_OBJECT + Q_OBJECT public: - IWinChannel(IWinStatus* statusParent, const QString& channelName); + IWinChannel(IWinStatus* statusParent, const QString& channelName); - bool print(const PrintType ptype, const QString& text) override; - void refreshWindowTitle() override; - void clear() override { view->resetView(); } - void resetNicklist(); + bool print(const PrintType ptype, const QString& text) override; + void refreshWindowTitle() override; + void clear() override { view->resetView(); } + void resetNicklist(); private: - void newLine(const QString& line); - void listboxDoubleclick(QListWidgetItem* item); - bool isUserModePrefix(QChar c); //! Returns true if the passed character is a prefix like @ + etc + void newLine(const QString& line); + void listboxDoubleclick(QListWidgetItem* item); + bool isUserModePrefix(QChar c); //! Returns true if the passed character is a prefix like @ + etc - void closeEvent(QCloseEvent* evt) override; - int tabComplete(int index, QString& pattern); + void closeEvent(QCloseEvent* evt) override; + int tabComplete(int index, QString& pattern); - QSplitter* splitter; - QVBoxLayout* v_layout; - IIRCView* view; - IListWidget* listbox; - ILineEdit* input; + QSplitter* splitter; + QVBoxLayout* v_layout; + IIRCView* view; + IListWidget* listbox; + ILineEdit* input; - NicklistController* nlControl; + NicklistController* nlControl; - IWinStatus* status; - IRC& connection; + IWinStatus* status; + IRC& connection; - SymbolScope menuSymbols; + SymbolScope menuSymbols; private slots: - void memberListReloaded(const QString& channel); + void memberListReloaded(const QString& channel); void memberListReset(const QString& channel); - void memberListCleared(); - void memberListAdd(const QString& channel, const IRCMemberEntry& member); - void memberListUpdateMember(const QString& nickname, const IRCMemberEntry& member); - void memberListRemoveMember(const QString& channel, const IRCMemberEntry& member); + void memberListCleared(); + void memberListAdd(const QString& channel, const IRCMemberEntry& member); + void memberListUpdateMember(const QString& nickname, const IRCMemberEntry& member); + void memberListRemoveMember(const QString& channel, const IRCMemberEntry& member); }; #endif // IWINCHANNEL_H diff --git a/IWin/IWinPrivate.cpp b/IWin/IWinPrivate.cpp index 8af97f8..f99fe24 100644 --- a/IWin/IWinPrivate.cpp +++ b/IWin/IWinPrivate.cpp @@ -13,73 +13,73 @@ #include IWinPrivate::IWinPrivate(IWinStatus* statusParent, const QString& targetName) - : IWin(IWin::Type::Private, statusParent) - , status(statusParent) - , connection(statusParent->getConnection()) + : IWin(IWin::Type::Private, statusParent) + , status(statusParent) + , connection(statusParent->getConnection()) { - setButtonText(targetName); + setButtonText(targetName); - layout = new QVBoxLayout(); - view = new IIRCView(); - input = new ILineEdit([this](int a, QString& b){ return tabComplete(a,b); }); + layout = new QVBoxLayout(); + view = new IIRCView(); + input = new ILineEdit([this](int a, QString& b){ return tabComplete(a,b); }); - layout->setMargin(0); - layout->setSpacing(2); - layout->addWidget(view); - layout->addWidget(input); - setLayout(layout); - setTabOrder(input, view); + layout->setMargin(0); + layout->setSpacing(2); + layout->addWidget(view); + layout->addWidget(input); + setLayout(layout); + setTabOrder(input, view); - view->setFocusPolicy(Qt::FocusPolicy::NoFocus); + view->setFocusPolicy(Qt::FocusPolicy::NoFocus); - connect(input, &ILineEdit::newLine, - this, &IWinPrivate::newLine); + connect(input, &ILineEdit::newLine, + this, &IWinPrivate::newLine); - connect(view, &IIRCView::customContextMenuRequested, [this](const QPoint& point){ - menuSymbols.set("nickname", getButtonText().toStdString()); - ScriptManager::instance()->contextMenuPopup(ScriptMenuType::Private, mapToGlobal(point), menuSymbols); - }); + connect(view, &IIRCView::customContextMenuRequested, [this](const QPoint& point){ + menuSymbols.set("nickname", getButtonText().toStdString()); + ScriptManager::instance()->contextMenuPopup(ScriptMenuType::Private, mapToGlobal(point), menuSymbols); + }); } bool IWinPrivate::print(const PrintType ptype, const QString& text) { - view->print(ptype, text); + view->print(ptype, text); MdiManager::instance().highlight(this, HL_Activity); - ConfigMgr& conf = ConfigMgr::instance(); - if (conf.logging("Privates") == "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; + ConfigMgr& conf = ConfigMgr::instance(); + if (conf.logging("Privates") == "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 IWinPrivate::refreshWindowTitle() { - QString target = getButtonText(); - auto ptr = connection.getMember(target.toStdString()); - if (!ptr) - setWindowTitle(target); - else { - const auto& prefix = ptr->prefix(); - if (prefix.host().empty()) - setWindowTitle(target); - else - setWindowTitle(QStringLiteral("%1 (%2@%3)") - .arg(target) - .arg(prefix.user().c_str()) - .arg(prefix.host().c_str())); - } + QString target = getButtonText(); + auto ptr = connection.getMember(target.toStdString()); + if (!ptr) + setWindowTitle(target); + else { + const auto& prefix = ptr->prefix(); + if (prefix.host().empty()) + setWindowTitle(target); + else + setWindowTitle(QStringLiteral("%1 (%2@%3)") + .arg(target) + .arg(prefix.user().c_str()) + .arg(prefix.host().c_str())); + } } void IWinPrivate::newLine(const QString& line) diff --git a/IWin/IWinPrivate.h b/IWin/IWinPrivate.h index 6669902..ca86031 100644 --- a/IWin/IWinPrivate.h +++ b/IWin/IWinPrivate.h @@ -19,26 +19,26 @@ class IRC; class IWinPrivate : public IWin { - Q_OBJECT + Q_OBJECT public: - IWinPrivate(IWinStatus* statusParent, const QString& targetName); - bool print(const PrintType ptype, const QString& text) override; - void refreshWindowTitle() override; + IWinPrivate(IWinStatus* statusParent, const QString& targetName); + bool print(const PrintType ptype, const QString& text) override; + void refreshWindowTitle() override; void clear() override { view->resetView(); } private: - void newLine(const QString& newLine); + void newLine(const QString& newLine); int tabComplete(int index, QString& pattern); - QVBoxLayout* layout; - IIRCView* view; - ILineEdit* input; + QVBoxLayout* layout; + IIRCView* view; + ILineEdit* input; - IWinStatus* status; - IRC& connection; + IWinStatus* status; + IRC& connection; - SymbolScope menuSymbols; + SymbolScope menuSymbols; }; #endif // IWINPRIVATE_H diff --git a/IWin/IWinStatus.cpp b/IWin/IWinStatus.cpp index f827955..3c0518a 100644 --- a/IWin/IWinStatus.cpp +++ b/IWin/IWinStatus.cpp @@ -16,202 +16,202 @@ int IWinStatus::StatusWindowCount = 0; IWinStatus::IWinStatus(const QString& buttonText) - : IWin(Type::Status) - , connection(*this) + : IWin(Type::Status) + , connection(*this) { - setButtonText(buttonText); - ++StatusWindowCount; + setButtonText(buttonText); + ++StatusWindowCount; - layout = new QVBoxLayout(); - view = new IIRCView(); - input = new ILineEdit([this](int a, QString& b){ return tabComplete(a,b); }); + layout = new QVBoxLayout(); + view = new IIRCView(); + input = new ILineEdit([this](int a, QString& b){ return tabComplete(a,b); }); - static int connectionIdCount{ 0 }; - connect(view, &IIRCView::customContextMenuRequested, [this](const QPoint& point){ - menuSymbols.set("cid", ++connectionIdCount); - ScriptManager::instance()->contextMenuPopup(ScriptMenuType::Status, mapToGlobal(point), menuSymbols); - }); + static int connectionIdCount{ 0 }; + connect(view, &IIRCView::customContextMenuRequested, [this](const QPoint& point){ + menuSymbols.set("cid", ++connectionIdCount); + ScriptManager::instance()->contextMenuPopup(ScriptMenuType::Status, mapToGlobal(point), menuSymbols); + }); - layout->setMargin(0); - layout->setSpacing(2); - layout->addWidget(view); - layout->addWidget(input); - setLayout(layout); - setTabOrder(input, view); + layout->setMargin(0); + layout->setSpacing(2); + layout->addWidget(view); + layout->addWidget(input); + setLayout(layout); + setTabOrder(input, view); - view->setFocusPolicy(Qt::FocusPolicy::NoFocus); + view->setFocusPolicy(Qt::FocusPolicy::NoFocus); - connect(input, &ILineEdit::newLine, - this, &IWinStatus::newLine); + connect(input, &ILineEdit::newLine, + this, &IWinStatus::newLine); - connect(&connection, &IRC::connected, [this] { - MdiManager::instance().connectionStateChange(); - refreshWindowTitle(); - }); + connect(&connection, &IRC::connected, [this] { + MdiManager::instance().connectionStateChange(); + refreshWindowTitle(); + }); - connect(&connection, &IRC::registered, [this] { - refreshWindowTitle(); - }); + connect(&connection, &IRC::registered, [this] { + refreshWindowTitle(); + }); - connect(&connection, &IRC::disconnected, [this] { - disconnectedFromServer(); - MdiManager::instance().connectionStateChange(); - refreshWindowTitle(); - }); + connect(&connection, &IRC::disconnected, [this] { + disconnectedFromServer(); + MdiManager::instance().connectionStateChange(); + refreshWindowTitle(); + }); - Qt_Eventloop_Hook(); + Qt_Eventloop_Hook(); } bool IWinStatus::print(const PrintType ptype, const QString& text) { - view->print(ptype, text); + view->print(ptype, text); MdiManager::instance().highlight(this, HL_Activity); - return true; + return true; } void IWinStatus::refreshWindowTitle() { - const auto& isupport = connection.isupport(); - const auto it = isupport.find("NETWORK"); + const auto& isupport = connection.isupport(); + const auto it = isupport.find("NETWORK"); QString title; - if (!connection.isOnline() && !connection.isConnected()) - title = tr("Status (Offline)"); - else if (!connection.isOnline() && connection.isConnected()) + if (!connection.isOnline() && !connection.isConnected()) + title = tr("Status (Offline)"); + else if (!connection.isOnline() && connection.isConnected()) title = tr("Status (Registering)"); - else if (it == isupport.end()) + else if (it == isupport.end()) title = QStringLiteral("%1 (%2)") .arg(QString::fromStdString( connection.getNickname() )) .arg(QString::fromStdString( connection.getHostname() )); - else - title = QStringLiteral("%1 (%2)") - .arg(QString::fromStdString( connection.getNickname() )) - .arg(QString::fromStdString( it->second )); + else + title = QStringLiteral("%1 (%2)") + .arg(QString::fromStdString( connection.getNickname() )) + .arg(QString::fromStdString( it->second )); - setWindowTitle(title); - MdiManager::instance().renameWindowButton(this, title); + setWindowTitle(title); + MdiManager::instance().renameWindowButton(this, title); } void IWinStatus::printTo(const QString& target, const PrintType ptype, const QString& text) { - MdiManager::instance().print(this, target, ptype, text); + MdiManager::instance().print(this, target, ptype, text); } void IWinStatus::printToTypes(const IWin::Type toType, const PrintType ptype, const QString& text) { - MdiManager::instance().printToTypes(this, toType, ptype, text); + MdiManager::instance().printToTypes(this, toType, ptype, text); } void IWinStatus::printToActive(const PrintType ptype, const QString& text) { - MdiManager::instance().printToActive(this, ptype, text); + MdiManager::instance().printToActive(this, ptype, text); } void IWinStatus::printToAll(const PrintType ptype, const QString& text) { - MdiManager::instance().printToAll(this, ptype, text); + MdiManager::instance().printToAll(this, ptype, text); } IWinChannel* IWinStatus::createChannelWindow(const QString& name) { - auto& mdiManager = MdiManager::instance(); - IWin* subwinBase = mdiManager.findWindow(this, name); - if (!subwinBase) - subwinBase = mdiManager.createSubwindow(this, name, IWin::Type::Channel); + auto& mdiManager = MdiManager::instance(); + IWin* subwinBase = mdiManager.findWindow(this, name); + if (!subwinBase) + subwinBase = mdiManager.createSubwindow(this, name, IWin::Type::Channel); - return dynamic_cast(subwinBase); + return dynamic_cast(subwinBase); } IWin* IWinStatus::createPrivateWindow(const QString& target, bool setFocus, Highlight buttonHighlight) { - auto& mdiManager = MdiManager::instance(); - IWin* subwinBase = mdiManager.findWindow(this, target); - if (!subwinBase) - subwinBase = mdiManager.createSubwindow(this, target, IWin::Type::Private, setFocus, buttonHighlight); + auto& mdiManager = MdiManager::instance(); + IWin* subwinBase = mdiManager.findWindow(this, target); + if (!subwinBase) + subwinBase = mdiManager.createSubwindow(this, target, IWin::Type::Private, setFocus, buttonHighlight); - return subwinBase; + return subwinBase; } IWin* IWinStatus::getActiveWindow() { - auto& mdiManager = MdiManager::instance(); - if (mdiManager.currentWindow()->getStatusParent() != this) - return this; - return mdiManager.currentWindow(); + auto& mdiManager = MdiManager::instance(); + if (mdiManager.currentWindow()->getStatusParent() != this) + return this; + return mdiManager.currentWindow(); } QList IWinStatus::subWindows() const { - return MdiManager::instance().childrenOf(this); + return MdiManager::instance().childrenOf(this); } void IWinStatus::closeEvent(QCloseEvent* evt) { - auto& mdiManager = MdiManager::instance(); + auto& mdiManager = MdiManager::instance(); const auto& conf = ConfigMgr::instance(); - if (StatusWindowCount == 1 || - (connection.isConnected() && QMessageBox::question(this, tr("Close status window"), tr("This status window has a connection. Close?")) - == QMessageBox::No)) { - evt->ignore(); - return; - } + if (StatusWindowCount == 1 || + (connection.isConnected() && QMessageBox::question(this, tr("Close status window"), tr("This status window has a connection. Close?")) + == QMessageBox::No)) { + evt->ignore(); + return; + } - if (connection.isConnected()) { - connect(&connection, &IRC::disconnected, [&] { closeAllChildren(); mdiManager.toMdiwin(this)->close(); }); + if (connection.isConnected()) { + connect(&connection, &IRC::disconnected, [&] { closeAllChildren(); mdiManager.toMdiwin(this)->close(); }); const auto quitMsg = conf.common("QuitMessage").toStdString(); const auto e = connection.disconnectFromServer(quitMsg); - if (e != IRCError::NoError) - qWarning() << "disconnectFromServer returned:" << QString::fromStdString(IRCErrorToString(e)); - evt->ignore(); - return; - } + if (e != IRCError::NoError) + qWarning() << "disconnectFromServer returned:" << QString::fromStdString(IRCErrorToString(e)); + evt->ignore(); + return; + } - --StatusWindowCount; + --StatusWindowCount; - IWin::closeEvent(evt); + IWin::closeEvent(evt); } void IWinStatus::newLine(const QString& line) { - InputHandler inHndl(connection); - inHndl.parse(*this, line); + InputHandler inHndl(connection); + inHndl.parse(*this, line); } void IWinStatus::closeAllChildren() { - auto& mdiManager = MdiManager::instance(); - QList subwinList = mdiManager.mdiChildrenOf(this); - for (QMdiSubWindow* subwin : subwinList) - subwin->close(); + auto& mdiManager = MdiManager::instance(); + QList subwinList = mdiManager.mdiChildrenOf(this); + for (QMdiSubWindow* subwin : subwinList) + subwin->close(); } void IWinStatus::Qt_Eventloop_Hook() { - const int nextInterval = connection.poll() ? 0 : 10; - QTimer::singleShot(nextInterval, this, std::bind(&IWinStatus::Qt_Eventloop_Hook, this)); + const int nextInterval = connection.poll() ? 0 : 10; + QTimer::singleShot(nextInterval, this, std::bind(&IWinStatus::Qt_Eventloop_Hook, this)); } void IWinStatus::disconnectedFromServer() { - const auto printDisconnected = [this](IWin* sw){ - sw->print(PrintType::ProgramInfo, tr("Disconnected")); - }; - - printDisconnected(this); - - auto subwins = subWindows(); - for (auto* sw : subwins) { - if (sw->getType() == IWin::Type::Channel) { - auto* chan = dynamic_cast(sw); - chan->resetNicklist(); - printDisconnected(chan); - } - else if (sw->getType() == IWin::Type::Private) { - printDisconnected(sw); - } - } + const auto printDisconnected = [this](IWin* sw){ + sw->print(PrintType::ProgramInfo, tr("Disconnected")); + }; + + printDisconnected(this); + + auto subwins = subWindows(); + for (auto* sw : subwins) { + if (sw->getType() == IWin::Type::Channel) { + auto* chan = dynamic_cast(sw); + chan->resetNicklist(); + printDisconnected(chan); + } + else if (sw->getType() == IWin::Type::Private) { + printDisconnected(sw); + } + } } int IWinStatus::tabComplete(int index, QString& pattern) diff --git a/IWin/IWinStatus.h b/IWin/IWinStatus.h index d749c97..e5932ae 100644 --- a/IWin/IWinStatus.h +++ b/IWin/IWinStatus.h @@ -23,42 +23,42 @@ class IWinChannel; class IWinStatus : public IWin { - Q_OBJECT + Q_OBJECT public: - explicit IWinStatus(const QString& buttonText); + explicit IWinStatus(const QString& buttonText); - bool print(const PrintType ptype, const QString& text) override; - void refreshWindowTitle() override; + bool print(const PrintType ptype, const QString& text) override; + void refreshWindowTitle() override; void clear() override { view->resetView(); } - void printTo(const QString& target, const PrintType ptype, const QString& text); - void printToTypes(const IWin::Type toType, const PrintType ptype, const QString& text); - void printToActive(const PrintType ptype, const QString& text); // TODO test - void printToAll(const PrintType ptype, const QString& text); - IWinChannel* createChannelWindow(const QString& name); - IWin* createPrivateWindow(const QString& target, bool setFocus = true, Highlight buttonHighlight = HL_None); - IWin* getActiveWindow(); - QList subWindows() const; - IRC& getConnection() { return connection; } + void printTo(const QString& target, const PrintType ptype, const QString& text); + void printToTypes(const IWin::Type toType, const PrintType ptype, const QString& text); + void printToActive(const PrintType ptype, const QString& text); // TODO test + void printToAll(const PrintType ptype, const QString& text); + IWinChannel* createChannelWindow(const QString& name); + IWin* createPrivateWindow(const QString& target, bool setFocus = true, Highlight buttonHighlight = HL_None); + IWin* getActiveWindow(); + QList subWindows() const; + IRC& getConnection() { return connection; } const IRC& getConnection() const { return connection; } - ILineEdit& getInputBox() { return *input; } + ILineEdit& getInputBox() { return *input; } private: - void closeEvent(QCloseEvent* evt) override; - void newLine(const QString& line); - void closeAllChildren(); - void Qt_Eventloop_Hook(); - void disconnectedFromServer(); + void closeEvent(QCloseEvent* evt) override; + void newLine(const QString& line); + void closeAllChildren(); + void Qt_Eventloop_Hook(); + void disconnectedFromServer(); int tabComplete(int index, QString& pattern); - static int StatusWindowCount; - QVBoxLayout* layout; - IIRCView* view; - ILineEdit* input; + static int StatusWindowCount; + QVBoxLayout* layout; + IIRCView* view; + ILineEdit* input; - IRC connection; + IRC connection; - SymbolScope menuSymbols; + SymbolScope menuSymbols; }; #endif // IWINSTATUS_H diff --git a/IWin/NicklistController.cpp b/IWin/NicklistController.cpp index b4065a2..e8507d6 100644 --- a/IWin/NicklistController.cpp +++ b/IWin/NicklistController.cpp @@ -14,189 +14,189 @@ #include NicklistController::NicklistController(QListWidget* listbox, IRC& server, const QString& channel, QObject* parent) - : QObject(parent) - , m_listbox(listbox) - , m_server(server) - , m_channel(channel) + : QObject(parent) + , m_listbox(listbox) + , m_server(server) + , m_channel(channel) { - ConfigMgr& conf = ConfigMgr::instance(); - connect(&conf, &ConfigMgr::saved, this, &NicklistController::newConfiguration); - - /* Precalculate m_prefixOrdered */ - const auto& isupport = m_server.isupport(); - const auto& prefix = isupport.at("PREFIX"); // PREFIX is always present - auto start = prefix.find_last_of(')'); - if (start != std::string::npos) { - ++start; - m_prefixOrdered = prefix.substr(start).c_str(); - } + ConfigMgr& conf = ConfigMgr::instance(); + connect(&conf, &ConfigMgr::saved, this, &NicklistController::newConfiguration); + + /* Precalculate m_prefixOrdered */ + const auto& isupport = m_server.isupport(); + const auto& prefix = isupport.at("PREFIX"); // PREFIX is always present + auto start = prefix.find_last_of(')'); + if (start != std::string::npos) { + ++start; + m_prefixOrdered = prefix.substr(start).c_str(); + } } void NicklistController::reload() { - m_listbox->clear(); - m_items.clear(); + m_listbox->clear(); + m_items.clear(); - auto chan = m_server.getChannel(m_channel.toStdString()); - if (!chan) - return; + auto chan = m_server.getChannel(m_channel.toStdString()); + if (!chan) + return; - const auto& members = chan->members(); + const auto& members = chan->members(); - for (const auto& mem : members) - m_items << makeItemText(mem); + for (const auto& mem : members) + m_items << makeItemText(mem); - std::sort(m_items.begin(), m_items.end(), - [this](const QString& left, const QString& right) { - return lessThan(left, right); - }); + std::sort(m_items.begin(), m_items.end(), + [this](const QString& left, const QString& right) { + return lessThan(left, right); + }); - m_listbox->addItems(m_items); - newConfiguration(); + m_listbox->addItems(m_items); + newConfiguration(); } void NicklistController::clear() { - m_listbox->clear(); + m_listbox->clear(); } bool NicklistController::lessThan(const QString& left, const QString& right) { - auto li = m_prefixOrdered.indexOf(left[0]); - auto ri = m_prefixOrdered.indexOf(right[0]); - - /* Both sides got a prefix */ - if (li != -1 && ri != -1) { - if (left[0] == right[0]) - return left.mid(1).compare(right.mid(1), Qt::CaseInsensitive) < 0; - else - return li < ri; - } - - /* Neither side got a prefix */ - else if (li == -1 && ri == -1) - return left.compare(right, Qt::CaseInsensitive) < 0; - - /* One side got a prefix */ - else - return ri == -1; + auto li = m_prefixOrdered.indexOf(left[0]); + auto ri = m_prefixOrdered.indexOf(right[0]); + + /* Both sides got a prefix */ + if (li != -1 && ri != -1) { + if (left[0] == right[0]) + return left.mid(1).compare(right.mid(1), Qt::CaseInsensitive) < 0; + else + return li < ri; + } + + /* Neither side got a prefix */ + else if (li == -1 && ri == -1) + return left.compare(right, Qt::CaseInsensitive) < 0; + + /* One side got a prefix */ + else + return ri == -1; } void NicklistController::addMember(const IRCMemberEntry& member) { - QString newItem = makeItemText(member); - int pos = findNewItemPosition(newItem); - m_items.insert(pos, newItem); - m_listbox->insertItem(pos, newItem); + QString newItem = makeItemText(member); + int pos = findNewItemPosition(newItem); + m_items.insert(pos, newItem); + m_listbox->insertItem(pos, newItem); - QListWidgetItem* item = m_listbox->item(pos); - updatePrefixColor(item, std::nullopt); + QListWidgetItem* item = m_listbox->item(pos); + updatePrefixColor(item, std::nullopt); } void NicklistController::updateMember(const QString& nickname, const IRCMemberEntry& member) { - // Find position of the item in the list. - // TODO use this loop also to find new item position. - int currPos = -1; - for (int i = 0; i < m_items.count(); ++i) { - QString item = m_items[i]; - if (m_prefixOrdered.indexOf(item[0]) > -1) - item = item.mid(1); - if (item == nickname) { - currPos = i; - break; - } - } - - // We don't have this nickname in this channel, and it is safe to ignore it silently. - // This is because when a nickname changes, that user might not be on all channels we're on. - if (currPos == -1) return; - - QListWidgetItem* lbitem = m_listbox->item(currPos); - bool isSelected = lbitem->isSelected(); - m_items.removeAt(currPos); - m_listbox->removeItemWidget(lbitem); - delete lbitem; - - QString newItemText = makeItemText(member); - int newPos = findNewItemPosition(newItemText); - - lbitem = new QListWidgetItem(newItemText); - m_listbox->insertItem(newPos, lbitem); - m_items.insert(newPos, newItemText); - lbitem->setSelected(isSelected); - updatePrefixColor(lbitem, std::nullopt); + // Find position of the item in the list. + // TODO use this loop also to find new item position. + int currPos = -1; + for (int i = 0; i < m_items.count(); ++i) { + QString item = m_items[i]; + if (m_prefixOrdered.indexOf(item[0]) > -1) + item = item.mid(1); + if (item == nickname) { + currPos = i; + break; + } + } + + // We don't have this nickname in this channel, and it is safe to ignore it silently. + // This is because when a nickname changes, that user might not be on all channels we're on. + if (currPos == -1) return; + + QListWidgetItem* lbitem = m_listbox->item(currPos); + bool isSelected = lbitem->isSelected(); + m_items.removeAt(currPos); + m_listbox->removeItemWidget(lbitem); + delete lbitem; + + QString newItemText = makeItemText(member); + int newPos = findNewItemPosition(newItemText); + + lbitem = new QListWidgetItem(newItemText); + m_listbox->insertItem(newPos, lbitem); + m_items.insert(newPos, newItemText); + lbitem->setSelected(isSelected); + updatePrefixColor(lbitem, std::nullopt); } void NicklistController::removeMember(const IRCMemberEntry& member) { - QString itemText = makeItemText(member); - int pos = 0; - int delpos = -1; - while (pos < m_items.count()) { - const QString& item = m_items[pos]; - if (item == itemText) { - delpos = pos; - break; - } - ++pos; - } - - if (delpos == -1) { - qWarning() << "Got request to delete" << itemText << "from" << m_channel << "but it was not found!"; - return; - } - - m_items.removeAt(delpos); - QListWidgetItem* lbitem = m_listbox->item(delpos); - m_listbox->removeItemWidget(lbitem); - delete lbitem; + QString itemText = makeItemText(member); + int pos = 0; + int delpos = -1; + while (pos < m_items.count()) { + const QString& item = m_items[pos]; + if (item == itemText) { + delpos = pos; + break; + } + ++pos; + } + + if (delpos == -1) { + qWarning() << "Got request to delete" << itemText << "from" << m_channel << "but it was not found!"; + return; + } + + m_items.removeAt(delpos); + QListWidgetItem* lbitem = m_listbox->item(delpos); + m_listbox->removeItemWidget(lbitem); + delete lbitem; } QString NicklistController::makeItemText(const IRCMemberEntry& member) { - QString item; - auto modes = member.modes(); - if (!modes.empty()) { - auto prefixes = m_server.toMemberPrefix(modes); - item += prefixes[0]; - } - item += member.member()->prefix().nickname().c_str(); - return item; + QString item; + auto modes = member.modes(); + if (!modes.empty()) { + auto prefixes = m_server.toMemberPrefix(modes); + item += prefixes[0]; + } + item += member.member()->prefix().nickname().c_str(); + return item; } int NicklistController::findNewItemPosition(const QString& text) { - int pos = 0; - while (pos < m_items.count()) { - const QString& item = m_items[pos]; - if (lessThan(text, item)) - break; + int pos = 0; + while (pos < m_items.count()) { + const QString& item = m_items[pos]; + if (lessThan(text, item)) + break; - ++pos; - } + ++pos; + } - return pos; + return pos; } void NicklistController::updatePrefixColor(QListWidgetItem* item, std::optional color) { - if (!color && m_prefixOrdered.indexOf(item->text()[0]) == -1) - return; - - ConfigMgr& conf = ConfigMgr::instance(); - if (!color) { - color = conf.prefixColor(item->text()[0]); - if (!color) return; - } - item->setForeground(*color); + if (!color && m_prefixOrdered.indexOf(item->text()[0]) == -1) + return; + + ConfigMgr& conf = ConfigMgr::instance(); + if (!color) { + color = conf.prefixColor(item->text()[0]); + if (!color) return; + } + item->setForeground(*color); } void NicklistController::newConfiguration() { - ConfigMgr& conf = ConfigMgr::instance(); - for (int i = 0; i < m_listbox->count(); ++i) { - updatePrefixColor(m_listbox->item(i) , QColor(conf.color("ListboxForeground"))); - updatePrefixColor(m_listbox->item(i) , std::nullopt); - } + ConfigMgr& conf = ConfigMgr::instance(); + for (int i = 0; i < m_listbox->count(); ++i) { + updatePrefixColor(m_listbox->item(i) , QColor(conf.color("ListboxForeground"))); + updatePrefixColor(m_listbox->item(i) , std::nullopt); + } } diff --git a/IWin/NicklistController.h b/IWin/NicklistController.h index 0090938..ce90d64 100644 --- a/IWin/NicklistController.h +++ b/IWin/NicklistController.h @@ -19,27 +19,27 @@ class IRCMemberEntry; class NicklistController : public QObject { - Q_OBJECT + Q_OBJECT public: - NicklistController(QListWidget* listbox, IRC& server, const QString& channel, QObject* parent = nullptr); - void reload(); - void clear(); - void addMember(const IRCMemberEntry& member); - void updateMember(const QString& nickname, const IRCMemberEntry& member); - void removeMember(const IRCMemberEntry& member); + NicklistController(QListWidget* listbox, IRC& server, const QString& channel, QObject* parent = nullptr); + void reload(); + void clear(); + void addMember(const IRCMemberEntry& member); + void updateMember(const QString& nickname, const IRCMemberEntry& member); + void removeMember(const IRCMemberEntry& member); private: - bool lessThan(const QString& left, const QString& right); - QString makeItemText(const IRCMemberEntry& member); - int findNewItemPosition(const QString& text); - void updatePrefixColor(QListWidgetItem* item, std::optional color); - void newConfiguration(); - QListWidget* m_listbox; - IRC& m_server; - const QString m_channel; - QStringList m_items; - QString m_prefixOrdered; //! Nickname prefix (@%+) in order + bool lessThan(const QString& left, const QString& right); + QString makeItemText(const IRCMemberEntry& member); + int findNewItemPosition(const QString& text); + void updatePrefixColor(QListWidgetItem* item, std::optional color); + void newConfiguration(); + QListWidget* m_listbox; + IRC& m_server; + const QString m_channel; + QStringList m_items; + QString m_prefixOrdered; //! Nickname prefix (@%+) in order }; #endif // NICKLISTCONTROLLER_H diff --git a/IdealIRC/AboutIIRC.cpp b/IdealIRC/AboutIIRC.cpp index ac79c59..aa71e1f 100644 --- a/IdealIRC/AboutIIRC.cpp +++ b/IdealIRC/AboutIIRC.cpp @@ -11,27 +11,27 @@ #include AboutIIRC::AboutIIRC(QWidget *parent) : - QDialog(parent), - ui(new Ui::AboutIIRC) + QDialog(parent), + ui(new Ui::AboutIIRC) { - ui->setupUi(this); + ui->setupUi(this); - QDateTime cur = QDateTime::currentDateTime(); - QString year = QString::number(cur.date().year()); + QDateTime cur = QDateTime::currentDateTime(); + QString year = QString::number(cur.date().year()); - QString text = ui->textBrowser->toHtml(); - text = text.replace("{year}", year); - text = text.replace("{ver}", VERSION_STRING); + QString text = ui->textBrowser->toHtml(); + text = text.replace("{year}", year); + text = text.replace("{ver}", VERSION_STRING); - if constexpr (BUILD_TYPE == BuildType::packaged) - text = text.replace("{buildtype}", QStringLiteral("Packaged")); - else if constexpr (BUILD_TYPE == BuildType::standalone) - text = text.replace("{buildtype}", QStringLiteral("Stand-alone")); + if constexpr (BUILD_TYPE == BuildType::packaged) + text = text.replace("{buildtype}", QStringLiteral("Packaged")); + else if constexpr (BUILD_TYPE == BuildType::standalone) + text = text.replace("{buildtype}", QStringLiteral("Stand-alone")); - ui->textBrowser->setHtml(text); + ui->textBrowser->setHtml(text); } AboutIIRC::~AboutIIRC() { - delete ui; + delete ui; } diff --git a/IdealIRC/AboutIIRC.h b/IdealIRC/AboutIIRC.h index 8420f70..674c955 100644 --- a/IdealIRC/AboutIIRC.h +++ b/IdealIRC/AboutIIRC.h @@ -16,14 +16,14 @@ class AboutIIRC; class AboutIIRC : public QDialog { - Q_OBJECT + Q_OBJECT public: - explicit AboutIIRC(QWidget *parent = nullptr); - ~AboutIIRC(); + explicit AboutIIRC(QWidget *parent = nullptr); + ~AboutIIRC(); private: - Ui::AboutIIRC *ui; + Ui::AboutIIRC *ui; }; #endif // ABOUTIIRC_H diff --git a/IdealIRC/ButtonbarMgr.cpp b/IdealIRC/ButtonbarMgr.cpp index fb0e4c1..cb5a702 100644 --- a/IdealIRC/ButtonbarMgr.cpp +++ b/IdealIRC/ButtonbarMgr.cpp @@ -11,31 +11,31 @@ int ButtonbarMgr::WindowTypeToGroupPos(const IWin* subwin) { - switch (subwin->getType()) { - case IWin::Type::Status: - return 1; - case IWin::Type::Channel: - return 2; - case IWin::Type::Private: - return 3; - default: - return 0; - } + switch (subwin->getType()) { + case IWin::Type::Status: + return 1; + case IWin::Type::Channel: + return 2; + case IWin::Type::Private: + return 3; + default: + return 0; + } } ButtonbarMgr::ButtonbarMgr(QToolBar *parent) - : QObject(parent) - , m_buttonBar(*parent) + : QObject(parent) + , m_buttonBar(*parent) { - m_buttonBar.setContextMenuPolicy(Qt::CustomContextMenu); - m_buttonBar.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - m_buttonBar.setIconSize(QSize(16, 16)); - m_buttonBar.setFloatable(false); + m_buttonBar.setContextMenuPolicy(Qt::CustomContextMenu); + m_buttonBar.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + m_buttonBar.setIconSize(QSize(16, 16)); + m_buttonBar.setFloatable(false); - connect(&m_buttonBar, &QToolBar::customContextMenuRequested, this, &ButtonbarMgr::buttonBarContextMenu); - m_others_rightSep = m_buttonBar.addSeparator(); + connect(&m_buttonBar, &QToolBar::customContextMenuRequested, this, &ButtonbarMgr::buttonBarContextMenu); + m_others_rightSep = m_buttonBar.addSeparator(); - connect(&m_buttonBar, &QToolBar::orientationChanged, [this](Qt::Orientation o){ + connect(&m_buttonBar, &QToolBar::orientationChanged, [this](Qt::Orientation o){ QHashIterator it(m_winbtn); while (it.hasNext()) { auto* action = it.next().value(); @@ -45,12 +45,12 @@ ButtonbarMgr::ButtonbarMgr(QToolBar *parent) else widget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); } - }); + }); } void ButtonbarMgr::addButton(IWin* subwin, QMdiSubWindow* mdiwin) { - auto* nn = findNextNeighbour(subwin); + auto* nn = findNextNeighbour(subwin); auto btn = Button(mdiwin); btn.toolButton->setMaximumWidth(150); @@ -66,84 +66,84 @@ void ButtonbarMgr::addButton(IWin* subwin, QMdiSubWindow* mdiwin) auto btnWidget = buttons(subwin).back().toolButton; connect(btnWidget, &QToolButton::clicked, [this,btnWidget,mdiwin](bool checked){ - if (!checked) { + if (!checked) { btnWidget->setChecked(true); - return; - } - emit changeWindow(mdiwin); - }); + return; + } + emit changeWindow(mdiwin); + }); } void ButtonbarMgr::delButton(IWin* subwin) { - auto clear = [this](Button& button){ - m_buttonBar.removeAction(button.action); - button.menu->deleteLater(); - button.action->deleteLater(); - button.toolButton->deleteLater(); - }; - - m_winbtn.remove(subwin); - if (subwin->getType() != IWin::Type::Status - && subwin->getType() != IWin::Type::Channel - && subwin->getType() != IWin::Type::Private) - { - int otherPos = buttonPosition(m_others, subwin); - if (otherPos > -1) { - clear(m_others[otherPos]); - m_others.removeAt(otherPos); - } - return; - } - - if (subwin->getType() == IWin::Type::Status) { - deleteGroup(subwin); - return; - } - - ButtonGroup* group = tryFindGroup(subwin); - if (!group) { - return; - } - - for (int i = 0; i < group->size; ++i) { - QList