added categories to the accountspage

This commit is contained in:
fourtf 2018-05-28 08:34:54 +02:00
parent 87f33501b2
commit 6156b1f430
22 changed files with 187 additions and 51 deletions

View file

@ -193,7 +193,6 @@ SOURCES += \
src/widgets/attachedwindow.cpp \ src/widgets/attachedwindow.cpp \
src/widgets/settingspages/externaltoolspage.cpp \ src/widgets/settingspages/externaltoolspage.cpp \
src/widgets/helper/comboboxitemdelegate.cpp \ src/widgets/helper/comboboxitemdelegate.cpp \
src/util/signalvectormodel.cpp \
src/controllers/commands/command.cpp \ src/controllers/commands/command.cpp \
src/controllers/commands/commandmodel.cpp \ src/controllers/commands/commandmodel.cpp \
src/controllers/commands/commandcontroller.cpp \ src/controllers/commands/commandcontroller.cpp \
@ -360,11 +359,12 @@ HEADERS += \
src/widgets/helper/dropoverlay.hpp \ src/widgets/helper/dropoverlay.hpp \
src/widgets/helper/splitnode.hpp \ src/widgets/helper/splitnode.hpp \
src/widgets/notificationpopup.hpp \ src/widgets/notificationpopup.hpp \
src/util/mutexvalue.h \
src/controllers/taggedusers/taggeduserscontroller.hpp \ src/controllers/taggedusers/taggeduserscontroller.hpp \
src/controllers/taggedusers/taggeduser.hpp \ src/controllers/taggedusers/taggeduser.hpp \
src/providerid.hpp \ src/providerid.hpp \
src/controllers/taggedusers/taggedusersmodel.hpp src/controllers/taggedusers/taggedusersmodel.hpp \
src/util/qstringhash.hpp \
src/util/mutexvalue.hpp
RESOURCES += \ RESOURCES += \
resources/resources.qrc resources/resources.qrc

View file

