#17 Tabs to spaces

master
Tomatix 3 years ago
parent fac1766fc5
commit 93e4840ec4
  1. 12
      CMakeLists.txt
  2. 60
      ICommand/CommandData.cpp
  3. 16
      ICommand/CommandData.h
  4. 18
      ICommand/Commands.h
  5. 20
      ICommand/External/kick.cpp
  6. 28
      ICommand/External/notice.cpp
  7. 30
      ICommand/External/privmsg.cpp
  8. 1116
      ICommand/ICommand.cpp
  9. 44
      ICommand/ICommand.h
  10. 6
      ICommand/ICommandPriv.cpp
  11. 12
      ICommand/ICommandPriv.h
  12. 26
      ICommand/Internal/me.cpp
  13. 552
      IConfig/ColorConfig.cpp
  14. 74
      IConfig/ColorConfig.h
  15. 178
      IConfig/IConfig.cpp
  16. 52
      IConfig/IConfig.h
  17. 100
      IConfig/IConfigLogging.cpp
  18. 30
      IConfig/IConfigLogging.h
  19. 154
      IConfig/IConfigOptions.cpp
  20. 66
      IConfig/IConfigOptions.h
  21. 128
      IConfig/IConfigServers.cpp
  22. 42
      IConfig/IConfigServers.h
  23. 458
      IConfig/ServerEditor.cpp
  24. 60
      IConfig/ServerEditor.h
  25. 60
      IConfig/ServerMgr.cpp
  26. 6
      IConfig/ServerMgr.h
  27. 256
      IConfig/ServerModel.cpp
  28. 16
      IConfig/ServerModel.h
  29. 108
      IRCClient/Commands.h
  30. 260
      IRCClient/DCC.cpp
  31. 80
      IRCClient/DCC.h
  32. 376
      IRCClient/IRCBase.cpp
  33. 208
      IRCClient/IRCBase.h
  34. 28
      IRCClient/IRCBasePriv.h
  35. 50
      IRCClient/IRCChannel.cpp
  36. 40
      IRCClient/IRCChannel.h
  37. 198
      IRCClient/IRCError.cpp
  38. 72
      IRCClient/IRCError.h
  39. 24
      IRCClient/IRCMember.cpp
  40. 20
      IRCClient/IRCMember.h
  41. 60
      IRCClient/IRCMemberEntry.cpp
  42. 18
      IRCClient/IRCMemberEntry.h
  43. 96
      IRCClient/IRCPrefix.cpp
  44. 58
      IRCClient/IRCPrefix.h
  45. 156
      IRCClient/Utilities.cpp
  46. 22
      IWin/IWin.cpp
  47. 60
      IWin/IWin.h
  48. 224
      IWin/IWinChannel.cpp
  49. 50
      IWin/IWinChannel.h
  50. 102
      IWin/IWinPrivate.cpp
  51. 22
      IWin/IWinPrivate.h
  52. 216
      IWin/IWinStatus.cpp
  53. 50
      IWin/IWinStatus.h
  54. 272
      IWin/NicklistController.cpp
  55. 34
      IWin/NicklistController.h
  56. 28
      IdealIRC/AboutIIRC.cpp
  57. 8
      IdealIRC/AboutIIRC.h
  58. 394
      IdealIRC/ButtonbarMgr.cpp
  59. 100
      IdealIRC/ButtonbarMgr.h
  60. 6
      IdealIRC/CMakeLists.txt
  61. 18
      IdealIRC/ConfigMgr.cpp
  62. 48
      IdealIRC/ConfigMgr.h
  63. 396
      IdealIRC/IRC.cpp
  64. 106
      IdealIRC/IRC.h
  65. 254
      IdealIRC/IdealIRC.cpp
  66. 56
      IdealIRC/IdealIRC.h
  67. 8
      IdealIRC/IniFile.h
  68. 76
      IdealIRC/InputHandler.cpp
  69. 12
      IdealIRC/InputHandler.h
  70. 342
      IdealIRC/MdiManager.cpp
  71. 94
      IdealIRC/MdiManager.h
  72. 42
      IdealIRC/ScriptEvent.h
  73. 10
      IdealIRC/main.cpp
  74. 174
      Script/Builtin/Builtin.cpp
  75. 254
      Script/Builtin/DialogUtils.cpp
  76. 64
      Script/Builtin/Error.cpp
  77. 204
      Script/Builtin/GeneralUtils.cpp
  78. 258
      Script/Builtin/ListUtils.cpp
  79. 86
      Script/Builtin/MapUtils.cpp
  80. 694
      Script/Builtin/Mathematics.cpp
  81. 308
      Script/Builtin/StringUtils.cpp
  82. 194
      Script/Dialog.cpp
  83. 106
      Script/Dialog.h
  84. 368
      Script/Manager.cpp
  85. 116
      Script/Manager.h
  86. 124
      Script/ManagerListModel.cpp
  87. 24
      Script/ManagerListModel.h
  88. 114
      Script/Menu.cpp
  89. 70
      Script/Menu.h
  90. 30
      Script/ParserOperator.h
  91. 124
      Script/ParserToken.cpp
  92. 42
      Script/ParserToken.h
  93. 1308
      Script/Script.cpp
  94. 78
      Script/Script.h
  95. 110
      Script/SymbolScope.cpp
  96. 70
      Script/SymbolScope.h
  97. 1720
      Script/Tokenizer.cpp
  98. 50
      Script/Tokenizer.h
  99. 260
      Script/Tokens.cpp
  100. 384
      Script/Tokens.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -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()

