mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Add feature to select channels to log (#4302)
* Add checkbox for custom logging and table with channels to log on Logs page * Add checkbox to enable and disable logging per channel * Return from addMessage before logging if custom logging enabled and channel does not have logging enabled * Use clang-format to fix formatting * Add CHANGELOG.md entry * Resolve PR comments * Remove toggle for channels so any channel listed will be logged * Move Only log channels listed below checkbox to just above table * Fix formatting * Re-order changelog * ChannelLog constructor: Copy & move instead of const ref & copy * ChannelLog::createEmpty: Curly brace initialize instead of repeating name * ChannelLog toString & createEmpty: nodiscard * Use COUNT paradigm in model column * Remove ChanneLoggingModel source file comments * Use Column::Channel in getRowFromItem * Rename `getItemFromRow` parameter and mark it as unused * Curly brace initialize ChannelLog * private & friend class the model * Filter out channels to log using a set instead of iterating over a vector every time a message comes in * Rename `ChannelLog::channel` member to `ChannelLog::channelName` Also made it private * mini comment on ChannelLog Co-authored-by: Felanbird <41973452+Felanbird@users.noreply.github.com> Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
parent
a567cc5ae7
commit
4c782ce90c
|
@ -8,6 +8,7 @@
|
||||||
- Minor: Tables in settings window will now scroll to newly added rows. (#4216)
|
- Minor: Tables in settings window will now scroll to newly added rows. (#4216)
|
||||||
- Minor: Added link to streamlink docs for easier user setup. (#4217)
|
- Minor: Added link to streamlink docs for easier user setup. (#4217)
|
||||||
- Minor: Added setting to turn off rendering of reply context. (#4224)
|
- Minor: Added setting to turn off rendering of reply context. (#4224)
|
||||||
|
- Minor: Added setting to select which channels to log. (#4302)
|
||||||
- Bugfix: Fixed crash that would occur when performing certain actions after removing all tabs. (#4271)
|
- Bugfix: Fixed crash that would occur when performing certain actions after removing all tabs. (#4271)
|
||||||
- Bugfix: Fixed highlight sounds not reloading on change properly. (#4194)
|
- Bugfix: Fixed highlight sounds not reloading on change properly. (#4194)
|
||||||
- Bugfix: Fixed CTRL + C not working in reply thread popups. (#4209)
|
- Bugfix: Fixed CTRL + C not working in reply thread popups. (#4209)
|
||||||
|
|
|
@ -119,6 +119,11 @@ set(SOURCE_FILES
|
||||||
controllers/moderationactions/ModerationActionModel.cpp
|
controllers/moderationactions/ModerationActionModel.cpp
|
||||||
controllers/moderationactions/ModerationActionModel.hpp
|
controllers/moderationactions/ModerationActionModel.hpp
|
||||||
|
|
||||||
|
controllers/logging/ChannelLog.cpp
|
||||||
|
controllers/logging/ChannelLog.hpp
|
||||||
|
controllers/logging/ChannelLoggingModel.cpp
|
||||||
|
controllers/logging/ChannelLoggingModel.hpp
|
||||||
|
|
||||||
controllers/nicknames/NicknamesModel.cpp
|
controllers/nicknames/NicknamesModel.cpp
|
||||||
controllers/nicknames/NicknamesModel.hpp
|
controllers/nicknames/NicknamesModel.hpp
|
||||||
controllers/nicknames/Nickname.hpp
|
controllers/nicknames/Nickname.hpp
|
||||||
|
|
25
src/controllers/logging/ChannelLog.cpp
Normal file
25
src/controllers/logging/ChannelLog.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "controllers/logging/ChannelLog.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
ChannelLog::ChannelLog(QString channelName)
|
||||||
|
: channelName_(std::move(channelName))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChannelLog::channelName() const
|
||||||
|
{
|
||||||
|
return this->channelName_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChannelLog::toString() const
|
||||||
|
{
|
||||||
|
return this->channelName_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelLog ChannelLog::createEmpty()
|
||||||
|
{
|
||||||
|
return {""};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
69
src/controllers/logging/ChannelLog.hpp
Normal file
69
src/controllers/logging/ChannelLog.hpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "util/RapidjsonHelpers.hpp"
|
||||||
|
|
||||||
|
#include <pajlada/serialize.hpp>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Contains the description of a channel that will be logged
|
||||||
|
**/
|
||||||
|
class ChannelLog
|
||||||
|
{
|
||||||
|
QString channelName_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ChannelLog(QString channelName);
|
||||||
|
|
||||||
|
bool operator==(const ChannelLog &other) const;
|
||||||
|
|
||||||
|
[[nodiscard]] QString channelName() const;
|
||||||
|
|
||||||
|
[[nodiscard]] QString toString() const;
|
||||||
|
|
||||||
|
[[nodiscard]] static ChannelLog createEmpty();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
|
|
||||||
|
namespace pajlada {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Serialize<chatterino::ChannelLog> {
|
||||||
|
static rapidjson::Value get(const chatterino::ChannelLog &value,
|
||||||
|
rapidjson::Document::AllocatorType &a)
|
||||||
|
{
|
||||||
|
rapidjson::Value ret(rapidjson::kObjectType);
|
||||||
|
|
||||||
|
chatterino::rj::set(ret, "channelName", value.channelName(), a);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Deserialize<chatterino::ChannelLog> {
|
||||||
|
static chatterino::ChannelLog get(const rapidjson::Value &value,
|
||||||
|
bool *error = nullptr)
|
||||||
|
{
|
||||||
|
if (!value.IsObject())
|
||||||
|
{
|
||||||
|
PAJLADA_REPORT_ERROR(error);
|
||||||
|
return chatterino::ChannelLog::createEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString channelName;
|
||||||
|
|
||||||
|
if (!chatterino::rj::getSafe(value, "channelName", channelName))
|
||||||
|
{
|
||||||
|
PAJLADA_REPORT_ERROR(error);
|
||||||
|
return chatterino::ChannelLog::createEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {channelName};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pajlada
|
25
src/controllers/logging/ChannelLoggingModel.cpp
Normal file
25
src/controllers/logging/ChannelLoggingModel.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "controllers/logging/ChannelLoggingModel.hpp"
|
||||||
|
|
||||||
|
#include "util/StandardItemHelper.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
ChannelLoggingModel ::ChannelLoggingModel(QObject *parent)
|
||||||
|
: SignalVectorModel<ChannelLog>(Column::COUNT, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelLog ChannelLoggingModel::getItemFromRow(
|
||||||
|
std::vector<QStandardItem *> &row, const ChannelLog & /*original*/)
|
||||||
|
{
|
||||||
|
auto channelName = row[Column::Channel]->data(Qt::DisplayRole).toString();
|
||||||
|
return {channelName};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChannelLoggingModel::getRowFromItem(const ChannelLog &item,
|
||||||
|
std::vector<QStandardItem *> &row)
|
||||||
|
{
|
||||||
|
setStringItem(row[Column::Channel], item.channelName());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
31
src/controllers/logging/ChannelLoggingModel.hpp
Normal file
31
src/controllers/logging/ChannelLoggingModel.hpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/SignalVectorModel.hpp"
|
||||||
|
#include "controllers/logging/ChannelLog.hpp"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
class ChannelLoggingModel : public SignalVectorModel<ChannelLog>
|
||||||
|
{
|
||||||
|
explicit ChannelLoggingModel(QObject *parent);
|
||||||
|
|
||||||
|
enum Column {
|
||||||
|
Channel,
|
||||||
|
COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// turn a vector item into a model row
|
||||||
|
ChannelLog getItemFromRow(std::vector<QStandardItem *> &row,
|
||||||
|
const ChannelLog &original) override;
|
||||||
|
|
||||||
|
// turns a row in the model into a vector item
|
||||||
|
void getRowFromItem(const ChannelLog &item,
|
||||||
|
std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
|
friend class ModerationPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
|
@ -1,6 +1,5 @@
|
||||||
#include "singletons/Logging.hpp"
|
#include "singletons/Logging.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
|
||||||
#include "singletons/helper/LoggingChannel.hpp"
|
#include "singletons/helper/LoggingChannel.hpp"
|
||||||
#include "singletons/Paths.hpp"
|
#include "singletons/Paths.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
@ -9,23 +8,42 @@
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
void Logging::initialize(Settings &settings, Paths &paths)
|
void Logging::initialize(Settings &settings, Paths & /*paths*/)
|
||||||
{
|
{
|
||||||
|
settings.loggedChannels.delayedItemsChanged.connect([this, &settings]() {
|
||||||
|
this->threadGuard.guard();
|
||||||
|
|
||||||
|
this->onlyLogListedChannels.clear();
|
||||||
|
|
||||||
|
for (const auto &loggedChannel : *settings.loggedChannels.readOnly())
|
||||||
|
{
|
||||||
|
this->onlyLogListedChannels.insert(loggedChannel.channelName());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logging::addMessage(const QString &channelName, MessagePtr message,
|
void Logging::addMessage(const QString &channelName, MessagePtr message,
|
||||||
const QString &platformName)
|
const QString &platformName)
|
||||||
{
|
{
|
||||||
|
this->threadGuard.guard();
|
||||||
|
|
||||||
if (!getSettings()->enableLogging)
|
if (!getSettings()->enableLogging)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getSettings()->onlyLogListedChannels)
|
||||||
|
{
|
||||||
|
if (!this->onlyLogListedChannels.contains(channelName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto platIt = this->loggingChannels_.find(platformName);
|
auto platIt = this->loggingChannels_.find(platformName);
|
||||||
if (platIt == this->loggingChannels_.end())
|
if (platIt == this->loggingChannels_.end())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/Singleton.hpp"
|
#include "common/Singleton.hpp"
|
||||||
|
#include "util/QStringHash.hpp"
|
||||||
|
#include "util/ThreadGuard.hpp"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
@ -32,6 +35,10 @@ private:
|
||||||
std::map<PlatformName,
|
std::map<PlatformName,
|
||||||
std::map<ChannelName, std::unique_ptr<LoggingChannel>>>
|
std::map<ChannelName, std::unique_ptr<LoggingChannel>>>
|
||||||
loggingChannels_;
|
loggingChannels_;
|
||||||
|
|
||||||
|
// Keeps the value of the `loggedChannels` settings
|
||||||
|
std::unordered_set<ChannelName> onlyLogListedChannels;
|
||||||
|
ThreadGuard threadGuard;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -25,6 +25,7 @@ ConcurrentSettings::ConcurrentSettings()
|
||||||
, filterRecords(*new SignalVector<FilterRecordPtr>())
|
, filterRecords(*new SignalVector<FilterRecordPtr>())
|
||||||
, nicknames(*new SignalVector<Nickname>())
|
, nicknames(*new SignalVector<Nickname>())
|
||||||
, moderationActions(*new SignalVector<ModerationAction>)
|
, moderationActions(*new SignalVector<ModerationAction>)
|
||||||
|
, loggedChannels(*new SignalVector<ChannelLog>)
|
||||||
{
|
{
|
||||||
persist(this->highlightedMessages, "/highlighting/highlights");
|
persist(this->highlightedMessages, "/highlighting/highlights");
|
||||||
persist(this->blacklistedUsers, "/highlighting/blacklist");
|
persist(this->blacklistedUsers, "/highlighting/blacklist");
|
||||||
|
@ -36,6 +37,7 @@ ConcurrentSettings::ConcurrentSettings()
|
||||||
persist(this->nicknames, "/nicknames");
|
persist(this->nicknames, "/nicknames");
|
||||||
// tagged users?
|
// tagged users?
|
||||||
persist(this->moderationActions, "/moderation/actions");
|
persist(this->moderationActions, "/moderation/actions");
|
||||||
|
persist(this->loggedChannels, "/logging/channels");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConcurrentSettings::isHighlightedUser(const QString &username)
|
bool ConcurrentSettings::isHighlightedUser(const QString &username)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "BaseSettings.hpp"
|
#include "BaseSettings.hpp"
|
||||||
#include "common/Channel.hpp"
|
#include "common/Channel.hpp"
|
||||||
#include "common/SignalVector.hpp"
|
#include "common/SignalVector.hpp"
|
||||||
|
#include "controllers/logging/ChannelLog.hpp"
|
||||||
#include "singletons/Toasts.hpp"
|
#include "singletons/Toasts.hpp"
|
||||||
#include "util/RapidJsonSerializeQString.hpp"
|
#include "util/RapidJsonSerializeQString.hpp"
|
||||||
#include "util/StreamerMode.hpp"
|
#include "util/StreamerMode.hpp"
|
||||||
|
@ -40,6 +41,7 @@ public:
|
||||||
SignalVector<FilterRecordPtr> &filterRecords;
|
SignalVector<FilterRecordPtr> &filterRecords;
|
||||||
SignalVector<Nickname> &nicknames;
|
SignalVector<Nickname> &nicknames;
|
||||||
SignalVector<ModerationAction> &moderationActions;
|
SignalVector<ModerationAction> &moderationActions;
|
||||||
|
SignalVector<ChannelLog> &loggedChannels;
|
||||||
|
|
||||||
bool isHighlightedUser(const QString &username);
|
bool isHighlightedUser(const QString &username);
|
||||||
bool isBlacklistedUser(const QString &username);
|
bool isBlacklistedUser(const QString &username);
|
||||||
|
@ -364,6 +366,8 @@ public:
|
||||||
|
|
||||||
/// Logging
|
/// Logging
|
||||||
BoolSetting enableLogging = {"/logging/enabled", false};
|
BoolSetting enableLogging = {"/logging/enabled", false};
|
||||||
|
BoolSetting onlyLogListedChannels = {"/logging/onlyLogListedChannels",
|
||||||
|
false};
|
||||||
|
|
||||||
QStringSetting logPath = {"/logging/path", ""};
|
QStringSetting logPath = {"/logging/path", ""};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "ModerationPage.hpp"
|
#include "ModerationPage.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
|
#include "controllers/logging/ChannelLoggingModel.hpp"
|
||||||
#include "controllers/moderationactions/ModerationAction.hpp"
|
#include "controllers/moderationactions/ModerationAction.hpp"
|
||||||
#include "controllers/moderationactions/ModerationActionModel.hpp"
|
#include "controllers/moderationactions/ModerationActionModel.hpp"
|
||||||
#include "singletons/Logging.hpp"
|
#include "singletons/Logging.hpp"
|
||||||
|
@ -69,8 +70,10 @@ ModerationPage::ModerationPage()
|
||||||
|
|
||||||
auto logs = tabs.appendTab(new QVBoxLayout, "Logs");
|
auto logs = tabs.appendTab(new QVBoxLayout, "Logs");
|
||||||
{
|
{
|
||||||
logs.append(this->createCheckBox("Enable logging",
|
QCheckBox *enableLogging = this->createCheckBox(
|
||||||
getSettings()->enableLogging));
|
"Enable logging", getSettings()->enableLogging);
|
||||||
|
logs.append(enableLogging);
|
||||||
|
|
||||||
auto logsPathLabel = logs.emplace<QLabel>();
|
auto logsPathLabel = logs.emplace<QLabel>();
|
||||||
|
|
||||||
// Logs (copied from LoggingMananger)
|
// Logs (copied from LoggingMananger)
|
||||||
|
@ -105,7 +108,6 @@ ModerationPage::ModerationPage()
|
||||||
});
|
});
|
||||||
|
|
||||||
buttons->addStretch();
|
buttons->addStretch();
|
||||||
logs->addStretch(1);
|
|
||||||
|
|
||||||
// Show how big (size-wise) the logs are
|
// Show how big (size-wise) the logs are
|
||||||
auto logsPathSizeLabel = logs.emplace<QLabel>();
|
auto logsPathSizeLabel = logs.emplace<QLabel>();
|
||||||
|
@ -140,6 +142,36 @@ ModerationPage::ModerationPage()
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QCheckBox *onlyLogListedChannels =
|
||||||
|
this->createCheckBox("Only log channels listed below",
|
||||||
|
getSettings()->onlyLogListedChannels);
|
||||||
|
|
||||||
|
onlyLogListedChannels->setEnabled(getSettings()->enableLogging);
|
||||||
|
logs.append(onlyLogListedChannels);
|
||||||
|
|
||||||
|
// Select event
|
||||||
|
QObject::connect(
|
||||||
|
enableLogging, &QCheckBox::stateChanged, this,
|
||||||
|
[enableLogging, onlyLogListedChannels]() mutable {
|
||||||
|
onlyLogListedChannels->setEnabled(enableLogging->isChecked());
|
||||||
|
});
|
||||||
|
|
||||||
|
EditableModelView *view =
|
||||||
|
logs.emplace<EditableModelView>(
|
||||||
|
(new ChannelLoggingModel(nullptr))
|
||||||
|
->initialized(&getSettings()->loggedChannels))
|
||||||
|
.getElement();
|
||||||
|
|
||||||
|
view->setTitles({"Twitch channels"});
|
||||||
|
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||||
|
QHeaderView::Fixed);
|
||||||
|
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||||
|
0, QHeaderView::Stretch);
|
||||||
|
|
||||||
|
view->addButtonPressed.connect([] {
|
||||||
|
getSettings()->loggedChannels.append(ChannelLog("channel"));
|
||||||
|
});
|
||||||
|
|
||||||
} // logs end
|
} // logs end
|
||||||
|
|
||||||
auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation buttons");
|
auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation buttons");
|
||||||
|
|
Loading…
Reference in a new issue