@ -6,9 +6,18 @@ namespace chatterino {
namespace controllers { namespace controllers {
namespace accounts { namespace accounts {
Account::Account(const QString &_category) Account::Account(ProviderId _providerId)
: category(_category) : providerId(_providerId)
{ {
static QString twitch("Twitch");
this->category = [&]() {
switch (_providerId) {
case ProviderId::Twitch:
return twitch;
}
return QString("Unknown ProviderId");
}();
} }
const QString &Account::getCategory() const const QString &Account::getCategory() const
@ -16,6 +25,11 @@ const QString &Account::getCategory() const
return this->category; return this->category;
} }
ProviderId Account::getProviderId() const
{
return this->providerId;
}
bool Account::operator<(const Account &other) const bool Account::operator<(const Account &other) const
{ {
QString a = this->toString(); QString a = this->toString();

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "providerid.hpp"
#include <QString> #include <QString>
namespace chatterino { namespace chatterino {
@ -9,14 +11,17 @@ namespace accounts {
class Account class Account
{ {
public: public:
Account(const QString &category); Account(ProviderId providerId);
virtual ~Account() = default;
virtual QString toString() const = 0; virtual QString toString() const = 0;
const QString &getCategory() const; const QString &getCategory() const;
ProviderId getProviderId() const;
bool operator<(const Account &other) const; bool operator<(const Account &other) const;
private: private:
ProviderId providerId;
QString category; QString category;
}; };

View file

@ -9,7 +9,29 @@ namespace accounts {
AccountController::AccountController() AccountController::AccountController()
{ {
this->twitch.accounts.itemInserted.connect([this](const auto &args) { this->twitch.accounts.itemInserted.connect([this](const auto &args) {
accounts.insertItem(std::dynamic_pointer_cast<Account>(args.item)); this->accounts.insertItem(std::dynamic_pointer_cast<Account>(args.item));
});
this->twitch.accounts.itemRemoved.connect([this](const auto &args) {
if (args.caller != this) {
auto &accs = this->twitch.accounts.getVector();
auto it = std::find(accs.begin(), accs.end(), args.item);
assert(it != accs.end());
this->accounts.removeItem(it - accs.begin());
}
});
this->accounts.itemRemoved.connect([this](const auto &args) {
switch (args.item->getProviderId()) {
case ProviderId::Twitch: {
auto &accs = this->twitch.accounts.getVector();
auto it = std::find(accs.begin(), accs.end(), args.item);
assert(it != accs.end());
this->twitch.accounts.removeItem(it - accs.begin(), this);
} break;
}
}); });
} }
@ -21,8 +43,18 @@ void AccountController::load()
AccountModel *AccountController::createModel(QObject *parent) AccountModel *AccountController::createModel(QObject *parent)
{ {
AccountModel *model = new AccountModel(parent); AccountModel *model = new AccountModel(parent);
// model->accountRemoved.connect([this](const auto &account) {
// switch (account->getProviderId()) {
// case ProviderId::Twitch: {
// auto &accs = this->twitch.accounts.getVector();
// auto it = std::find(accs.begin(), accs.end(), account);
// assert(it != accs.end());
// this->twitch.accounts.removeItem(it - accs.begin());
// } break;
// }
// });
//(util::BaseSignalVector<stdAccount> *)
model->init(&this->accounts); model->init(&this->accounts);
return model; return model;
} }

View file

@ -1,5 +1,7 @@
#include "accountmodel.hpp" #include "accountmodel.hpp"
#include "util/standarditemhelper.hpp"
namespace chatterino { namespace chatterino {
namespace controllers { namespace controllers {
namespace accounts { namespace accounts {
@ -21,6 +23,41 @@ void AccountModel::getRowFromItem(const std::shared_ptr<Account> &item,
std::vector<QStandardItem *> &row) std::vector<QStandardItem *> &row)
{ {
row[0]->setData(item->toString(), Qt::DisplayRole); row[0]->setData(item->toString(), Qt::DisplayRole);
row[0]->setData(QFont("Segoe UI", 10), Qt::FontRole);
// row[0]->setData(QColor(255, 255, 255), Qt::BackgroundRole);
}
int AccountModel::beforeInsert(const std::shared_ptr<Account> &item,
std::vector<QStandardItem *> &row, int proposedIndex)
{
if (this->categoryCount[item->getCategory()]++ == 0) {
auto row = this->createRow();
util::setStringItem(row[0], item->getCategory(), false, false);
// row[0]->setData(QColor(142, 36, 170), Qt::ForegroundRole);
// row[0]->setData(QColor(255, 255, 255), Qt::BackgroundRole);
row[0]->setData(QFont("Segoe UI Light", 16), Qt::FontRole);
this->insertCustomRow(std::move(row), proposedIndex);
return proposedIndex + 1;
}
return proposedIndex;
}
void AccountModel::afterRemoved(const std::shared_ptr<Account> &item,
std::vector<QStandardItem *> &row, int index)
{
auto it = this->categoryCount.find(item->getCategory());
assert(it != this->categoryCount.end());
if (it->second <= 1) {
this->categoryCount.erase(it);
this->removeCustomRow(index - 1);
} else {
it->second--;
}
} }
} // namespace accounts } // namespace accounts

View file

@ -1,8 +1,11 @@
#pragma once #pragma once
#include "controllers/accounts/account.hpp" #include "controllers/accounts/account.hpp"
#include "util/qstringhash.hpp"
#include "util/signalvectormodel.hpp" #include "util/signalvectormodel.hpp"
#include <unordered_map>
namespace chatterino { namespace chatterino {
namespace controllers { namespace controllers {
namespace accounts { namespace accounts {
@ -23,7 +26,16 @@ protected:
virtual void getRowFromItem(const std::shared_ptr<Account> &item, virtual void getRowFromItem(const std::shared_ptr<Account> &item,
std::vector<QStandardItem *> &row) override; std::vector<QStandardItem *> &row) override;
virtual int beforeInsert(const std::shared_ptr<Account> &item,
std::vector<QStandardItem *> &row, int proposedIndex) override;
virtual void afterRemoved(const std::shared_ptr<Account> &item,
std::vector<QStandardItem *> &row, int index) override;
friend class AccountController; friend class AccountController;
private:
std::unordered_map<QString, int> categoryCount;
}; };
} // namespace accounts } // namespace accounts

View file

@ -58,12 +58,12 @@ int runGui(int argc, char *argv[])
// https://stackoverflow.com/questions/15035767/is-the-qt-5-dark-fusion-theme-available-for-windows // https://stackoverflow.com/questions/15035767/is-the-qt-5-dark-fusion-theme-available-for-windows
QPalette darkPalette = a.palette(); QPalette darkPalette = a.palette();
darkPalette.setColor(QPalette::Window, QColor(33, 33, 33)); darkPalette.setColor(QPalette::Window, QColor(22, 22, 22));
darkPalette.setColor(QPalette::WindowText, Qt::white); darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white); darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127)); darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
darkPalette.setColor(QPalette::Base, QColor(90, 90, 90)); darkPalette.setColor(QPalette::Base, QColor("#333"));
darkPalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66)); darkPalette.setColor(QPalette::AlternateBase, QColor("#444"));
darkPalette.setColor(QPalette::ToolTipBase, Qt::white); darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
darkPalette.setColor(QPalette::ToolTipText, Qt::white); darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));

View file

@ -32,7 +32,8 @@ MessagePtr Message::createSystemMessage(const QString &text)
message->addElement(new TimestampElement(QTime::currentTime())); message->addElement(new TimestampElement(QTime::currentTime()));
message->addElement(new TextElement(text, MessageElement::Text, MessageColor::System)); message->addElement(new TextElement(text, MessageElement::Text, MessageColor::System));
message->flags.EnableFlag(MessageFlags::System); message->flags |= MessageFlags::System;
message->flags |= MessageFlags::DoNotTriggerNotification;
message->searchText = text; message->searchText = text;
return message; return message;

View file

@ -12,7 +12,7 @@ namespace twitch {
TwitchAccount::TwitchAccount(const QString &_username, const QString &_oauthToken, TwitchAccount::TwitchAccount(const QString &_username, const QString &_oauthToken,
const QString &_oauthClient, const QString &_userID) const QString &_oauthClient, const QString &_userID)
: controllers::accounts::Account("Twitch") : controllers::accounts::Account(ProviderId::Twitch)
, oauthClient(_oauthClient) , oauthClient(_oauthClient)
, oauthToken(_oauthToken) , oauthToken(_oauthToken)
, userName(_username) , userName(_username)

View file

@ -32,7 +32,7 @@ std::vector<QString> TwitchAccountManager::getUsernames() const
std::lock_guard<std::mutex> lock(this->mutex); std::lock_guard<std::mutex> lock(this->mutex);
for (const auto &user : this->users) { for (const auto &user : this->accounts.getVector()) {
userNames.push_back(user->getUserName()); userNames.push_back(user->getUserName());
} }
@ -44,7 +44,7 @@ std::shared_ptr<TwitchAccount> TwitchAccountManager::findUserByUsername(
{ {
std::lock_guard<std::mutex> lock(this->mutex); std::lock_guard<std::mutex> lock(this->mutex);
for (const auto &user : this->users) { for (const auto &user : this->accounts.getVector()) {
if (username.compare(user->getUserName(), Qt::CaseInsensitive) == 0) { if (username.compare(user->getUserName(), Qt::CaseInsensitive) == 0) {
return user; return user;
} }
@ -140,17 +140,27 @@ bool TwitchAccountManager::removeUser(const QString &username)
return false; return false;
} }
this->mutex.lock(); {
this->users.erase(std::remove_if(this->users.begin(), this->users.end(), [username](auto user) { std::lock_guard<std::mutex> guard(this->mutex);
if (user->getUserName() == username) {
std::string userID(user->getUserId().toStdString()); const auto &accs = this->accounts.getVector();
assert(!userID.empty());
pajlada::Settings::SettingManager::removeSetting("/accounts/uid" + userID); while (true) {
return true; auto it = std::find_if(accs.begin(), accs.end(),
[&](const auto &acc) { return acc->getUserName() == username; });
if (it == accs.end()) {
break;
}
std::string userID(it->get()->getUserId().toStdString());
if (!userID.empty()) {
pajlada::Settings::SettingManager::removeSetting("/accounts/uid" + userID);
}
this->accounts.removeItem(int(it - accs.begin()));
} }
return false; }
}));
this->mutex.unlock();
if (username == qS(this->currentUsername.getValue())) { if (username == qS(this->currentUsername.getValue())) {
// The user that was removed is the current user, log into the anonymous user // The user that was removed is the current user, log into the anonymous user
@ -189,7 +199,7 @@ TwitchAccountManager::AddUserResponse TwitchAccountManager::addUser(
std::lock_guard<std::mutex> lock(this->mutex); std::lock_guard<std::mutex> lock(this->mutex);
this->users.push_back(newUser); this->accounts.insertItem(newUser);
return AddUserResponse::UserAdded; return AddUserResponse::UserAdded;
} }

View file

@ -68,7 +68,7 @@ private:
std::shared_ptr<TwitchAccount> currentUser; std::shared_ptr<TwitchAccount> currentUser;
std::shared_ptr<TwitchAccount> anonymousUser; std::shared_ptr<TwitchAccount> anonymousUser;
std::vector<std::shared_ptr<TwitchAccount>> users; // std::vector<std::shared_ptr<TwitchAccount>> users;
mutable std::mutex mutex; mutable std::mutex mutex;
friend class chatterino::controllers::accounts::AccountController; friend class chatterino::controllers::accounts::AccountController;

View file

@ -7,7 +7,7 @@
#include "singletons/emotemanager.hpp" #include "singletons/emotemanager.hpp"
#include "singletons/ircmanager.hpp" #include "singletons/ircmanager.hpp"
#include "util/concurrentmap.hpp" #include "util/concurrentmap.hpp"
#include "util/mutexvalue.h" #include "util/mutexvalue.hpp"
#include <pajlada/signals/signalholder.hpp> #include <pajlada/signals/signalholder.hpp>

View file

@ -3,7 +3,7 @@
#include "providers/irc/abstractircserver.hpp" #include "providers/irc/abstractircserver.hpp"
#include "providers/twitch/twitchaccount.hpp" #include "providers/twitch/twitchaccount.hpp"
#include "providers/twitch/twitchchannel.hpp" #include "providers/twitch/twitchchannel.hpp"
#include "util/mutexvalue.h" #include "util/mutexvalue.hpp"
#include <memory> #include <memory>

View file

@ -113,13 +113,14 @@ void NativeMessagingManager::ReceiverThread::run()
while (true) { while (true) {
try { try {
char *buf = (char *)malloc(MESSAGE_SIZE); std::unique_ptr<char> buf(static_cast<char *>(malloc(MESSAGE_SIZE)));
ipc::message_queue::size_type retSize; ipc::message_queue::size_type retSize;
unsigned int priority; unsigned int priority;
messageQueue.receive(buf, MESSAGE_SIZE, retSize, priority); messageQueue.receive(buf.get(), MESSAGE_SIZE, retSize, priority);
QJsonDocument document = QJsonDocument::fromJson(QByteArray(buf, retSize)); QJsonDocument document =
QJsonDocument::fromJson(QByteArray::fromRawData(buf.get(), retSize));
this->handleMessage(document.object()); this->handleMessage(document.object());
} catch (ipc::interprocess_exception &ex) { } catch (ipc::interprocess_exception &ex) {

14
src/util/qstringhash.hpp Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include <QHash>
#include <QString>
namespace std {
template <>
struct hash<QString> {
std::size_t operator()(const QString &s) const
{
return qHash(s);
}
};
} // namespace std

View file

@ -1 +0,0 @@
#include "signalvectormodel.hpp"

View file

@ -28,10 +28,6 @@ public:
this->vector = vec; this->vector = vec;
auto insert = [this](const SignalVectorItemArgs<TVectorItem> &args) { auto insert = [this](const SignalVectorItemArgs<TVectorItem> &args) {
if (args.caller == this) {
return;
}
// get row index // get row index
int index = this->getModelIndexFromVectorIndex(args.index); int index = this->getModelIndexFromVectorIndex(args.index);
assert(index >= 0 && index <= this->rows.size()); assert(index >= 0 && index <= this->rows.size());
@ -58,20 +54,21 @@ public:
this->managedConnect(vec->itemInserted, insert); this->managedConnect(vec->itemInserted, insert);
this->managedConnect(vec->itemRemoved, [this](auto args) { this->managedConnect(vec->itemRemoved, [this](auto args) {
if (args.caller == this) {
return;
}
int row = this->getModelIndexFromVectorIndex(args.index); int row = this->getModelIndexFromVectorIndex(args.index);
assert(row >= 0 && row <= this->rows.size()); assert(row >= 0 && row <= this->rows.size());
// remove row // remove row
std::vector<QStandardItem *> items = std::move(this->rows[row].items);
this->beginRemoveRows(QModelIndex(), row, row); this->beginRemoveRows(QModelIndex(), row, row);
for (QStandardItem *item : this->rows[row].items) {
delete item;
}
this->rows.erase(this->rows.begin() + row); this->rows.erase(this->rows.begin() + row);
this->endRemoveRows(); this->endRemoveRows();
this->afterRemoved(args.item, items, row);
for (QStandardItem *item : items) {
delete item;
}
}); });
this->afterInit(); this->afterInit();
@ -185,7 +182,7 @@ public:
assert(row >= 0 && row < this->rows.size()); assert(row >= 0 && row < this->rows.size());
int signalVectorRow = this->getVectorIndexFromModelIndex(row); int signalVectorRow = this->getVectorIndexFromModelIndex(row);
this->vector->removeItem(signalVectorRow); this->vector->removeItem(signalVectorRow, this);
return true; return true;
} }
@ -226,6 +223,16 @@ protected:
this->endInsertRows(); this->endInsertRows();
} }
void removeCustomRow(int index)
{
assert(index >= 0 && index <= this->rows.size());
assert(this->rows[index].isCustomRow);
this->beginRemoveRows(QModelIndex(), index, index);
this->rows.erase(this->rows.begin() + index);
this->endRemoveRows();
}
std::vector<QStandardItem *> createRow() std::vector<QStandardItem *> createRow()
{ {
std::vector<QStandardItem *> row; std::vector<QStandardItem *> row;

View file

@ -78,8 +78,8 @@ void AttachedWindow::attachToHwnd(void *_hwnd)
QTimer *timer = new QTimer(this); QTimer *timer = new QTimer(this);
timer->setInterval(1); timer->setInterval(1);
HWND hwnd = (HWND)this->winId(); HWND hwnd = HWND(this->winId());
HWND attached = (HWND)_hwnd; HWND attached = HWND(_hwnd);
QObject::connect(timer, &QTimer::timeout, [this, hwnd, attached, timer] { QObject::connect(timer, &QTimer::timeout, [this, hwnd, attached, timer] {
::SetLastError(0); ::SetLastError(0);
RECT xD; RECT xD;
@ -93,7 +93,8 @@ void AttachedWindow::attachToHwnd(void *_hwnd)
HWND next = ::GetNextWindow(attached, GW_HWNDPREV); HWND next = ::GetNextWindow(attached, GW_HWNDPREV);
::SetWindowPos(hwnd, next ? next : HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); ::SetWindowPos(hwnd, next ? next : HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
::MoveWindow(hwnd, xD.right - 360, xD.top + this->yOffset - 8, 360 - 8, ::MoveWindow(hwnd, xD.right - 360, xD.top + this->yOffset - 8, 360 - 8,
xD.bottom - xD.top - this->yOffset, false); xD.bottom - xD.top - this->yOffset, false);
// ::MoveWindow(hwnd, xD.right - 360, xD.top + 82, 360 - 8, xD.bottom - xD.top - 82 - // ::MoveWindow(hwnd, xD.right - 360, xD.top + 82, 360 - 8, xD.bottom - xD.top - 82 -

View file

@ -579,7 +579,7 @@ bool ChannelView::isPaused()
void ChannelView::paintEvent(QPaintEvent * /*event*/) void ChannelView::paintEvent(QPaintEvent * /*event*/)
{ {
BenchmarkGuard benchmark("paint event"); // BenchmarkGuard benchmark("paint event");
QPainter painter(this); QPainter painter(this);

View file

@ -30,14 +30,17 @@ AccountsPage::AccountsPage()
helper::EditableModelView *view = helper::EditableModelView *view =
*layout.emplace<helper::EditableModelView>(app->accounts->createModel(nullptr)); *layout.emplace<helper::EditableModelView>(app->accounts->createModel(nullptr));
view->setTitles({"Name"}); view->getTableView()->horizontalHeader()->setVisible(false);
view->getTableView()->horizontalHeader()->setStretchLastSection(true); view->getTableView()->horizontalHeader()->setStretchLastSection(true);
view->addButtonPressed.connect([] { view->addButtonPressed.connect([] {
static auto loginWidget = new LoginWidget(); static auto loginWidget = new LoginWidget();
loginWidget->show(); loginWidget->show();
}); });
view->getTableView()->setStyleSheet("background: #333");
// auto buttons = layout.emplace<QDialogButtonBox>(); // auto buttons = layout.emplace<QDialogButtonBox>();
// { // {
// this->addButton = buttons->addButton("Add", QDialogButtonBox::YesRole); // this->addButton = buttons->addButton("Add", QDialogButtonBox::YesRole);

View file

@ -34,7 +34,7 @@ IgnoreUsersPage::IgnoreUsersPage()
// auto group = layout.emplace<QGroupBox>("Ignored users").setLayoutType<QVBoxLayout>(); // auto group = layout.emplace<QGroupBox>("Ignored users").setLayoutType<QVBoxLayout>();
auto tabs = layout.emplace<QTabWidget>(); auto tabs = layout.emplace<QTabWidget>();
tabs->setStyleSheet("color: #000"); // tabs->setStyleSheet("color: #000");
// users // users
auto users = tabs.appendTab(new QVBoxLayout, "Users"); auto users = tabs.appendTab(new QVBoxLayout, "Users");