@ -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<int>(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<int>(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<std::string>& 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;
}

@ -15,22 +15,22 @@
#include <optional>
using PredicateList = std::vector< std::function<
std::optional<std::string>
(int& idx, const QString& line)
>>;
std::optional<std::string>
(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<std::string>& operator[](int idx);
std::string joinString(char sep) const;
CommandData(const QString& line, PredicateList argp, bool repeatLastPredicate = false);
int size() const;
const std::optional<std::string>& operator[](int idx);
std::string joinString(char sep) const;
private:
std::vector<std::optional<std::string>> m_l;
std::vector<std::optional<std::string>> m_l;
};
#endif // COMMANDDATA_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";

@ -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);
}

@ -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()));
}
}

@ -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()));
}
}

File diff suppressed because it is too large Load Diff

@ -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<std::string> prd_AnyWord(int& idx, const QString& line);
static std::optional<std::string> prd_AnyWordToUpper(int& idx, const QString& line);
static std::optional<std::string> prd_OptionalChannel(int& idx, const QString& line);
static std::optional<std::string> prd_NotSwitch(int& idx, const QString& line);
static std::optional<std::string> prd_Switch(int& idx, const QString& line);
static std::optional<std::string> prd_Message(int& idx, const QString& line);
std::unique_ptr<ICommandPriv> 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<std::string> prd_AnyWord(int& idx, const QString& line);
static std::optional<std::string> prd_AnyWordToUpper(int& idx, const QString& line);
static std::optional<std::string> prd_OptionalChannel(int& idx, const QString& line);
static std::optional<std::string> prd_NotSwitch(int& idx, const QString& line);
static std::optional<std::string> prd_Switch(int& idx, const QString& line);
static std::optional<std::string> prd_Message(int& idx, const QString& line);
std::unique_ptr<ICommandPriv> mp;
};
#endif // ICOMMAND_H

@ -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_)
{}

@ -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);
};

@ -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()));
}

@ -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<QString,QRect> 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<QString,QRect> 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<QChar,QRect> 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<QString,QRect> 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<QString,QRect> 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<QChar,QRect> 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<QString,QString> it(textTypeMap);
QStringList sorted;
textTypeBB.clear();
QHashIterator<QString,QString> 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<QColor> 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();
}

@ -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<QColor> 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<QColor> 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<QString,QString> palette;
QWidget* addPrefixContainer;
QHBoxLayout* addPrefixLayout;
QToolButton* btnAddPrefix;
QLineEdit* edAddPrefix;
QHash<QString,QString> palette;
QHash<QString,QString> textTypeMap;
QHash<QString,QString> colorTypeMap;
QVector<std::pair<QChar,QColor>> prefixColor; // Use vector for displaying prefixes in insertion order.
QHash<QString,QString> textTypeMap;
QHash<QString,QString> colorTypeMap;
QVector<std::pair<QChar,QColor>> prefixColor; // Use vector for displaying prefixes in insertion order.
QHash<QString,QRect> textTypeBB;
QHash<QString,QRect> listboxItemBB;
QHash<QChar,QRect> prefixDeleteBB;
QRect textViewBB;
QRect inputBB;
QRect inputTextBB;
QRect listboxBB;
QHash<QString,QRect> textTypeBB;
QHash<QString,QRect> listboxItemBB;
QHash<QChar,QRect> 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

@ -11,75 +11,75 @@
#include <QMessageBox>
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;