Normalize line endings in already existing files
This commit is contained in:
+294
-294
@@ -1,294 +1,294 @@
|
||||
#include "AttachedWindow.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "util/DebugCount.hpp"
|
||||
#include "widgets/splits/Split.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#ifdef USEWINSDK
|
||||
# include "util/WindowsHelper.hpp"
|
||||
|
||||
# include "Windows.h"
|
||||
// don't even think about reordering these
|
||||
# include "Psapi.h"
|
||||
# pragma comment(lib, "Dwmapi.lib")
|
||||
#endif
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
#ifdef USEWINSDK
|
||||
static thread_local std::vector<HWND> taskbarHwnds;
|
||||
|
||||
BOOL CALLBACK enumWindows(HWND hwnd, LPARAM)
|
||||
{
|
||||
constexpr int length = 16;
|
||||
|
||||
auto className = std::make_unique<WCHAR[]>(length);
|
||||
GetClassName(hwnd, className.get(), length);
|
||||
|
||||
// qDebug() << QString::fromWCharArray(className.get(), length);
|
||||
|
||||
if (lstrcmp(className.get(), L"Shell_TrayWnd") == 0 ||
|
||||
lstrcmp(className.get(), L"Shell_Secondary") == 0)
|
||||
{
|
||||
taskbarHwnds.push_back(hwnd);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
AttachedWindow::AttachedWindow(void *_target, int _yOffset)
|
||||
: QWidget(nullptr, Qt::FramelessWindowHint | Qt::Window)
|
||||
, target_(_target)
|
||||
, yOffset_(_yOffset)
|
||||
{
|
||||
QLayout *layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
this->setLayout(layout);
|
||||
|
||||
auto *split = new Split(this);
|
||||
this->ui_.split = split;
|
||||
split->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
|
||||
layout->addWidget(split);
|
||||
|
||||
DebugCount::increase("attached window");
|
||||
}
|
||||
|
||||
AttachedWindow::~AttachedWindow()
|
||||
{
|
||||
for (auto it = items.begin(); it != items.end(); it++)
|
||||
{
|
||||
if (it->window == this)
|
||||
{
|
||||
items.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DebugCount::decrease("attached window");
|
||||
}
|
||||
|
||||
AttachedWindow *AttachedWindow::get(void *target, const GetArgs &args)
|
||||
{
|
||||
AttachedWindow *window = [&]() {
|
||||
for (Item &item : items)
|
||||
{
|
||||
if (item.hwnd == target)
|
||||
{
|
||||
return item.window;
|
||||
}
|
||||
}
|
||||
|
||||
auto *window = new AttachedWindow(target, args.yOffset);
|
||||
items.push_back(Item{target, window, args.winId});
|
||||
return window;
|
||||
}();
|
||||
|
||||
bool show = true;
|
||||
QSize size = window->size();
|
||||
|
||||
window->fullscreen_ = args.fullscreen;
|
||||
|
||||
if (args.height != -1)
|
||||
{
|
||||
if (args.height == 0)
|
||||
{
|
||||
window->hide();
|
||||
show = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->height_ = args.height;
|
||||
size.setHeight(args.height);
|
||||
}
|
||||
}
|
||||
if (args.width != -1)
|
||||
{
|
||||
if (args.width == 0)
|
||||
{
|
||||
window->hide();
|
||||
show = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->width_ = args.width;
|
||||
size.setWidth(args.width);
|
||||
}
|
||||
}
|
||||
|
||||
if (show)
|
||||
{
|
||||
window->updateWindowRect(window->target_);
|
||||
window->show();
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
void AttachedWindow::detach(const QString &winId)
|
||||
{
|
||||
for (Item &item : items)
|
||||
{
|
||||
if (item.winId == winId)
|
||||
{
|
||||
item.window->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AttachedWindow::setChannel(ChannelPtr channel)
|
||||
{
|
||||
this->ui_.split->setChannel(channel);
|
||||
}
|
||||
|
||||
void AttachedWindow::showEvent(QShowEvent *)
|
||||
{
|
||||
this->attachToHwnd(this->target_);
|
||||
}
|
||||
|
||||
void AttachedWindow::attachToHwnd(void *_attachedPtr)
|
||||
{
|
||||
#ifdef USEWINSDK
|
||||
if (this->attached_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->attached_ = true;
|
||||
|
||||
//auto hwnd = HWND(this->winId());
|
||||
auto attached = HWND(_attachedPtr);
|
||||
|
||||
// FAST TIMER - used to resize/reorder windows
|
||||
this->timer_.setInterval(1);
|
||||
QObject::connect(&this->timer_, &QTimer::timeout, [this, attached] {
|
||||
// check process id
|
||||
if (!this->validProcessName_)
|
||||
{
|
||||
DWORD processId;
|
||||
::GetWindowThreadProcessId(attached, &processId);
|
||||
|
||||
HANDLE process = ::OpenProcess(
|
||||
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId);
|
||||
|
||||
std::unique_ptr<TCHAR[]> filename(new TCHAR[512]);
|
||||
DWORD filenameLength =
|
||||
::GetModuleFileNameEx(process, nullptr, filename.get(), 512);
|
||||
QString qfilename =
|
||||
QString::fromWCharArray(filename.get(), int(filenameLength));
|
||||
|
||||
if (!qfilename.endsWith("chrome.exe") &&
|
||||
!qfilename.endsWith("firefox.exe"))
|
||||
{
|
||||
qDebug() << "NM Illegal caller" << qfilename;
|
||||
this->timer_.stop();
|
||||
this->deleteLater();
|
||||
return;
|
||||
}
|
||||
this->validProcessName_ = true;
|
||||
}
|
||||
|
||||
this->updateWindowRect(attached);
|
||||
});
|
||||
|
||||
this->timer_.start();
|
||||
|
||||
// SLOW TIMER - used to hide taskbar behind fullscreen window
|
||||
this->slowTimer_.setInterval(2000);
|
||||
QObject::connect(&this->slowTimer_, &QTimer::timeout, [this, attached] {
|
||||
if (this->fullscreen_)
|
||||
{
|
||||
taskbarHwnds.clear();
|
||||
::EnumWindows(&enumWindows, 0);
|
||||
|
||||
for (auto taskbarHwnd : taskbarHwnds)
|
||||
{
|
||||
::SetWindowPos(taskbarHwnd,
|
||||
GetNextWindow(attached, GW_HWNDNEXT), 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
}
|
||||
}
|
||||
});
|
||||
this->slowTimer_.start();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AttachedWindow::updateWindowRect(void *_attachedPtr)
|
||||
{
|
||||
#ifdef USEWINSDK
|
||||
auto hwnd = HWND(this->winId());
|
||||
auto attached = HWND(_attachedPtr);
|
||||
|
||||
// We get the window rect first so we can close this window when it returns
|
||||
// an error. If we query the process first and check the filename then it
|
||||
// will return and empty string that doens't match.
|
||||
::SetLastError(0);
|
||||
RECT rect;
|
||||
::GetWindowRect(attached, &rect);
|
||||
|
||||
if (::GetLastError() != 0)
|
||||
{
|
||||
qDebug() << "NM GetLastError()" << ::GetLastError();
|
||||
|
||||
this->timer_.stop();
|
||||
this->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// set the correct z-order
|
||||
if (HWND next = ::GetNextWindow(attached, GW_HWNDPREV))
|
||||
{
|
||||
::SetWindowPos(hwnd, next ? next : HWND_TOPMOST, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
float scale = 1.f;
|
||||
if (auto dpi = getWindowDpi(attached))
|
||||
{
|
||||
scale = dpi.get() / 96.f;
|
||||
|
||||
for (auto w : this->ui_.split->findChildren<BaseWidget *>())
|
||||
{
|
||||
w->setOverrideScale(scale);
|
||||
}
|
||||
this->ui_.split->setOverrideScale(scale);
|
||||
}
|
||||
|
||||
if (this->height_ != -1)
|
||||
{
|
||||
this->ui_.split->setFixedWidth(int(this->width_ * scale));
|
||||
|
||||
// offset
|
||||
int o = this->fullscreen_ ? 0 : 8;
|
||||
|
||||
::MoveWindow(hwnd, int(rect.right - this->width_ * scale - o),
|
||||
int(rect.bottom - this->height_ * scale - o) + 4,
|
||||
int(this->width_ * scale) - 5,
|
||||
int(this->height_ * scale) - 5, true);
|
||||
}
|
||||
|
||||
// if (this->fullscreen_)
|
||||
// {
|
||||
// ::BringWindowToTop(attached);
|
||||
// }
|
||||
|
||||
// ::MoveWindow(hwnd, rect.right - 360, rect.top + 82, 360 - 8,
|
||||
// rect.bottom - rect.top - 82 - 8, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
// void AttachedWindow::nativeEvent(const QByteArray &eventType, void *message,
|
||||
// long *result)
|
||||
//{
|
||||
// MSG *msg = reinterpret_cast
|
||||
|
||||
// case WM_NCCALCSIZE: {
|
||||
// }
|
||||
//}
|
||||
|
||||
std::vector<AttachedWindow::Item> AttachedWindow::items;
|
||||
|
||||
} // namespace chatterino
|
||||
#include "AttachedWindow.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "util/DebugCount.hpp"
|
||||
#include "widgets/splits/Split.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#ifdef USEWINSDK
|
||||
# include "util/WindowsHelper.hpp"
|
||||
|
||||
# include "Windows.h"
|
||||
// don't even think about reordering these
|
||||
# include "Psapi.h"
|
||||
# pragma comment(lib, "Dwmapi.lib")
|
||||
#endif
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
#ifdef USEWINSDK
|
||||
static thread_local std::vector<HWND> taskbarHwnds;
|
||||
|
||||
BOOL CALLBACK enumWindows(HWND hwnd, LPARAM)
|
||||
{
|
||||
constexpr int length = 16;
|
||||
|
||||
auto className = std::make_unique<WCHAR[]>(length);
|
||||
GetClassName(hwnd, className.get(), length);
|
||||
|
||||
// qDebug() << QString::fromWCharArray(className.get(), length);
|
||||
|
||||
if (lstrcmp(className.get(), L"Shell_TrayWnd") == 0 ||
|
||||
lstrcmp(className.get(), L"Shell_Secondary") == 0)
|
||||
{
|
||||
taskbarHwnds.push_back(hwnd);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
AttachedWindow::AttachedWindow(void *_target, int _yOffset)
|
||||
: QWidget(nullptr, Qt::FramelessWindowHint | Qt::Window)
|
||||
, target_(_target)
|
||||
, yOffset_(_yOffset)
|
||||
{
|
||||
QLayout *layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
this->setLayout(layout);
|
||||
|
||||
auto *split = new Split(this);
|
||||
this->ui_.split = split;
|
||||
split->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
|
||||
layout->addWidget(split);
|
||||
|
||||
DebugCount::increase("attached window");
|
||||
}
|
||||
|
||||
AttachedWindow::~AttachedWindow()
|
||||
{
|
||||
for (auto it = items.begin(); it != items.end(); it++)
|
||||
{
|
||||
if (it->window == this)
|
||||
{
|
||||
items.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DebugCount::decrease("attached window");
|
||||
}
|
||||
|
||||
AttachedWindow *AttachedWindow::get(void *target, const GetArgs &args)
|
||||
{
|
||||
AttachedWindow *window = [&]() {
|
||||
for (Item &item : items)
|
||||
{
|
||||
if (item.hwnd == target)
|
||||
{
|
||||
return item.window;
|
||||
}
|
||||
}
|
||||
|
||||
auto *window = new AttachedWindow(target, args.yOffset);
|
||||
items.push_back(Item{target, window, args.winId});
|
||||
return window;
|
||||
}();
|
||||
|
||||
bool show = true;
|
||||
QSize size = window->size();
|
||||
|
||||
window->fullscreen_ = args.fullscreen;
|
||||
|
||||
if (args.height != -1)
|
||||
{
|
||||
if (args.height == 0)
|
||||
{
|
||||
window->hide();
|
||||
show = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->height_ = args.height;
|
||||
size.setHeight(args.height);
|
||||
}
|
||||
}
|
||||
if (args.width != -1)
|
||||
{
|
||||
if (args.width == 0)
|
||||
{
|
||||
window->hide();
|
||||
show = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->width_ = args.width;
|
||||
size.setWidth(args.width);
|
||||
}
|
||||
}
|
||||
|
||||
if (show)
|
||||
{
|
||||
window->updateWindowRect(window->target_);
|
||||
window->show();
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
void AttachedWindow::detach(const QString &winId)
|
||||
{
|
||||
for (Item &item : items)
|
||||
{
|
||||
if (item.winId == winId)
|
||||
{
|
||||
item.window->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AttachedWindow::setChannel(ChannelPtr channel)
|
||||
{
|
||||
this->ui_.split->setChannel(channel);
|
||||
}
|
||||
|
||||
void AttachedWindow::showEvent(QShowEvent *)
|
||||
{
|
||||
this->attachToHwnd(this->target_);
|
||||
}
|
||||
|
||||
void AttachedWindow::attachToHwnd(void *_attachedPtr)
|
||||
{
|
||||
#ifdef USEWINSDK
|
||||
if (this->attached_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this->attached_ = true;
|
||||
|
||||
//auto hwnd = HWND(this->winId());
|
||||
auto attached = HWND(_attachedPtr);
|
||||
|
||||
// FAST TIMER - used to resize/reorder windows
|
||||
this->timer_.setInterval(1);
|
||||
QObject::connect(&this->timer_, &QTimer::timeout, [this, attached] {
|
||||
// check process id
|
||||
if (!this->validProcessName_)
|
||||
{
|
||||
DWORD processId;
|
||||
::GetWindowThreadProcessId(attached, &processId);
|
||||
|
||||
HANDLE process = ::OpenProcess(
|
||||
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId);
|
||||
|
||||
std::unique_ptr<TCHAR[]> filename(new TCHAR[512]);
|
||||
DWORD filenameLength =
|
||||
::GetModuleFileNameEx(process, nullptr, filename.get(), 512);
|
||||
QString qfilename =
|
||||
QString::fromWCharArray(filename.get(), int(filenameLength));
|
||||
|
||||
if (!qfilename.endsWith("chrome.exe") &&
|
||||
!qfilename.endsWith("firefox.exe"))
|
||||
{
|
||||
qDebug() << "NM Illegal caller" << qfilename;
|
||||
this->timer_.stop();
|
||||
this->deleteLater();
|
||||
return;
|
||||
}
|
||||
this->validProcessName_ = true;
|
||||
}
|
||||
|
||||
this->updateWindowRect(attached);
|
||||
});
|
||||
|
||||
this->timer_.start();
|
||||
|
||||
// SLOW TIMER - used to hide taskbar behind fullscreen window
|
||||
this->slowTimer_.setInterval(2000);
|
||||
QObject::connect(&this->slowTimer_, &QTimer::timeout, [this, attached] {
|
||||
if (this->fullscreen_)
|
||||
{
|
||||
taskbarHwnds.clear();
|
||||
::EnumWindows(&enumWindows, 0);
|
||||
|
||||
for (auto taskbarHwnd : taskbarHwnds)
|
||||
{
|
||||
::SetWindowPos(taskbarHwnd,
|
||||
GetNextWindow(attached, GW_HWNDNEXT), 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
}
|
||||
}
|
||||
});
|
||||
this->slowTimer_.start();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AttachedWindow::updateWindowRect(void *_attachedPtr)
|
||||
{
|
||||
#ifdef USEWINSDK
|
||||
auto hwnd = HWND(this->winId());
|
||||
auto attached = HWND(_attachedPtr);
|
||||
|
||||
// We get the window rect first so we can close this window when it returns
|
||||
// an error. If we query the process first and check the filename then it
|
||||
// will return and empty string that doens't match.
|
||||
::SetLastError(0);
|
||||
RECT rect;
|
||||
::GetWindowRect(attached, &rect);
|
||||
|
||||
if (::GetLastError() != 0)
|
||||
{
|
||||
qDebug() << "NM GetLastError()" << ::GetLastError();
|
||||
|
||||
this->timer_.stop();
|
||||
this->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// set the correct z-order
|
||||
if (HWND next = ::GetNextWindow(attached, GW_HWNDPREV))
|
||||
{
|
||||
::SetWindowPos(hwnd, next ? next : HWND_TOPMOST, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
float scale = 1.f;
|
||||
if (auto dpi = getWindowDpi(attached))
|
||||
{
|
||||
scale = dpi.get() / 96.f;
|
||||
|
||||
for (auto w : this->ui_.split->findChildren<BaseWidget *>())
|
||||
{
|
||||
w->setOverrideScale(scale);
|
||||
}
|
||||
this->ui_.split->setOverrideScale(scale);
|
||||
}
|
||||
|
||||
if (this->height_ != -1)
|
||||
{
|
||||
this->ui_.split->setFixedWidth(int(this->width_ * scale));
|
||||
|
||||
// offset
|
||||
int o = this->fullscreen_ ? 0 : 8;
|
||||
|
||||
::MoveWindow(hwnd, int(rect.right - this->width_ * scale - o),
|
||||
int(rect.bottom - this->height_ * scale - o) + 4,
|
||||
int(this->width_ * scale) - 5,
|
||||
int(this->height_ * scale) - 5, true);
|
||||
}
|
||||
|
||||
// if (this->fullscreen_)
|
||||
// {
|
||||
// ::BringWindowToTop(attached);
|
||||
// }
|
||||
|
||||
// ::MoveWindow(hwnd, rect.right - 360, rect.top + 82, 360 - 8,
|
||||
// rect.bottom - rect.top - 82 - 8, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
// void AttachedWindow::nativeEvent(const QByteArray &eventType, void *message,
|
||||
// long *result)
|
||||
//{
|
||||
// MSG *msg = reinterpret_cast
|
||||
|
||||
// case WM_NCCALCSIZE: {
|
||||
// }
|
||||
//}
|
||||
|
||||
std::vector<AttachedWindow::Item> AttachedWindow::items;
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Split;
|
||||
class Channel;
|
||||
using ChannelPtr = std::shared_ptr<Channel>;
|
||||
|
||||
class AttachedWindow : public QWidget
|
||||
{
|
||||
AttachedWindow(void *_target, int _yOffset);
|
||||
|
||||
public:
|
||||
struct GetArgs {
|
||||
QString winId;
|
||||
int yOffset = -1;
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
bool fullscreen = false;
|
||||
};
|
||||
|
||||
virtual ~AttachedWindow() override;
|
||||
|
||||
static AttachedWindow *get(void *target_, const GetArgs &args);
|
||||
static void detach(const QString &winId);
|
||||
|
||||
void setChannel(ChannelPtr channel);
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent *) override;
|
||||
// virtual void nativeEvent(const QByteArray &eventType, void *message,
|
||||
// long *result) override;
|
||||
|
||||
private:
|
||||
struct {
|
||||
Split *split;
|
||||
} ui_;
|
||||
|
||||
struct Item {
|
||||
void *hwnd;
|
||||
AttachedWindow *window;
|
||||
QString winId;
|
||||
};
|
||||
|
||||
static std::vector<Item> items;
|
||||
|
||||
void attachToHwnd(void *attached);
|
||||
void updateWindowRect(void *attached);
|
||||
|
||||
void *target_;
|
||||
int yOffset_;
|
||||
int currentYOffset_;
|
||||
int width_ = 360;
|
||||
int height_ = -1;
|
||||
bool fullscreen_ = false;
|
||||
|
||||
#ifdef USEWINSDK
|
||||
bool validProcessName_ = false;
|
||||
bool attached_ = false;
|
||||
#endif
|
||||
QTimer timer_;
|
||||
QTimer slowTimer_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Split;
|
||||
class Channel;
|
||||
using ChannelPtr = std::shared_ptr<Channel>;
|
||||
|
||||
class AttachedWindow : public QWidget
|
||||
{
|
||||
AttachedWindow(void *_target, int _yOffset);
|
||||
|
||||
public:
|
||||
struct GetArgs {
|
||||
QString winId;
|
||||
int yOffset = -1;
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
bool fullscreen = false;
|
||||
};
|
||||
|
||||
virtual ~AttachedWindow() override;
|
||||
|
||||
static AttachedWindow *get(void *target_, const GetArgs &args);
|
||||
static void detach(const QString &winId);
|
||||
|
||||
void setChannel(ChannelPtr channel);
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent *) override;
|
||||
// virtual void nativeEvent(const QByteArray &eventType, void *message,
|
||||
// long *result) override;
|
||||
|
||||
private:
|
||||
struct {
|
||||
Split *split;
|
||||
} ui_;
|
||||
|
||||
struct Item {
|
||||
void *hwnd;
|
||||
AttachedWindow *window;
|
||||
QString winId;
|
||||
};
|
||||
|
||||
static std::vector<Item> items;
|
||||
|
||||
void attachToHwnd(void *attached);
|
||||
void updateWindowRect(void *attached);
|
||||
|
||||
void *target_;
|
||||
int yOffset_;
|
||||
int currentYOffset_;
|
||||
int width_ = 360;
|
||||
int height_ = -1;
|
||||
bool fullscreen_ = false;
|
||||
|
||||
#ifdef USEWINSDK
|
||||
bool validProcessName_ = false;
|
||||
bool attached_ = false;
|
||||
#endif
|
||||
QTimer timer_;
|
||||
QTimer slowTimer_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
+35
-35
@@ -1,35 +1,35 @@
|
||||
#include "StreamView.hpp"
|
||||
|
||||
#include "common/Channel.hpp"
|
||||
#include "util/Helpers.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/helper/ChannelView.hpp"
|
||||
#include "widgets/splits/Split.hpp"
|
||||
|
||||
#ifdef USEWEBENGINE
|
||||
# include <QtWebEngineWidgets>
|
||||
#endif
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
StreamView::StreamView(ChannelPtr channel, const QUrl &url)
|
||||
{
|
||||
LayoutCreator<StreamView> layoutCreator(this);
|
||||
|
||||
#ifdef USEWEBENGINE
|
||||
auto web =
|
||||
layoutCreator.emplace<QWebEngineView>(this).assign(&this->stream);
|
||||
web->setUrl(url);
|
||||
web->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled,
|
||||
true);
|
||||
#endif
|
||||
|
||||
auto chat = layoutCreator.emplace<ChannelView>();
|
||||
chat->setFixedWidth(300);
|
||||
chat->setChannel(channel);
|
||||
|
||||
this->layout()->setSpacing(0);
|
||||
this->layout()->setMargin(0);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "StreamView.hpp"
|
||||
|
||||
#include "common/Channel.hpp"
|
||||
#include "util/Helpers.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/helper/ChannelView.hpp"
|
||||
#include "widgets/splits/Split.hpp"
|
||||
|
||||
#ifdef USEWEBENGINE
|
||||
# include <QtWebEngineWidgets>
|
||||
#endif
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
StreamView::StreamView(ChannelPtr channel, const QUrl &url)
|
||||
{
|
||||
LayoutCreator<StreamView> layoutCreator(this);
|
||||
|
||||
#ifdef USEWEBENGINE
|
||||
auto web =
|
||||
layoutCreator.emplace<QWebEngineView>(this).assign(&this->stream);
|
||||
web->setUrl(url);
|
||||
web->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled,
|
||||
true);
|
||||
#endif
|
||||
|
||||
auto chat = layoutCreator.emplace<ChannelView>();
|
||||
chat->setFixedWidth(300);
|
||||
chat->setChannel(channel);
|
||||
|
||||
this->layout()->setSpacing(0);
|
||||
this->layout()->setMargin(0);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
+25
-25
@@ -1,25 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <QUrl>
|
||||
#include <QWidget>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QWebEngineView;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Channel;
|
||||
|
||||
class StreamView : public QWidget
|
||||
{
|
||||
public:
|
||||
StreamView(std::shared_ptr<Channel> channel, const QUrl &url);
|
||||
|
||||
private:
|
||||
#ifdef USEWEBENGINE
|
||||
QWebEngineView *stream;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QUrl>
|
||||
#include <QWidget>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QWebEngineView;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Channel;
|
||||
|
||||
class StreamView : public QWidget
|
||||
{
|
||||
public:
|
||||
StreamView(std::shared_ptr<Channel> channel, const QUrl &url);
|
||||
|
||||
private:
|
||||
#ifdef USEWEBENGINE
|
||||
QWebEngineView *stream;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
#include "LastRunCrashDialog.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "singletons/Updates.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/PostToThread.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
LastRunCrashDialog::LastRunCrashDialog()
|
||||
{
|
||||
this->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||
this->setWindowTitle("Chatterino");
|
||||
|
||||
auto layout =
|
||||
LayoutCreator<LastRunCrashDialog>(this).setLayoutType<QVBoxLayout>();
|
||||
|
||||
layout.emplace<QLabel>("The application wasn't terminated properly the "
|
||||
"last time it was executed.");
|
||||
|
||||
layout->addSpacing(16);
|
||||
|
||||
// auto update = layout.emplace<QLabel>();
|
||||
auto buttons = layout.emplace<QDialogButtonBox>();
|
||||
|
||||
// auto *installUpdateButton = buttons->addButton("Install Update",
|
||||
// QDialogButtonBox::NoRole); installUpdateButton->setEnabled(false);
|
||||
// QObject::connect(installUpdateButton, &QPushButton::clicked, [this,
|
||||
// update]() mutable {
|
||||
// auto &updateManager = UpdateManager::getInstance();
|
||||
|
||||
// updateManager.installUpdates();
|
||||
// this->setEnabled(false);
|
||||
// update->setText("Downloading updates...");
|
||||
// });
|
||||
|
||||
auto *okButton =
|
||||
buttons->addButton("Ignore", QDialogButtonBox::ButtonRole::NoRole);
|
||||
QObject::connect(okButton, &QPushButton::clicked,
|
||||
[this] { this->accept(); });
|
||||
|
||||
// Updates
|
||||
// auto updateUpdateLabel = [update]() mutable {
|
||||
// auto &updateManager = UpdateManager::getInstance();
|
||||
|
||||
// switch (updateManager.getStatus()) {
|
||||
// case UpdateManager::None: {
|
||||
// update->setText("Not checking for updates.");
|
||||
// } break;
|
||||
// case UpdateManager::Searching: {
|
||||
// update->setText("Checking for updates...");
|
||||
// } break;
|
||||
// case UpdateManager::UpdateAvailable: {
|
||||
// update->setText("Update available.");
|
||||
// } break;
|
||||
// case UpdateManager::NoUpdateAvailable: {
|
||||
// update->setText("No update abailable.");
|
||||
// } break;
|
||||
// case UpdateManager::SearchFailed: {
|
||||
// update->setText("Error while searching for update.\nEither
|
||||
// the update service is "
|
||||
// "temporarily down or there is an issue
|
||||
// with your installation.");
|
||||
// } break;
|
||||
// case UpdateManager::Downloading: {
|
||||
// update->setText(
|
||||
// "Downloading the update. Chatterino will close once
|
||||
// the download is done.");
|
||||
// } break;
|
||||
// case UpdateManager::DownloadFailed: {
|
||||
// update->setText("Download failed.");
|
||||
// } break;
|
||||
// case UpdateManager::WriteFileFailed: {
|
||||
// update->setText("Writing the update file to the hard drive
|
||||
// failed.");
|
||||
// } break;
|
||||
// }
|
||||
// };
|
||||
|
||||
// updateUpdateLabel();
|
||||
// this->managedConnect(updateManager.statusUpdated,
|
||||
// [updateUpdateLabel](auto) mutable {
|
||||
// postToThread([updateUpdateLabel]() mutable { updateUpdateLabel();
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "LastRunCrashDialog.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "singletons/Updates.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/PostToThread.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
LastRunCrashDialog::LastRunCrashDialog()
|
||||
{
|
||||
this->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||
this->setWindowTitle("Chatterino");
|
||||
|
||||
auto layout =
|
||||
LayoutCreator<LastRunCrashDialog>(this).setLayoutType<QVBoxLayout>();
|
||||
|
||||
layout.emplace<QLabel>("The application wasn't terminated properly the "
|
||||
"last time it was executed.");
|
||||
|
||||
layout->addSpacing(16);
|
||||
|
||||
// auto update = layout.emplace<QLabel>();
|
||||
auto buttons = layout.emplace<QDialogButtonBox>();
|
||||
|
||||
// auto *installUpdateButton = buttons->addButton("Install Update",
|
||||
// QDialogButtonBox::NoRole); installUpdateButton->setEnabled(false);
|
||||
// QObject::connect(installUpdateButton, &QPushButton::clicked, [this,
|
||||
// update]() mutable {
|
||||
// auto &updateManager = UpdateManager::getInstance();
|
||||
|
||||
// updateManager.installUpdates();
|
||||
// this->setEnabled(false);
|
||||
// update->setText("Downloading updates...");
|
||||
// });
|
||||
|
||||
auto *okButton =
|
||||
buttons->addButton("Ignore", QDialogButtonBox::ButtonRole::NoRole);
|
||||
QObject::connect(okButton, &QPushButton::clicked,
|
||||
[this] { this->accept(); });
|
||||
|
||||
// Updates
|
||||
// auto updateUpdateLabel = [update]() mutable {
|
||||
// auto &updateManager = UpdateManager::getInstance();
|
||||
|
||||
// switch (updateManager.getStatus()) {
|
||||
// case UpdateManager::None: {
|
||||
// update->setText("Not checking for updates.");
|
||||
// } break;
|
||||
// case UpdateManager::Searching: {
|
||||
// update->setText("Checking for updates...");
|
||||
// } break;
|
||||
// case UpdateManager::UpdateAvailable: {
|
||||
// update->setText("Update available.");
|
||||
// } break;
|
||||
// case UpdateManager::NoUpdateAvailable: {
|
||||
// update->setText("No update abailable.");
|
||||
// } break;
|
||||
// case UpdateManager::SearchFailed: {
|
||||
// update->setText("Error while searching for update.\nEither
|
||||
// the update service is "
|
||||
// "temporarily down or there is an issue
|
||||
// with your installation.");
|
||||
// } break;
|
||||
// case UpdateManager::Downloading: {
|
||||
// update->setText(
|
||||
// "Downloading the update. Chatterino will close once
|
||||
// the download is done.");
|
||||
// } break;
|
||||
// case UpdateManager::DownloadFailed: {
|
||||
// update->setText("Download failed.");
|
||||
// } break;
|
||||
// case UpdateManager::WriteFileFailed: {
|
||||
// update->setText("Writing the update file to the hard drive
|
||||
// failed.");
|
||||
// } break;
|
||||
// }
|
||||
// };
|
||||
|
||||
// updateUpdateLabel();
|
||||
// this->managedConnect(updateManager.statusUpdated,
|
||||
// [updateUpdateLabel](auto) mutable {
|
||||
// postToThread([updateUpdateLabel]() mutable { updateUpdateLabel();
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <pajlada/signals/signalholder.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class LastRunCrashDialog : public QDialog, pajlada::Signals::SignalHolder
|
||||
{
|
||||
public:
|
||||
LastRunCrashDialog();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <pajlada/signals/signalholder.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class LastRunCrashDialog : public QDialog, pajlada::Signals::SignalHolder
|
||||
{
|
||||
public:
|
||||
LastRunCrashDialog();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
#include "NotificationPopup.hpp"
|
||||
|
||||
#include "common/Channel.hpp"
|
||||
#include "messages/Message.hpp"
|
||||
#include "widgets/helper/ChannelView.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QScreen>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
NotificationPopup::NotificationPopup()
|
||||
: BaseWindow((QWidget *)nullptr, BaseWindow::Frameless)
|
||||
, channel_(std::make_shared<Channel>("notifications", Channel::Type::None))
|
||||
|
||||
{
|
||||
this->channelView_ = new ChannelView(this);
|
||||
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
this->setLayout(layout);
|
||||
|
||||
layout->addWidget(this->channelView_);
|
||||
|
||||
this->channelView_->setChannel(this->channel_);
|
||||
this->setScaleIndependantSize(300, 150);
|
||||
}
|
||||
|
||||
void NotificationPopup::updatePosition()
|
||||
{
|
||||
Location location = BottomRight;
|
||||
|
||||
QDesktopWidget *desktop = QApplication::desktop();
|
||||
const QRect rect = desktop->availableGeometry();
|
||||
|
||||
switch (location)
|
||||
{
|
||||
case BottomRight:
|
||||
{
|
||||
this->move(rect.right() - this->width(),
|
||||
rect.bottom() - this->height());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationPopup::addMessage(MessagePtr msg)
|
||||
{
|
||||
this->channel_->addMessage(msg);
|
||||
|
||||
// QTimer::singleShot(5000, this, [this, msg] { this->channel->remove });
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "NotificationPopup.hpp"
|
||||
|
||||
#include "common/Channel.hpp"
|
||||
#include "messages/Message.hpp"
|
||||
#include "widgets/helper/ChannelView.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QScreen>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
NotificationPopup::NotificationPopup()
|
||||
: BaseWindow((QWidget *)nullptr, BaseWindow::Frameless)
|
||||
, channel_(std::make_shared<Channel>("notifications", Channel::Type::None))
|
||||
|
||||
{
|
||||
this->channelView_ = new ChannelView(this);
|
||||
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
this->setLayout(layout);
|
||||
|
||||
layout->addWidget(this->channelView_);
|
||||
|
||||
this->channelView_->setChannel(this->channel_);
|
||||
this->setScaleIndependantSize(300, 150);
|
||||
}
|
||||
|
||||
void NotificationPopup::updatePosition()
|
||||
{
|
||||
Location location = BottomRight;
|
||||
|
||||
QDesktopWidget *desktop = QApplication::desktop();
|
||||
const QRect rect = desktop->availableGeometry();
|
||||
|
||||
switch (location)
|
||||
{
|
||||
case BottomRight:
|
||||
{
|
||||
this->move(rect.right() - this->width(),
|
||||
rect.bottom() - this->height());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationPopup::addMessage(MessagePtr msg)
|
||||
{
|
||||
this->channel_->addMessage(msg);
|
||||
|
||||
// QTimer::singleShot(5000, this, [this, msg] { this->channel->remove });
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class ChannelView;
|
||||
|
||||
class Channel;
|
||||
using ChannelPtr = std::shared_ptr<Channel>;
|
||||
|
||||
struct Message;
|
||||
using MessagePtr = std::shared_ptr<const Message>;
|
||||
|
||||
class NotificationPopup : public BaseWindow
|
||||
{
|
||||
public:
|
||||
enum Location { TopLeft, TopRight, BottomLeft, BottomRight };
|
||||
NotificationPopup();
|
||||
|
||||
void addMessage(MessagePtr msg);
|
||||
void updatePosition();
|
||||
|
||||
private:
|
||||
ChannelView *channelView_;
|
||||
ChannelPtr channel_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class ChannelView;
|
||||
|
||||
class Channel;
|
||||
using ChannelPtr = std::shared_ptr<Channel>;
|
||||
|
||||
struct Message;
|
||||
using MessagePtr = std::shared_ptr<const Message>;
|
||||
|
||||
class NotificationPopup : public BaseWindow
|
||||
{
|
||||
public:
|
||||
enum Location { TopLeft, TopRight, BottomLeft, BottomRight };
|
||||
NotificationPopup();
|
||||
|
||||
void addMessage(MessagePtr msg);
|
||||
void updatePosition();
|
||||
|
||||
private:
|
||||
ChannelView *channelView_;
|
||||
ChannelPtr channel_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,358 +1,358 @@
|
||||
#include "SelectChannelDialog.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "providers/twitch/TwitchServer.hpp"
|
||||
#include "singletons/Theme.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/Notebook.hpp"
|
||||
#include "widgets/helper/NotebookTab.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#define TAB_TWITCH 0
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
SelectChannelDialog::SelectChannelDialog(QWidget *parent)
|
||||
: BaseWindow(parent, BaseWindow::EnableCustomFrame)
|
||||
, selectedChannel_(Channel::getEmpty())
|
||||
{
|
||||
this->setWindowTitle("Select a channel to join");
|
||||
|
||||
this->tabFilter_.dialog = this;
|
||||
|
||||
LayoutCreator<QWidget> layoutWidget(this->getLayoutContainer());
|
||||
auto layout = layoutWidget.setLayoutType<QVBoxLayout>().withoutMargin();
|
||||
auto notebook = layout.emplace<Notebook>(this).assign(&this->ui_.notebook);
|
||||
|
||||
// twitch
|
||||
{
|
||||
LayoutCreator<QWidget> obj(new QWidget());
|
||||
auto vbox = obj.setLayoutType<QVBoxLayout>();
|
||||
|
||||
// channel_btn
|
||||
auto channel_btn = vbox.emplace<QRadioButton>("Channel").assign(
|
||||
&this->ui_.twitch.channel);
|
||||
auto channel_lbl =
|
||||
vbox.emplace<QLabel>("Join a twitch channel by its name.").hidden();
|
||||
channel_lbl->setWordWrap(true);
|
||||
auto channel_edit = vbox.emplace<QLineEdit>().hidden().assign(
|
||||
&this->ui_.twitch.channelName);
|
||||
|
||||
QObject::connect(channel_btn.getElement(), &QRadioButton::toggled,
|
||||
[=](bool enabled) mutable {
|
||||
if (enabled)
|
||||
{
|
||||
channel_edit->setFocus();
|
||||
channel_edit->setSelection(
|
||||
0, channel_edit->text().length());
|
||||
}
|
||||
|
||||
channel_edit->setVisible(enabled);
|
||||
channel_lbl->setVisible(enabled);
|
||||
});
|
||||
|
||||
channel_btn->installEventFilter(&this->tabFilter_);
|
||||
channel_edit->installEventFilter(&this->tabFilter_);
|
||||
|
||||
// whispers_btn
|
||||
auto whispers_btn = vbox.emplace<QRadioButton>("Whispers")
|
||||
.assign(&this->ui_.twitch.whispers);
|
||||
auto whispers_lbl =
|
||||
vbox.emplace<QLabel>("Shows the whispers that you receive while "
|
||||
"chatterino is running.")
|
||||
.hidden();
|
||||
|
||||
whispers_lbl->setWordWrap(true);
|
||||
whispers_btn->installEventFilter(&this->tabFilter_);
|
||||
|
||||
QObject::connect(
|
||||
whispers_btn.getElement(), &QRadioButton::toggled,
|
||||
[=](bool enabled) mutable { whispers_lbl->setVisible(enabled); });
|
||||
|
||||
// mentions_btn
|
||||
auto mentions_btn = vbox.emplace<QRadioButton>("Mentions")
|
||||
.assign(&this->ui_.twitch.mentions);
|
||||
auto mentions_lbl =
|
||||
vbox.emplace<QLabel>("Shows all the messages that highlight you "
|
||||
"from any channel.")
|
||||
.hidden();
|
||||
|
||||
mentions_lbl->setWordWrap(true);
|
||||
mentions_btn->installEventFilter(&this->tabFilter_);
|
||||
|
||||
QObject::connect(
|
||||
mentions_btn.getElement(), &QRadioButton::toggled,
|
||||
[=](bool enabled) mutable { mentions_lbl->setVisible(enabled); });
|
||||
|
||||
// watching_btn
|
||||
auto watching_btn = vbox.emplace<QRadioButton>("Watching")
|
||||
.assign(&this->ui_.twitch.watching);
|
||||
auto watching_lbl =
|
||||
vbox.emplace<QLabel>("Requires the chatterino browser extension.")
|
||||
.hidden();
|
||||
|
||||
watching_lbl->setWordWrap(true);
|
||||
watching_btn->installEventFilter(&this->tabFilter_);
|
||||
|
||||
QObject::connect(
|
||||
watching_btn.getElement(), &QRadioButton::toggled,
|
||||
[=](bool enabled) mutable { watching_lbl->setVisible(enabled); });
|
||||
|
||||
vbox->addStretch(1);
|
||||
|
||||
// tabbing order
|
||||
QWidget::setTabOrder(watching_btn.getElement(),
|
||||
channel_btn.getElement());
|
||||
QWidget::setTabOrder(channel_btn.getElement(),
|
||||
whispers_btn.getElement());
|
||||
QWidget::setTabOrder(whispers_btn.getElement(),
|
||||
mentions_btn.getElement());
|
||||
QWidget::setTabOrder(mentions_btn.getElement(),
|
||||
watching_btn.getElement());
|
||||
|
||||
// tab
|
||||
auto tab = notebook->addPage(obj.getElement());
|
||||
tab->setCustomTitle("Twitch");
|
||||
}
|
||||
|
||||
// irc
|
||||
/*
|
||||
{
|
||||
LayoutCreator<QWidget> obj(new QWidget());
|
||||
auto vbox = obj.setLayoutType<QVBoxLayout>();
|
||||
auto form = vbox.emplace<QFormLayout>();
|
||||
|
||||
form->addRow(new QLabel("User name:"), new QLineEdit());
|
||||
form->addRow(new QLabel("First nick choice:"), new QLineEdit());
|
||||
form->addRow(new QLabel("Second nick choice:"), new QLineEdit());
|
||||
form->addRow(new QLabel("Third nick choice:"), new QLineEdit());
|
||||
|
||||
auto tab = notebook->addPage(obj.getElement());
|
||||
tab->setCustomTitle("Irc");
|
||||
}
|
||||
*/
|
||||
|
||||
layout->setStretchFactor(notebook.getElement(), 1);
|
||||
|
||||
auto buttons =
|
||||
layout.emplace<QHBoxLayout>().emplace<QDialogButtonBox>(this);
|
||||
{
|
||||
auto *button_ok = buttons->addButton(QDialogButtonBox::Ok);
|
||||
QObject::connect(button_ok, &QPushButton::clicked,
|
||||
[=](bool) { this->ok(); });
|
||||
auto *button_cancel = buttons->addButton(QDialogButtonBox::Cancel);
|
||||
QObject::connect(button_cancel, &QAbstractButton::clicked,
|
||||
[=](bool) { this->close(); });
|
||||
}
|
||||
|
||||
this->setScaleIndependantSize(300, 310);
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.channel->setFocus();
|
||||
|
||||
// Shortcuts
|
||||
auto *shortcut_ok = new QShortcut(QKeySequence("Return"), this);
|
||||
QObject::connect(shortcut_ok, &QShortcut::activated, [=] { this->ok(); });
|
||||
auto *shortcut_cancel = new QShortcut(QKeySequence("Esc"), this);
|
||||
QObject::connect(shortcut_cancel, &QShortcut::activated,
|
||||
[=] { this->close(); });
|
||||
}
|
||||
|
||||
void SelectChannelDialog::ok()
|
||||
{
|
||||
this->hasSelectedChannel_ = true;
|
||||
this->close();
|
||||
}
|
||||
|
||||
void SelectChannelDialog::setSelectedChannel(IndirectChannel _channel)
|
||||
{
|
||||
auto channel = _channel.get();
|
||||
|
||||
assert(channel);
|
||||
|
||||
this->selectedChannel_ = channel;
|
||||
|
||||
switch (_channel.getType())
|
||||
{
|
||||
case Channel::Type::Twitch:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.channel->setFocus();
|
||||
this->ui_.twitch.channelName->setText(channel->getName());
|
||||
}
|
||||
break;
|
||||
case Channel::Type::TwitchWatching:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.watching->setFocus();
|
||||
}
|
||||
break;
|
||||
case Channel::Type::TwitchMentions:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.mentions->setFocus();
|
||||
}
|
||||
break;
|
||||
case Channel::Type::TwitchWhispers:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.whispers->setFocus();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.channel->setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
this->hasSelectedChannel_ = false;
|
||||
}
|
||||
|
||||
IndirectChannel SelectChannelDialog::getSelectedChannel() const
|
||||
{
|
||||
if (!this->hasSelectedChannel_)
|
||||
{
|
||||
return this->selectedChannel_;
|
||||
}
|
||||
|
||||
auto app = getApp();
|
||||
|
||||
switch (this->ui_.notebook->getSelectedIndex())
|
||||
{
|
||||
case TAB_TWITCH:
|
||||
{
|
||||
if (this->ui_.twitch.channel->isChecked())
|
||||
{
|
||||
return app->twitch.server->getOrAddChannel(
|
||||
this->ui_.twitch.channelName->text().trimmed());
|
||||
}
|
||||
else if (this->ui_.twitch.watching->isChecked())
|
||||
{
|
||||
return app->twitch.server->watchingChannel;
|
||||
}
|
||||
else if (this->ui_.twitch.mentions->isChecked())
|
||||
{
|
||||
return app->twitch.server->mentionsChannel;
|
||||
}
|
||||
else if (this->ui_.twitch.whispers->isChecked())
|
||||
{
|
||||
return app->twitch.server->whispersChannel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this->selectedChannel_;
|
||||
}
|
||||
|
||||
bool SelectChannelDialog::hasSeletedChannel() const
|
||||
{
|
||||
return this->hasSelectedChannel_;
|
||||
}
|
||||
|
||||
bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched,
|
||||
QEvent *event)
|
||||
{
|
||||
auto *widget = (QWidget *)watched;
|
||||
|
||||
if (event->type() == QEvent::FocusIn)
|
||||
{
|
||||
widget->grabKeyboard();
|
||||
|
||||
auto *radio = dynamic_cast<QRadioButton *>(watched);
|
||||
if (radio)
|
||||
{
|
||||
radio->setChecked(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (event->type() == QEvent::FocusOut)
|
||||
{
|
||||
widget->releaseKeyboard();
|
||||
return false;
|
||||
}
|
||||
else if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *event_key = static_cast<QKeyEvent *>(event);
|
||||
if ((event_key->key() == Qt::Key_Tab ||
|
||||
event_key->key() == Qt::Key_Down) &&
|
||||
event_key->modifiers() == Qt::NoModifier)
|
||||
{
|
||||
if (widget == this->dialog->ui_.twitch.channelName)
|
||||
{
|
||||
this->dialog->ui_.twitch.whispers->setFocus();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
widget->nextInFocusChain()->setFocus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (((event_key->key() == Qt::Key_Tab ||
|
||||
event_key->key() == Qt::Key_Backtab) &&
|
||||
event_key->modifiers() == Qt::ShiftModifier) ||
|
||||
((event_key->key() == Qt::Key_Up) &&
|
||||
event_key->modifiers() == Qt::NoModifier))
|
||||
{
|
||||
if (widget == this->dialog->ui_.twitch.channelName)
|
||||
{
|
||||
this->dialog->ui_.twitch.watching->setFocus();
|
||||
return true;
|
||||
}
|
||||
else if (widget == this->dialog->ui_.twitch.whispers)
|
||||
{
|
||||
this->dialog->ui_.twitch.channel->setFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
widget->previousInFocusChain()->setFocus();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (event->type() == QEvent::KeyRelease)
|
||||
{
|
||||
QKeyEvent *event_key = static_cast<QKeyEvent *>(event);
|
||||
if ((event_key->key() == Qt::Key_Backtab ||
|
||||
event_key->key() == Qt::Key_Down) &&
|
||||
event_key->modifiers() == Qt::NoModifier)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SelectChannelDialog::closeEvent(QCloseEvent *)
|
||||
{
|
||||
this->closed.invoke();
|
||||
}
|
||||
|
||||
void SelectChannelDialog::themeChangedEvent()
|
||||
{
|
||||
BaseWindow::themeChangedEvent();
|
||||
|
||||
if (this->theme->isLightTheme())
|
||||
{
|
||||
this->setStyleSheet(
|
||||
"QRadioButton { color: #000 } QLabel { color: #000 }");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setStyleSheet(
|
||||
"QRadioButton { color: #fff } QLabel { color: #fff }");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "SelectChannelDialog.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "providers/twitch/TwitchServer.hpp"
|
||||
#include "singletons/Theme.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/Notebook.hpp"
|
||||
#include "widgets/helper/NotebookTab.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#define TAB_TWITCH 0
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
SelectChannelDialog::SelectChannelDialog(QWidget *parent)
|
||||
: BaseWindow(parent, BaseWindow::EnableCustomFrame)
|
||||
, selectedChannel_(Channel::getEmpty())
|
||||
{
|
||||
this->setWindowTitle("Select a channel to join");
|
||||
|
||||
this->tabFilter_.dialog = this;
|
||||
|
||||
LayoutCreator<QWidget> layoutWidget(this->getLayoutContainer());
|
||||
auto layout = layoutWidget.setLayoutType<QVBoxLayout>().withoutMargin();
|
||||
auto notebook = layout.emplace<Notebook>(this).assign(&this->ui_.notebook);
|
||||
|
||||
// twitch
|
||||
{
|
||||
LayoutCreator<QWidget> obj(new QWidget());
|
||||
auto vbox = obj.setLayoutType<QVBoxLayout>();
|
||||
|
||||
// channel_btn
|
||||
auto channel_btn = vbox.emplace<QRadioButton>("Channel").assign(
|
||||
&this->ui_.twitch.channel);
|
||||
auto channel_lbl =
|
||||
vbox.emplace<QLabel>("Join a twitch channel by its name.").hidden();
|
||||
channel_lbl->setWordWrap(true);
|
||||
auto channel_edit = vbox.emplace<QLineEdit>().hidden().assign(
|
||||
&this->ui_.twitch.channelName);
|
||||
|
||||
QObject::connect(channel_btn.getElement(), &QRadioButton::toggled,
|
||||
[=](bool enabled) mutable {
|
||||
if (enabled)
|
||||
{
|
||||
channel_edit->setFocus();
|
||||
channel_edit->setSelection(
|
||||
0, channel_edit->text().length());
|
||||
}
|
||||
|
||||
channel_edit->setVisible(enabled);
|
||||
channel_lbl->setVisible(enabled);
|
||||
});
|
||||
|
||||
channel_btn->installEventFilter(&this->tabFilter_);
|
||||
channel_edit->installEventFilter(&this->tabFilter_);
|
||||
|
||||
// whispers_btn
|
||||
auto whispers_btn = vbox.emplace<QRadioButton>("Whispers")
|
||||
.assign(&this->ui_.twitch.whispers);
|
||||
auto whispers_lbl =
|
||||
vbox.emplace<QLabel>("Shows the whispers that you receive while "
|
||||
"chatterino is running.")
|
||||
.hidden();
|
||||
|
||||
whispers_lbl->setWordWrap(true);
|
||||
whispers_btn->installEventFilter(&this->tabFilter_);
|
||||
|
||||
QObject::connect(
|
||||
whispers_btn.getElement(), &QRadioButton::toggled,
|
||||
[=](bool enabled) mutable { whispers_lbl->setVisible(enabled); });
|
||||
|
||||
// mentions_btn
|
||||
auto mentions_btn = vbox.emplace<QRadioButton>("Mentions")
|
||||
.assign(&this->ui_.twitch.mentions);
|
||||
auto mentions_lbl =
|
||||
vbox.emplace<QLabel>("Shows all the messages that highlight you "
|
||||
"from any channel.")
|
||||
.hidden();
|
||||
|
||||
mentions_lbl->setWordWrap(true);
|
||||
mentions_btn->installEventFilter(&this->tabFilter_);
|
||||
|
||||
QObject::connect(
|
||||
mentions_btn.getElement(), &QRadioButton::toggled,
|
||||
[=](bool enabled) mutable { mentions_lbl->setVisible(enabled); });
|
||||
|
||||
// watching_btn
|
||||
auto watching_btn = vbox.emplace<QRadioButton>("Watching")
|
||||
.assign(&this->ui_.twitch.watching);
|
||||
auto watching_lbl =
|
||||
vbox.emplace<QLabel>("Requires the chatterino browser extension.")
|
||||
.hidden();
|
||||
|
||||
watching_lbl->setWordWrap(true);
|
||||
watching_btn->installEventFilter(&this->tabFilter_);
|
||||
|
||||
QObject::connect(
|
||||
watching_btn.getElement(), &QRadioButton::toggled,
|
||||
[=](bool enabled) mutable { watching_lbl->setVisible(enabled); });
|
||||
|
||||
vbox->addStretch(1);
|
||||
|
||||
// tabbing order
|
||||
QWidget::setTabOrder(watching_btn.getElement(),
|
||||
channel_btn.getElement());
|
||||
QWidget::setTabOrder(channel_btn.getElement(),
|
||||
whispers_btn.getElement());
|
||||
QWidget::setTabOrder(whispers_btn.getElement(),
|
||||
mentions_btn.getElement());
|
||||
QWidget::setTabOrder(mentions_btn.getElement(),
|
||||
watching_btn.getElement());
|
||||
|
||||
// tab
|
||||
auto tab = notebook->addPage(obj.getElement());
|
||||
tab->setCustomTitle("Twitch");
|
||||
}
|
||||
|
||||
// irc
|
||||
/*
|
||||
{
|
||||
LayoutCreator<QWidget> obj(new QWidget());
|
||||
auto vbox = obj.setLayoutType<QVBoxLayout>();
|
||||
auto form = vbox.emplace<QFormLayout>();
|
||||
|
||||
form->addRow(new QLabel("User name:"), new QLineEdit());
|
||||
form->addRow(new QLabel("First nick choice:"), new QLineEdit());
|
||||
form->addRow(new QLabel("Second nick choice:"), new QLineEdit());
|
||||
form->addRow(new QLabel("Third nick choice:"), new QLineEdit());
|
||||
|
||||
auto tab = notebook->addPage(obj.getElement());
|
||||
tab->setCustomTitle("Irc");
|
||||
}
|
||||
*/
|
||||
|
||||
layout->setStretchFactor(notebook.getElement(), 1);
|
||||
|
||||
auto buttons =
|
||||
layout.emplace<QHBoxLayout>().emplace<QDialogButtonBox>(this);
|
||||
{
|
||||
auto *button_ok = buttons->addButton(QDialogButtonBox::Ok);
|
||||
QObject::connect(button_ok, &QPushButton::clicked,
|
||||
[=](bool) { this->ok(); });
|
||||
auto *button_cancel = buttons->addButton(QDialogButtonBox::Cancel);
|
||||
QObject::connect(button_cancel, &QAbstractButton::clicked,
|
||||
[=](bool) { this->close(); });
|
||||
}
|
||||
|
||||
this->setScaleIndependantSize(300, 310);
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.channel->setFocus();
|
||||
|
||||
// Shortcuts
|
||||
auto *shortcut_ok = new QShortcut(QKeySequence("Return"), this);
|
||||
QObject::connect(shortcut_ok, &QShortcut::activated, [=] { this->ok(); });
|
||||
auto *shortcut_cancel = new QShortcut(QKeySequence("Esc"), this);
|
||||
QObject::connect(shortcut_cancel, &QShortcut::activated,
|
||||
[=] { this->close(); });
|
||||
}
|
||||
|
||||
void SelectChannelDialog::ok()
|
||||
{
|
||||
this->hasSelectedChannel_ = true;
|
||||
this->close();
|
||||
}
|
||||
|
||||
void SelectChannelDialog::setSelectedChannel(IndirectChannel _channel)
|
||||
{
|
||||
auto channel = _channel.get();
|
||||
|
||||
assert(channel);
|
||||
|
||||
this->selectedChannel_ = channel;
|
||||
|
||||
switch (_channel.getType())
|
||||
{
|
||||
case Channel::Type::Twitch:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.channel->setFocus();
|
||||
this->ui_.twitch.channelName->setText(channel->getName());
|
||||
}
|
||||
break;
|
||||
case Channel::Type::TwitchWatching:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.watching->setFocus();
|
||||
}
|
||||
break;
|
||||
case Channel::Type::TwitchMentions:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.mentions->setFocus();
|
||||
}
|
||||
break;
|
||||
case Channel::Type::TwitchWhispers:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.whispers->setFocus();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.channel->setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
this->hasSelectedChannel_ = false;
|
||||
}
|
||||
|
||||
IndirectChannel SelectChannelDialog::getSelectedChannel() const
|
||||
{
|
||||
if (!this->hasSelectedChannel_)
|
||||
{
|
||||
return this->selectedChannel_;
|
||||
}
|
||||
|
||||
auto app = getApp();
|
||||
|
||||
switch (this->ui_.notebook->getSelectedIndex())
|
||||
{
|
||||
case TAB_TWITCH:
|
||||
{
|
||||
if (this->ui_.twitch.channel->isChecked())
|
||||
{
|
||||
return app->twitch.server->getOrAddChannel(
|
||||
this->ui_.twitch.channelName->text().trimmed());
|
||||
}
|
||||
else if (this->ui_.twitch.watching->isChecked())
|
||||
{
|
||||
return app->twitch.server->watchingChannel;
|
||||
}
|
||||
else if (this->ui_.twitch.mentions->isChecked())
|
||||
{
|
||||
return app->twitch.server->mentionsChannel;
|
||||
}
|
||||
else if (this->ui_.twitch.whispers->isChecked())
|
||||
{
|
||||
return app->twitch.server->whispersChannel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this->selectedChannel_;
|
||||
}
|
||||
|
||||
bool SelectChannelDialog::hasSeletedChannel() const
|
||||
{
|
||||
return this->hasSelectedChannel_;
|
||||
}
|
||||
|
||||
bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched,
|
||||
QEvent *event)
|
||||
{
|
||||
auto *widget = (QWidget *)watched;
|
||||
|
||||
if (event->type() == QEvent::FocusIn)
|
||||
{
|
||||
widget->grabKeyboard();
|
||||
|
||||
auto *radio = dynamic_cast<QRadioButton *>(watched);
|
||||
if (radio)
|
||||
{
|
||||
radio->setChecked(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (event->type() == QEvent::FocusOut)
|
||||
{
|
||||
widget->releaseKeyboard();
|
||||
return false;
|
||||
}
|
||||
else if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *event_key = static_cast<QKeyEvent *>(event);
|
||||
if ((event_key->key() == Qt::Key_Tab ||
|
||||
event_key->key() == Qt::Key_Down) &&
|
||||
event_key->modifiers() == Qt::NoModifier)
|
||||
{
|
||||
if (widget == this->dialog->ui_.twitch.channelName)
|
||||
{
|
||||
this->dialog->ui_.twitch.whispers->setFocus();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
widget->nextInFocusChain()->setFocus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (((event_key->key() == Qt::Key_Tab ||
|
||||
event_key->key() == Qt::Key_Backtab) &&
|
||||
event_key->modifiers() == Qt::ShiftModifier) ||
|
||||
((event_key->key() == Qt::Key_Up) &&
|
||||
event_key->modifiers() == Qt::NoModifier))
|
||||
{
|
||||
if (widget == this->dialog->ui_.twitch.channelName)
|
||||
{
|
||||
this->dialog->ui_.twitch.watching->setFocus();
|
||||
return true;
|
||||
}
|
||||
else if (widget == this->dialog->ui_.twitch.whispers)
|
||||
{
|
||||
this->dialog->ui_.twitch.channel->setFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
widget->previousInFocusChain()->setFocus();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (event->type() == QEvent::KeyRelease)
|
||||
{
|
||||
QKeyEvent *event_key = static_cast<QKeyEvent *>(event);
|
||||
if ((event_key->key() == Qt::Key_Backtab ||
|
||||
event_key->key() == Qt::Key_Down) &&
|
||||
event_key->modifiers() == Qt::NoModifier)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SelectChannelDialog::closeEvent(QCloseEvent *)
|
||||
{
|
||||
this->closed.invoke();
|
||||
}
|
||||
|
||||
void SelectChannelDialog::themeChangedEvent()
|
||||
{
|
||||
BaseWindow::themeChangedEvent();
|
||||
|
||||
if (this->theme->isLightTheme())
|
||||
{
|
||||
this->setStyleSheet(
|
||||
"QRadioButton { color: #000 } QLabel { color: #000 }");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setStyleSheet(
|
||||
"QRadioButton { color: #fff } QLabel { color: #fff }");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "common/Channel.hpp"
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QRadioButton>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Notebook;
|
||||
|
||||
class SelectChannelDialog final : public BaseWindow
|
||||
{
|
||||
public:
|
||||
SelectChannelDialog(QWidget *parent = nullptr);
|
||||
|
||||
void setSelectedChannel(IndirectChannel selectedChannel_);
|
||||
IndirectChannel getSelectedChannel() const;
|
||||
bool hasSeletedChannel() const;
|
||||
|
||||
pajlada::Signals::NoArgSignal closed;
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *) override;
|
||||
virtual void themeChangedEvent() override;
|
||||
|
||||
private:
|
||||
class EventFilter : public QObject
|
||||
{
|
||||
public:
|
||||
SelectChannelDialog *dialog;
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
};
|
||||
|
||||
struct {
|
||||
Notebook *notebook;
|
||||
struct {
|
||||
QRadioButton *channel;
|
||||
QLineEdit *channelName;
|
||||
QRadioButton *whispers;
|
||||
QRadioButton *mentions;
|
||||
QRadioButton *watching;
|
||||
} twitch;
|
||||
} ui_;
|
||||
|
||||
EventFilter tabFilter_;
|
||||
|
||||
ChannelPtr selectedChannel_;
|
||||
bool hasSelectedChannel_ = false;
|
||||
|
||||
void ok();
|
||||
friend class EventFilter;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "common/Channel.hpp"
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QRadioButton>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Notebook;
|
||||
|
||||
class SelectChannelDialog final : public BaseWindow
|
||||
{
|
||||
public:
|
||||
SelectChannelDialog(QWidget *parent = nullptr);
|
||||
|
||||
void setSelectedChannel(IndirectChannel selectedChannel_);
|
||||
IndirectChannel getSelectedChannel() const;
|
||||
bool hasSeletedChannel() const;
|
||||
|
||||
pajlada::Signals::NoArgSignal closed;
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *) override;
|
||||
virtual void themeChangedEvent() override;
|
||||
|
||||
private:
|
||||
class EventFilter : public QObject
|
||||
{
|
||||
public:
|
||||
SelectChannelDialog *dialog;
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
};
|
||||
|
||||
struct {
|
||||
Notebook *notebook;
|
||||
struct {
|
||||
QRadioButton *channel;
|
||||
QLineEdit *channelName;
|
||||
QRadioButton *whispers;
|
||||
QRadioButton *mentions;
|
||||
QRadioButton *watching;
|
||||
} twitch;
|
||||
} ui_;
|
||||
|
||||
EventFilter tabFilter_;
|
||||
|
||||
ChannelPtr selectedChannel_;
|
||||
bool hasSelectedChannel_ = false;
|
||||
|
||||
void ok();
|
||||
friend class EventFilter;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
#include "UpdateDialog.hpp"
|
||||
|
||||
#include "singletons/Updates.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/Label.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
UpdateDialog::UpdateDialog()
|
||||
: BaseWindow(nullptr,
|
||||
BaseWindow::Flags(BaseWindow::Frameless | BaseWindow::TopMost |
|
||||
BaseWindow::EnableCustomFrame))
|
||||
{
|
||||
auto layout =
|
||||
LayoutCreator<UpdateDialog>(this).setLayoutType<QVBoxLayout>();
|
||||
|
||||
layout.emplace<Label>("You shouldn't be seeing this dialog.")
|
||||
.assign(&this->ui_.label);
|
||||
|
||||
auto buttons = layout.emplace<QDialogButtonBox>();
|
||||
auto install = buttons->addButton("Install", QDialogButtonBox::AcceptRole);
|
||||
this->ui_.installButton = install;
|
||||
auto dismiss = buttons->addButton("Dismiss", QDialogButtonBox::RejectRole);
|
||||
|
||||
QObject::connect(install, &QPushButton::clicked, this, [this] {
|
||||
Updates::getInstance().installUpdates();
|
||||
this->close();
|
||||
});
|
||||
QObject::connect(dismiss, &QPushButton::clicked, this, [this] {
|
||||
this->buttonClicked.invoke(Dismiss);
|
||||
this->close();
|
||||
});
|
||||
|
||||
this->updateStatusChanged(Updates::getInstance().getStatus());
|
||||
this->connections_.managedConnect(
|
||||
Updates::getInstance().statusUpdated,
|
||||
[this](auto status) { this->updateStatusChanged(status); });
|
||||
|
||||
this->setScaleIndependantHeight(150);
|
||||
}
|
||||
|
||||
void UpdateDialog::updateStatusChanged(Updates::Status status)
|
||||
{
|
||||
this->ui_.installButton->setVisible(status == Updates::UpdateAvailable);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case Updates::UpdateAvailable:
|
||||
{
|
||||
this->ui_.label->setText(
|
||||
QString("An update (%1) is available.\n\nDo you want to "
|
||||
"download and install it?")
|
||||
.arg(Updates::getInstance().getOnlineVersion()));
|
||||
this->updateGeometry();
|
||||
}
|
||||
break;
|
||||
|
||||
case Updates::SearchFailed:
|
||||
{
|
||||
this->ui_.label->setText("Failed to load version information.");
|
||||
}
|
||||
break;
|
||||
|
||||
case Updates::Downloading:
|
||||
{
|
||||
this->ui_.label->setText(
|
||||
"Downloading updates.\n\nChatterino will restart "
|
||||
"automatically when the download is done.");
|
||||
}
|
||||
break;
|
||||
|
||||
case Updates::DownloadFailed:
|
||||
{
|
||||
this->ui_.label->setText("Failed to download the update.");
|
||||
}
|
||||
break;
|
||||
|
||||
case Updates::WriteFileFailed:
|
||||
{
|
||||
this->ui_.label->setText("Failed to save the update to disk.");
|
||||
}
|
||||
break;
|
||||
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "UpdateDialog.hpp"
|
||||
|
||||
#include "singletons/Updates.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/Label.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
UpdateDialog::UpdateDialog()
|
||||
: BaseWindow(nullptr,
|
||||
BaseWindow::Flags(BaseWindow::Frameless | BaseWindow::TopMost |
|
||||
BaseWindow::EnableCustomFrame))
|
||||
{
|
||||
auto layout =
|
||||
LayoutCreator<UpdateDialog>(this).setLayoutType<QVBoxLayout>();
|
||||
|
||||
layout.emplace<Label>("You shouldn't be seeing this dialog.")
|
||||
.assign(&this->ui_.label);
|
||||
|
||||
auto buttons = layout.emplace<QDialogButtonBox>();
|
||||
auto install = buttons->addButton("Install", QDialogButtonBox::AcceptRole);
|
||||
this->ui_.installButton = install;
|
||||
auto dismiss = buttons->addButton("Dismiss", QDialogButtonBox::RejectRole);
|
||||
|
||||
QObject::connect(install, &QPushButton::clicked, this, [this] {
|
||||
Updates::getInstance().installUpdates();
|
||||
this->close();
|
||||
});
|
||||
QObject::connect(dismiss, &QPushButton::clicked, this, [this] {
|
||||
this->buttonClicked.invoke(Dismiss);
|
||||
this->close();
|
||||
});
|
||||
|
||||
this->updateStatusChanged(Updates::getInstance().getStatus());
|
||||
this->connections_.managedConnect(
|
||||
Updates::getInstance().statusUpdated,
|
||||
[this](auto status) { this->updateStatusChanged(status); });
|
||||
|
||||
this->setScaleIndependantHeight(150);
|
||||
}
|
||||
|
||||
void UpdateDialog::updateStatusChanged(Updates::Status status)
|
||||
{
|
||||
this->ui_.installButton->setVisible(status == Updates::UpdateAvailable);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case Updates::UpdateAvailable:
|
||||
{
|
||||
this->ui_.label->setText(
|
||||
QString("An update (%1) is available.\n\nDo you want to "
|
||||
"download and install it?")
|
||||
.arg(Updates::getInstance().getOnlineVersion()));
|
||||
this->updateGeometry();
|
||||
}
|
||||
break;
|
||||
|
||||
case Updates::SearchFailed:
|
||||
{
|
||||
this->ui_.label->setText("Failed to load version information.");
|
||||
}
|
||||
break;
|
||||
|
||||
case Updates::Downloading:
|
||||
{
|
||||
this->ui_.label->setText(
|
||||
"Downloading updates.\n\nChatterino will restart "
|
||||
"automatically when the download is done.");
|
||||
}
|
||||
break;
|
||||
|
||||
case Updates::DownloadFailed:
|
||||
{
|
||||
this->ui_.label->setText("Failed to download the update.");
|
||||
}
|
||||
break;
|
||||
|
||||
case Updates::WriteFileFailed:
|
||||
{
|
||||
this->ui_.label->setText("Failed to save the update to disk.");
|
||||
}
|
||||
break;
|
||||
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "pajlada/signals/signalholder.hpp"
|
||||
#include "singletons/Updates.hpp"
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
#include "widgets/Label.hpp"
|
||||
|
||||
class QPushButton;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class UpdateDialog : public BaseWindow
|
||||
{
|
||||
public:
|
||||
enum Button { Dismiss, Install };
|
||||
|
||||
UpdateDialog();
|
||||
|
||||
pajlada::Signals::Signal<Button> buttonClicked;
|
||||
|
||||
private:
|
||||
void updateStatusChanged(Updates::Status status);
|
||||
|
||||
struct {
|
||||
Label *label = nullptr;
|
||||
QPushButton *installButton = nullptr;
|
||||
} ui_;
|
||||
|
||||
pajlada::Signals::SignalHolder connections_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "pajlada/signals/signalholder.hpp"
|
||||
#include "singletons/Updates.hpp"
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
#include "widgets/Label.hpp"
|
||||
|
||||
class QPushButton;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class UpdateDialog : public BaseWindow
|
||||
{
|
||||
public:
|
||||
enum Button { Dismiss, Install };
|
||||
|
||||
UpdateDialog();
|
||||
|
||||
pajlada::Signals::Signal<Button> buttonClicked;
|
||||
|
||||
private:
|
||||
void updateStatusChanged(Updates::Status status);
|
||||
|
||||
struct {
|
||||
Label *label = nullptr;
|
||||
QPushButton *installButton = nullptr;
|
||||
} ui_;
|
||||
|
||||
pajlada::Signals::SignalHolder connections_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,73 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
class QCheckBox;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Channel;
|
||||
using ChannelPtr = std::shared_ptr<Channel>;
|
||||
class Label;
|
||||
|
||||
class UserInfoPopup final : public BaseWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UserInfoPopup();
|
||||
|
||||
void setData(const QString &name, const ChannelPtr &channel);
|
||||
|
||||
protected:
|
||||
virtual void themeChangedEvent() override;
|
||||
virtual void scaleChangedEvent(float scale) override;
|
||||
|
||||
private:
|
||||
void installEvents();
|
||||
void updateUserData();
|
||||
|
||||
void loadAvatar(const QUrl &url);
|
||||
bool isMod_;
|
||||
bool isBroadcaster_;
|
||||
|
||||
QString userName_;
|
||||
QString userId_;
|
||||
ChannelPtr channel_;
|
||||
|
||||
pajlada::Signals::NoArgSignal userStateChanged_;
|
||||
|
||||
std::shared_ptr<bool> hack_;
|
||||
|
||||
struct {
|
||||
Button *avatarButton = nullptr;
|
||||
// RippleEffectLabel2 *viewLogs = nullptr;
|
||||
|
||||
Label *nameLabel = nullptr;
|
||||
Label *viewCountLabel = nullptr;
|
||||
Label *followerCountLabel = nullptr;
|
||||
Label *createdDateLabel = nullptr;
|
||||
Label *userIDLabel = nullptr;
|
||||
|
||||
QCheckBox *follow = nullptr;
|
||||
QCheckBox *ignore = nullptr;
|
||||
QCheckBox *ignoreHighlights = nullptr;
|
||||
} ui_;
|
||||
|
||||
class TimeoutWidget : public BaseWidget
|
||||
{
|
||||
public:
|
||||
enum Action { Ban, Unban, Timeout };
|
||||
|
||||
TimeoutWidget();
|
||||
|
||||
pajlada::Signals::Signal<std::pair<Action, int>> buttonClicked;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
class QCheckBox;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Channel;
|
||||
using ChannelPtr = std::shared_ptr<Channel>;
|
||||
class Label;
|
||||
|
||||
class UserInfoPopup final : public BaseWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UserInfoPopup();
|
||||
|
||||
void setData(const QString &name, const ChannelPtr &channel);
|
||||
|
||||
protected:
|
||||
virtual void themeChangedEvent() override;
|
||||
virtual void scaleChangedEvent(float scale) override;
|
||||
|
||||
private:
|
||||
void installEvents();
|
||||
void updateUserData();
|
||||
|
||||
void loadAvatar(const QUrl &url);
|
||||
bool isMod_;
|
||||
bool isBroadcaster_;
|
||||
|
||||
QString userName_;
|
||||
QString userId_;
|
||||
ChannelPtr channel_;
|
||||
|
||||
pajlada::Signals::NoArgSignal userStateChanged_;
|
||||
|
||||
std::shared_ptr<bool> hack_;
|
||||
|
||||
struct {
|
||||
Button *avatarButton = nullptr;
|
||||
// RippleEffectLabel2 *viewLogs = nullptr;
|
||||
|
||||
Label *nameLabel = nullptr;
|
||||
Label *viewCountLabel = nullptr;
|
||||
Label *followerCountLabel = nullptr;
|
||||
Label *createdDateLabel = nullptr;
|
||||
Label *userIDLabel = nullptr;
|
||||
|
||||
QCheckBox *follow = nullptr;
|
||||
QCheckBox *ignore = nullptr;
|
||||
QCheckBox *ignoreHighlights = nullptr;
|
||||
} ui_;
|
||||
|
||||
class TimeoutWidget : public BaseWidget
|
||||
{
|
||||
public:
|
||||
enum Action { Ban, Unban, Timeout };
|
||||
|
||||
TimeoutWidget();
|
||||
|
||||
pajlada::Signals::Signal<std::pair<Action, int>> buttonClicked;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "WelcomeDialog.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
WelcomeDialog::WelcomeDialog()
|
||||
: BaseWindow(nullptr, BaseWindow::EnableCustomFrame)
|
||||
{
|
||||
this->setWindowTitle("Chatterino quick setup");
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "WelcomeDialog.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
WelcomeDialog::WelcomeDialog()
|
||||
: BaseWindow(nullptr, BaseWindow::EnableCustomFrame)
|
||||
{
|
||||
this->setWindowTitle("Chatterino quick setup");
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class WelcomeDialog : public BaseWindow
|
||||
{
|
||||
public:
|
||||
WelcomeDialog();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class WelcomeDialog : public BaseWindow
|
||||
{
|
||||
public:
|
||||
WelcomeDialog();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
#include "ComboBoxItemDelegate.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
ComboBoxItemDelegate::ComboBoxItemDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ComboBoxItemDelegate::~ComboBoxItemDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
QWidget *ComboBoxItemDelegate::createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QVariant data = index.data(Qt::UserRole + 1);
|
||||
|
||||
if (data.type() != QVariant::StringList)
|
||||
{
|
||||
return QStyledItemDelegate::createEditor(parent, option, index);
|
||||
}
|
||||
|
||||
QComboBox *combo = new QComboBox(parent);
|
||||
combo->addItems(data.toStringList());
|
||||
return combo;
|
||||
}
|
||||
|
||||
void ComboBoxItemDelegate::setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (QComboBox *cb = qobject_cast<QComboBox *>(editor))
|
||||
{
|
||||
// get the index of the text in the combobox that matches the current
|
||||
// value of the itenm
|
||||
QString currentText = index.data(Qt::EditRole).toString();
|
||||
int cbIndex = cb->findText(currentText);
|
||||
|
||||
// if it is valid, adjust the combobox
|
||||
if (cbIndex >= 0)
|
||||
{
|
||||
cb->setCurrentIndex(cbIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBoxItemDelegate::setModelData(QWidget *editor,
|
||||
QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (QComboBox *cb = qobject_cast<QComboBox *>(editor))
|
||||
// save the current text of the combo box as the current value of the
|
||||
// item
|
||||
model->setData(index, cb->currentText(), Qt::EditRole);
|
||||
else
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
}
|
||||
} // namespace chatterino
|
||||
#include "ComboBoxItemDelegate.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
ComboBoxItemDelegate::ComboBoxItemDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ComboBoxItemDelegate::~ComboBoxItemDelegate()
|
||||
{
|
||||
}
|
||||
|
||||
QWidget *ComboBoxItemDelegate::createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QVariant data = index.data(Qt::UserRole + 1);
|
||||
|
||||
if (data.type() != QVariant::StringList)
|
||||
{
|
||||
return QStyledItemDelegate::createEditor(parent, option, index);
|
||||
}
|
||||
|
||||
QComboBox *combo = new QComboBox(parent);
|
||||
combo->addItems(data.toStringList());
|
||||
return combo;
|
||||
}
|
||||
|
||||
void ComboBoxItemDelegate::setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (QComboBox *cb = qobject_cast<QComboBox *>(editor))
|
||||
{
|
||||
// get the index of the text in the combobox that matches the current
|
||||
// value of the itenm
|
||||
QString currentText = index.data(Qt::EditRole).toString();
|
||||
int cbIndex = cb->findText(currentText);
|
||||
|
||||
// if it is valid, adjust the combobox
|
||||
if (cbIndex >= 0)
|
||||
{
|
||||
cb->setCurrentIndex(cbIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBoxItemDelegate::setModelData(QWidget *editor,
|
||||
QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (QComboBox *cb = qobject_cast<QComboBox *>(editor))
|
||||
// save the current text of the combo box as the current value of the
|
||||
// item
|
||||
model->setData(index, cb->currentText(), Qt::EditRole);
|
||||
else
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
}
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
// stolen from https://wiki.qt.io/Combo_Boxes_in_Item_Views
|
||||
|
||||
class ComboBoxItemDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ComboBoxItemDelegate(QObject *parent = nullptr);
|
||||
~ComboBoxItemDelegate();
|
||||
|
||||
virtual QWidget *createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const;
|
||||
virtual void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
// stolen from https://wiki.qt.io/Combo_Boxes_in_Item_Views
|
||||
|
||||
class ComboBoxItemDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ComboBoxItemDelegate(QObject *parent = nullptr);
|
||||
~ComboBoxItemDelegate();
|
||||
|
||||
virtual QWidget *createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const;
|
||||
virtual void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
#include "DebugPopup.hpp"
|
||||
|
||||
#include "util/DebugCount.hpp"
|
||||
|
||||
#include <QFontDatabase>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QTimer>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
DebugPopup::DebugPopup()
|
||||
{
|
||||
auto *layout = new QHBoxLayout(this);
|
||||
auto *text = new QLabel(this);
|
||||
auto *timer = new QTimer(this);
|
||||
|
||||
timer->setInterval(300);
|
||||
QObject::connect(timer, &QTimer::timeout,
|
||||
[text] { text->setText(DebugCount::getDebugText()); });
|
||||
timer->start();
|
||||
|
||||
text->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
|
||||
layout->addWidget(text);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "DebugPopup.hpp"
|
||||
|
||||
#include "util/DebugCount.hpp"
|
||||
|
||||
#include <QFontDatabase>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QTimer>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
DebugPopup::DebugPopup()
|
||||
{
|
||||
auto *layout = new QHBoxLayout(this);
|
||||
auto *text = new QLabel(this);
|
||||
auto *timer = new QTimer(this);
|
||||
|
||||
timer->setInterval(300);
|
||||
QObject::connect(timer, &QTimer::timeout,
|
||||
[text] { text->setText(DebugCount::getDebugText()); });
|
||||
timer->start();
|
||||
|
||||
text->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
|
||||
layout->addWidget(text);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class DebugPopup : public QWidget
|
||||
{
|
||||
public:
|
||||
DebugPopup();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class DebugPopup : public QWidget
|
||||
{
|
||||
public:
|
||||
DebugPopup();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
#include "EditableModelView.hpp"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QPushButton>
|
||||
#include <QTableView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
EditableModelView::EditableModelView(QAbstractTableModel *model)
|
||||
: tableView_(new QTableView(this))
|
||||
, model_(model)
|
||||
{
|
||||
this->model_->setParent(this);
|
||||
this->tableView_->setModel(model);
|
||||
this->tableView_->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
this->tableView_->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
this->tableView_->verticalHeader()->hide();
|
||||
|
||||
// create layout
|
||||
QVBoxLayout *vbox = new QVBoxLayout(this);
|
||||
vbox->setMargin(0);
|
||||
|
||||
// create button layout
|
||||
QHBoxLayout *buttons = new QHBoxLayout(this);
|
||||
this->buttons_ = buttons;
|
||||
vbox->addLayout(buttons);
|
||||
|
||||
// add
|
||||
QPushButton *add = new QPushButton("Add");
|
||||
buttons->addWidget(add);
|
||||
QObject::connect(add, &QPushButton::clicked,
|
||||
[this] { this->addButtonPressed.invoke(); });
|
||||
|
||||
// remove
|
||||
QPushButton *remove = new QPushButton("Remove");
|
||||
buttons->addWidget(remove);
|
||||
QObject::connect(remove, &QPushButton::clicked, [this] {
|
||||
QModelIndexList list;
|
||||
while ((list = this->getTableView()->selectionModel()->selectedRows(0))
|
||||
.length() > 0)
|
||||
{
|
||||
model_->removeRow(list[0].row());
|
||||
}
|
||||
});
|
||||
|
||||
buttons->addStretch();
|
||||
|
||||
// add tableview
|
||||
vbox->addWidget(this->tableView_);
|
||||
|
||||
// finish button layout
|
||||
buttons->addStretch(1);
|
||||
}
|
||||
|
||||
void EditableModelView::setTitles(std::initializer_list<QString> titles)
|
||||
{
|
||||
int i = 0;
|
||||
for (const QString &title : titles)
|
||||
{
|
||||
if (this->model_->columnCount() == i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
this->model_->setHeaderData(i++, Qt::Horizontal, title,
|
||||
Qt::DisplayRole);
|
||||
}
|
||||
}
|
||||
|
||||
QTableView *EditableModelView::getTableView()
|
||||
{
|
||||
return this->tableView_;
|
||||
}
|
||||
|
||||
QAbstractTableModel *EditableModelView::getModel()
|
||||
{
|
||||
return this->model_;
|
||||
}
|
||||
|
||||
void EditableModelView::addCustomButton(QWidget *widget)
|
||||
{
|
||||
this->buttons_->addWidget(widget);
|
||||
}
|
||||
|
||||
void EditableModelView::addRegexHelpLink()
|
||||
{
|
||||
auto regexHelpLabel =
|
||||
new QLabel("<a href='https://chatterino.com/help/regex'><span "
|
||||
"style='color:#99f'>regex info</span></a>");
|
||||
regexHelpLabel->setOpenExternalLinks(true);
|
||||
this->addCustomButton(regexHelpLabel);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "EditableModelView.hpp"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QPushButton>
|
||||
#include <QTableView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
EditableModelView::EditableModelView(QAbstractTableModel *model)
|
||||
: tableView_(new QTableView(this))
|
||||
, model_(model)
|
||||
{
|
||||
this->model_->setParent(this);
|
||||
this->tableView_->setModel(model);
|
||||
this->tableView_->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
this->tableView_->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
this->tableView_->verticalHeader()->hide();
|
||||
|
||||
// create layout
|
||||
QVBoxLayout *vbox = new QVBoxLayout(this);
|
||||
vbox->setMargin(0);
|
||||
|
||||
// create button layout
|
||||
QHBoxLayout *buttons = new QHBoxLayout(this);
|
||||
this->buttons_ = buttons;
|
||||
vbox->addLayout(buttons);
|
||||
|
||||
// add
|
||||
QPushButton *add = new QPushButton("Add");
|
||||
buttons->addWidget(add);
|
||||
QObject::connect(add, &QPushButton::clicked,
|
||||
[this] { this->addButtonPressed.invoke(); });
|
||||
|
||||
// remove
|
||||
QPushButton *remove = new QPushButton("Remove");
|
||||
buttons->addWidget(remove);
|
||||
QObject::connect(remove, &QPushButton::clicked, [this] {
|
||||
QModelIndexList list;
|
||||
while ((list = this->getTableView()->selectionModel()->selectedRows(0))
|
||||
.length() > 0)
|
||||
{
|
||||
model_->removeRow(list[0].row());
|
||||
}
|
||||
});
|
||||
|
||||
buttons->addStretch();
|
||||
|
||||
// add tableview
|
||||
vbox->addWidget(this->tableView_);
|
||||
|
||||
// finish button layout
|
||||
buttons->addStretch(1);
|
||||
}
|
||||
|
||||
void EditableModelView::setTitles(std::initializer_list<QString> titles)
|
||||
{
|
||||
int i = 0;
|
||||
for (const QString &title : titles)
|
||||
{
|
||||
if (this->model_->columnCount() == i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
this->model_->setHeaderData(i++, Qt::Horizontal, title,
|
||||
Qt::DisplayRole);
|
||||
}
|
||||
}
|
||||
|
||||
QTableView *EditableModelView::getTableView()
|
||||
{
|
||||
return this->tableView_;
|
||||
}
|
||||
|
||||
QAbstractTableModel *EditableModelView::getModel()
|
||||
{
|
||||
return this->model_;
|
||||
}
|
||||
|
||||
void EditableModelView::addCustomButton(QWidget *widget)
|
||||
{
|
||||
this->buttons_->addWidget(widget);
|
||||
}
|
||||
|
||||
void EditableModelView::addRegexHelpLink()
|
||||
{
|
||||
auto regexHelpLabel =
|
||||
new QLabel("<a href='https://chatterino.com/help/regex'><span "
|
||||
"style='color:#99f'>regex info</span></a>");
|
||||
regexHelpLabel->setOpenExternalLinks(true);
|
||||
this->addCustomButton(regexHelpLabel);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
class QAbstractTableModel;
|
||||
class QTableView;
|
||||
class QHBoxLayout;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class EditableModelView : public QWidget
|
||||
{
|
||||
public:
|
||||
EditableModelView(QAbstractTableModel *model);
|
||||
|
||||
void setTitles(std::initializer_list<QString> titles);
|
||||
|
||||
QTableView *getTableView();
|
||||
QAbstractTableModel *getModel();
|
||||
|
||||
pajlada::Signals::NoArgSignal addButtonPressed;
|
||||
|
||||
void addCustomButton(QWidget *widget);
|
||||
void addRegexHelpLink();
|
||||
|
||||
private:
|
||||
QTableView *tableView_{};
|
||||
QAbstractTableModel *model_{};
|
||||
QHBoxLayout *buttons_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
class QAbstractTableModel;
|
||||
class QTableView;
|
||||
class QHBoxLayout;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class EditableModelView : public QWidget
|
||||
{
|
||||
public:
|
||||
EditableModelView(QAbstractTableModel *model);
|
||||
|
||||
void setTitles(std::initializer_list<QString> titles);
|
||||
|
||||
QTableView *getTableView();
|
||||
QAbstractTableModel *getModel();
|
||||
|
||||
pajlada::Signals::NoArgSignal addButtonPressed;
|
||||
|
||||
void addCustomButton(QWidget *widget);
|
||||
void addRegexHelpLink();
|
||||
|
||||
private:
|
||||
QTableView *tableView_{};
|
||||
QAbstractTableModel *model_{};
|
||||
QHBoxLayout *buttons_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
+48
-48
@@ -1,48 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/BaseWidget.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Line : public BaseWidget
|
||||
{
|
||||
public:
|
||||
Line(bool vertical)
|
||||
: BaseWidget(nullptr)
|
||||
, vertical_(vertical)
|
||||
{
|
||||
if (this->vertical_)
|
||||
{
|
||||
this->setScaleIndependantWidth(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setScaleIndependantHeight(8);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
painter.setPen(QColor("#999"));
|
||||
|
||||
if (this->vertical_)
|
||||
{
|
||||
painter.drawLine(this->width() / 2, 0, this->width() / 2,
|
||||
this->height());
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.drawLine(0, this->height() / 2, this->width(),
|
||||
this->height() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool vertical_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/BaseWidget.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Line : public BaseWidget
|
||||
{
|
||||
public:
|
||||
Line(bool vertical)
|
||||
: BaseWidget(nullptr)
|
||||
, vertical_(vertical)
|
||||
{
|
||||
if (this->vertical_)
|
||||
{
|
||||
this->setScaleIndependantWidth(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->setScaleIndependantHeight(8);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
painter.setPen(QColor("#999"));
|
||||
|
||||
if (this->vertical_)
|
||||
{
|
||||
painter.drawLine(this->width() / 2, 0, this->width() / 2,
|
||||
this->height());
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.drawLine(0, this->height() / 2, this->width(),
|
||||
this->height() / 2);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool vertical_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
+116
-116
@@ -1,116 +1,116 @@
|
||||
#include "SearchPopup.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "common/Channel.hpp"
|
||||
#include "messages/Message.hpp"
|
||||
#include "widgets/helper/ChannelView.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace {
|
||||
ChannelPtr filter(const QString &text, const QString &channelName,
|
||||
const LimitedQueueSnapshot<MessagePtr> &snapshot)
|
||||
{
|
||||
ChannelPtr channel(new Channel(channelName, Channel::Type::None));
|
||||
|
||||
for (size_t i = 0; i < snapshot.size(); i++)
|
||||
{
|
||||
MessagePtr message = snapshot[i];
|
||||
|
||||
if (text.isEmpty() ||
|
||||
message->searchText.indexOf(text, 0, Qt::CaseInsensitive) != -1)
|
||||
{
|
||||
channel->addMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SearchPopup::SearchPopup()
|
||||
{
|
||||
this->initLayout();
|
||||
this->resize(400, 600);
|
||||
}
|
||||
|
||||
void SearchPopup::setChannel(const ChannelPtr &channel)
|
||||
{
|
||||
this->channelName_ = channel->getName();
|
||||
this->snapshot_ = channel->getMessageSnapshot();
|
||||
this->search();
|
||||
|
||||
this->updateWindowTitle();
|
||||
}
|
||||
|
||||
void SearchPopup::updateWindowTitle()
|
||||
{
|
||||
this->setWindowTitle("Searching in " + this->channelName_ + "s history");
|
||||
}
|
||||
|
||||
void SearchPopup::search()
|
||||
{
|
||||
this->channelView_->setChannel(filter(this->searchInput_->text(),
|
||||
this->channelName_, this->snapshot_));
|
||||
}
|
||||
|
||||
void SearchPopup::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Escape)
|
||||
{
|
||||
this->close();
|
||||
return;
|
||||
}
|
||||
|
||||
BaseWidget::keyPressEvent(e);
|
||||
}
|
||||
|
||||
void SearchPopup::initLayout()
|
||||
{
|
||||
// VBOX
|
||||
{
|
||||
QVBoxLayout *layout1 = new QVBoxLayout(this);
|
||||
layout1->setMargin(0);
|
||||
layout1->setSpacing(0);
|
||||
|
||||
// HBOX
|
||||
{
|
||||
QHBoxLayout *layout2 = new QHBoxLayout(this);
|
||||
layout2->setMargin(8);
|
||||
layout2->setSpacing(8);
|
||||
|
||||
// SEARCH INPUT
|
||||
{
|
||||
this->searchInput_ = new QLineEdit(this);
|
||||
layout2->addWidget(this->searchInput_);
|
||||
QObject::connect(this->searchInput_, &QLineEdit::returnPressed,
|
||||
[this] { this->search(); });
|
||||
}
|
||||
|
||||
// SEARCH BUTTON
|
||||
{
|
||||
QPushButton *searchButton = new QPushButton(this);
|
||||
searchButton->setText("Search");
|
||||
layout2->addWidget(searchButton);
|
||||
QObject::connect(searchButton, &QPushButton::clicked,
|
||||
[this] { this->search(); });
|
||||
}
|
||||
|
||||
layout1->addLayout(layout2);
|
||||
}
|
||||
|
||||
// CHANNELVIEW
|
||||
{
|
||||
this->channelView_ = new ChannelView(this);
|
||||
|
||||
layout1->addWidget(this->channelView_);
|
||||
}
|
||||
|
||||
this->setLayout(layout1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "SearchPopup.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "common/Channel.hpp"
|
||||
#include "messages/Message.hpp"
|
||||
#include "widgets/helper/ChannelView.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace {
|
||||
ChannelPtr filter(const QString &text, const QString &channelName,
|
||||
const LimitedQueueSnapshot<MessagePtr> &snapshot)
|
||||
{
|
||||
ChannelPtr channel(new Channel(channelName, Channel::Type::None));
|
||||
|
||||
for (size_t i = 0; i < snapshot.size(); i++)
|
||||
{
|
||||
MessagePtr message = snapshot[i];
|
||||
|
||||
if (text.isEmpty() ||
|
||||
message->searchText.indexOf(text, 0, Qt::CaseInsensitive) != -1)
|
||||
{
|
||||
channel->addMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SearchPopup::SearchPopup()
|
||||
{
|
||||
this->initLayout();
|
||||
this->resize(400, 600);
|
||||
}
|
||||
|
||||
void SearchPopup::setChannel(const ChannelPtr &channel)
|
||||
{
|
||||
this->channelName_ = channel->getName();
|
||||
this->snapshot_ = channel->getMessageSnapshot();
|
||||
this->search();
|
||||
|
||||
this->updateWindowTitle();
|
||||
}
|
||||
|
||||
void SearchPopup::updateWindowTitle()
|
||||
{
|
||||
this->setWindowTitle("Searching in " + this->channelName_ + "s history");
|
||||
}
|
||||
|
||||
void SearchPopup::search()
|
||||
{
|
||||
this->channelView_->setChannel(filter(this->searchInput_->text(),
|
||||
this->channelName_, this->snapshot_));
|
||||
}
|
||||
|
||||
void SearchPopup::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (e->key() == Qt::Key_Escape)
|
||||
{
|
||||
this->close();
|
||||
return;
|
||||
}
|
||||
|
||||
BaseWidget::keyPressEvent(e);
|
||||
}
|
||||
|
||||
void SearchPopup::initLayout()
|
||||
{
|
||||
// VBOX
|
||||
{
|
||||
QVBoxLayout *layout1 = new QVBoxLayout(this);
|
||||
layout1->setMargin(0);
|
||||
layout1->setSpacing(0);
|
||||
|
||||
// HBOX
|
||||
{
|
||||
QHBoxLayout *layout2 = new QHBoxLayout(this);
|
||||
layout2->setMargin(8);
|
||||
layout2->setSpacing(8);
|
||||
|
||||
// SEARCH INPUT
|
||||
{
|
||||
this->searchInput_ = new QLineEdit(this);
|
||||
layout2->addWidget(this->searchInput_);
|
||||
QObject::connect(this->searchInput_, &QLineEdit::returnPressed,
|
||||
[this] { this->search(); });
|
||||
}
|
||||
|
||||
// SEARCH BUTTON
|
||||
{
|
||||
QPushButton *searchButton = new QPushButton(this);
|
||||
searchButton->setText("Search");
|
||||
layout2->addWidget(searchButton);
|
||||
QObject::connect(searchButton, &QPushButton::clicked,
|
||||
[this] { this->search(); });
|
||||
}
|
||||
|
||||
layout1->addLayout(layout2);
|
||||
}
|
||||
|
||||
// CHANNELVIEW
|
||||
{
|
||||
this->channelView_ = new ChannelView(this);
|
||||
|
||||
layout1->addWidget(this->channelView_);
|
||||
}
|
||||
|
||||
this->setLayout(layout1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "ForwardDecl.hpp"
|
||||
#include "messages/LimitedQueueSnapshot.hpp"
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class SearchPopup : public BaseWindow
|
||||
{
|
||||
public:
|
||||
SearchPopup();
|
||||
|
||||
virtual void setChannel(const ChannelPtr &channel);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
virtual void updateWindowTitle();
|
||||
|
||||
private:
|
||||
void initLayout();
|
||||
void search();
|
||||
|
||||
LimitedQueueSnapshot<MessagePtr> snapshot_;
|
||||
QLineEdit *searchInput_{};
|
||||
ChannelView *channelView_{};
|
||||
QString channelName_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "ForwardDecl.hpp"
|
||||
#include "messages/LimitedQueueSnapshot.hpp"
|
||||
#include "widgets/BaseWindow.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class SearchPopup : public BaseWindow
|
||||
{
|
||||
public:
|
||||
SearchPopup();
|
||||
|
||||
virtual void setChannel(const ChannelPtr &channel);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
virtual void updateWindowTitle();
|
||||
|
||||
private:
|
||||
void initLayout();
|
||||
void search();
|
||||
|
||||
LimitedQueueSnapshot<MessagePtr> snapshot_;
|
||||
QLineEdit *searchInput_{};
|
||||
ChannelView *channelView_{};
|
||||
QString channelName_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,222 +1,222 @@
|
||||
#include "AboutPage.hpp"
|
||||
|
||||
#include "debug/Log.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/RemoveScrollAreaBackground.hpp"
|
||||
#include "widgets/helper/SignalLabel.hpp"
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QTextStream>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#define PIXMAP_WIDTH 500
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
AboutPage::AboutPage()
|
||||
: SettingsPage("About", ":/settings/about.svg")
|
||||
{
|
||||
LayoutCreator<AboutPage> layoutCreator(this);
|
||||
|
||||
auto scroll = layoutCreator.emplace<QScrollArea>();
|
||||
auto widget = scroll.emplaceScrollAreaWidget();
|
||||
removeScrollAreaBackground(scroll.getElement(), widget.getElement());
|
||||
|
||||
auto layout = widget.setLayoutType<QVBoxLayout>();
|
||||
{
|
||||
QPixmap pixmap;
|
||||
pixmap.load(":/settings/aboutlogo.png");
|
||||
|
||||
auto logo = layout.emplace<QLabel>().assign(&this->logo_);
|
||||
logo->setPixmap(pixmap);
|
||||
logo->setFixedSize(PIXMAP_WIDTH,
|
||||
PIXMAP_WIDTH * pixmap.height() / pixmap.width());
|
||||
logo->setScaledContents(true);
|
||||
|
||||
// this does nothing
|
||||
// QPalette palette;
|
||||
// palette.setColor(QPalette::Text, Qt::white);
|
||||
// palette.setColor(QPalette::Link, "#a5cdff");
|
||||
// palette.setColor(QPalette::LinkVisited, "#a5cdff");
|
||||
|
||||
/*auto xd = layout.emplace<QGroupBox>("Created by...");
|
||||
{
|
||||
auto created = xd.emplace<QLabel>();
|
||||
{
|
||||
created->setText("Created by <a
|
||||
href=\"https://github.com/fourtf\">fourtf</a><br>" "with big help from
|
||||
pajlada."); created->setTextFormat(Qt::RichText);
|
||||
created->setTextInteractionFlags(Qt::TextBrowserInteraction |
|
||||
Qt::LinksAccessibleByKeyboard |
|
||||
Qt::LinksAccessibleByKeyboard);
|
||||
created->setOpenExternalLinks(true);
|
||||
// created->setPalette(palette);
|
||||
}
|
||||
|
||||
// auto github = xd.emplace<QLabel>();
|
||||
// {
|
||||
// github->setText(
|
||||
// "<a
|
||||
href=\"https://github.com/fourtf/chatterino2\">Chatterino on
|
||||
// Github</a>");
|
||||
// github->setTextFormat(Qt::RichText);
|
||||
// github->setTextInteractionFlags(Qt::TextBrowserInteraction |
|
||||
// Qt::LinksAccessibleByKeyboard |
|
||||
// Qt::LinksAccessibleByKeyboard);
|
||||
// github->setOpenExternalLinks(true);
|
||||
// // github->setPalette(palette);
|
||||
// }
|
||||
}*/
|
||||
|
||||
auto licenses =
|
||||
layout.emplace<QGroupBox>("Open source software used...");
|
||||
{
|
||||
auto form = licenses.emplace<QFormLayout>();
|
||||
|
||||
addLicense(form.getElement(), "Qt Framework", "https://www.qt.io",
|
||||
":/licenses/qt_lgpl-3.0.txt");
|
||||
addLicense(form.getElement(), "Boost", "https://www.boost.org/",
|
||||
":/licenses/boost_boost.txt");
|
||||
addLicense(form.getElement(), "Fmt", "http://fmtlib.net/",
|
||||
":/licenses/fmt_bsd2.txt");
|
||||
addLicense(form.getElement(), "LibCommuni",
|
||||
"https://github.com/communi/libcommuni",
|
||||
":/licenses/libcommuni_BSD3.txt");
|
||||
addLicense(form.getElement(), "OpenSSL", "https://www.openssl.org/",
|
||||
":/licenses/openssl.txt");
|
||||
addLicense(form.getElement(), "RapidJson", "http://rapidjson.org/",
|
||||
":/licenses/rapidjson.txt");
|
||||
addLicense(form.getElement(), "Pajlada/Settings",
|
||||
"https://github.com/pajlada/settings",
|
||||
":/licenses/pajlada_settings.txt");
|
||||
addLicense(form.getElement(), "Pajlada/Signals",
|
||||
"https://github.com/pajlada/signals",
|
||||
":/licenses/pajlada_signals.txt");
|
||||
addLicense(form.getElement(), "Websocketpp",
|
||||
"https://www.zaphoyd.com/websocketpp/",
|
||||
":/licenses/websocketpp.txt");
|
||||
}
|
||||
|
||||
auto attributions = layout.emplace<QGroupBox>("Attributions...");
|
||||
{
|
||||
auto l = attributions.emplace<QVBoxLayout>();
|
||||
|
||||
// clang-format off
|
||||
l.emplace<QLabel>("EmojiOne 2 and 3 emojis provided by <a href=\"https://www.emojione.com/\">EmojiOne</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Twemoji emojis provided by <a href=\"https://github.com/twitter/twemoji\">Twitter's Twemoji</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Facebook emojis provided by <a href=\"https://facebook.com\">Facebook</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Apple emojis provided by <a href=\"https://apple.com\">Apple</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Google emojis provided by <a href=\"https://google.com\">Google</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Messenger emojis provided by <a href=\"https://facebook.com\">Facebook</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Emoji datasource provided by <a href=\"https://www.iamcal.com/\">Cal Henderson</a>"
|
||||
"(<a href=\"https://github.com/iamcal/emoji-data/blob/master/LICENSE\">show license</a>)")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Twitch emote data provided by <a href=\"https://twitchemotes.com/\">twitchemotes.com</a> through the <a href=\"https://github.com/Chatterino/api\">Chatterino API</a>")->setOpenExternalLinks(true);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
// Contributors
|
||||
auto contributors = layout.emplace<QGroupBox>("Contributors");
|
||||
{
|
||||
auto l = contributors.emplace<QVBoxLayout>();
|
||||
|
||||
QFile contributorsFile(":/contributors.txt");
|
||||
contributorsFile.open(QFile::ReadOnly);
|
||||
|
||||
QTextStream stream(&contributorsFile);
|
||||
stream.setCodec("UTF-8");
|
||||
|
||||
QString line;
|
||||
|
||||
while (stream.readLineInto(&line))
|
||||
{
|
||||
if (line.isEmpty() || line.startsWith('#'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList contributorParts = line.split("|");
|
||||
|
||||
if (contributorParts.size() != 4)
|
||||
{
|
||||
log("Missing parts in line '{}'", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
QString username = contributorParts[0].trimmed();
|
||||
QString url = contributorParts[1].trimmed();
|
||||
QString avatarUrl = contributorParts[2].trimmed();
|
||||
QString role = contributorParts[3].trimmed();
|
||||
|
||||
auto *usernameLabel =
|
||||
new QLabel("<a href=\"" + url + "\">" + username + "</a>");
|
||||
usernameLabel->setOpenExternalLinks(true);
|
||||
auto *roleLabel = new QLabel(role);
|
||||
|
||||
auto contributorBox2 = l.emplace<QHBoxLayout>();
|
||||
|
||||
const auto addAvatar = [&avatarUrl, &contributorBox2] {
|
||||
if (!avatarUrl.isEmpty())
|
||||
{
|
||||
QPixmap avatarPixmap;
|
||||
avatarPixmap.load(avatarUrl);
|
||||
|
||||
auto avatar = contributorBox2.emplace<QLabel>();
|
||||
avatar->setPixmap(avatarPixmap);
|
||||
avatar->setFixedSize(64, 64);
|
||||
avatar->setScaledContents(true);
|
||||
}
|
||||
};
|
||||
|
||||
const auto addLabels = [&contributorBox2, &usernameLabel,
|
||||
&roleLabel] {
|
||||
auto labelBox = new QVBoxLayout();
|
||||
contributorBox2->addLayout(labelBox);
|
||||
|
||||
labelBox->addWidget(usernameLabel);
|
||||
labelBox->addWidget(roleLabel);
|
||||
};
|
||||
|
||||
addLabels();
|
||||
addAvatar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto buildInfo = QStringList();
|
||||
buildInfo += "Qt " QT_VERSION_STR;
|
||||
#ifdef USEWINSDK
|
||||
buildInfo += "Windows SDK";
|
||||
#endif
|
||||
#ifdef _MSC_FULL_VER
|
||||
buildInfo += "MSVC " + QString::number(_MSC_FULL_VER, 10);
|
||||
#endif
|
||||
|
||||
auto buildText = QString("Built with " + buildInfo.join(", "));
|
||||
layout.emplace<QLabel>(buildText);
|
||||
|
||||
layout->addStretch(1);
|
||||
}
|
||||
|
||||
void AboutPage::addLicense(QFormLayout *form, const QString &name,
|
||||
const QString &website, const QString &licenseLink)
|
||||
{
|
||||
auto *a = new QLabel("<a href=\"" + website + "\">" + name + "</a>");
|
||||
a->setOpenExternalLinks(true);
|
||||
auto *b = new QLabel("<a href=\"" + licenseLink + "\">show license</a>");
|
||||
QObject::connect(b, &QLabel::linkActivated, [licenseLink] {
|
||||
auto *edit = new QTextEdit;
|
||||
|
||||
QFile file(licenseLink);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
edit->setText(file.readAll());
|
||||
edit->setReadOnly(true);
|
||||
edit->show();
|
||||
});
|
||||
|
||||
form->addRow(a, b);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "AboutPage.hpp"
|
||||
|
||||
#include "debug/Log.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/RemoveScrollAreaBackground.hpp"
|
||||
#include "widgets/helper/SignalLabel.hpp"
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QTextStream>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#define PIXMAP_WIDTH 500
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
AboutPage::AboutPage()
|
||||
: SettingsPage("About", ":/settings/about.svg")
|
||||
{
|
||||
LayoutCreator<AboutPage> layoutCreator(this);
|
||||
|
||||
auto scroll = layoutCreator.emplace<QScrollArea>();
|
||||
auto widget = scroll.emplaceScrollAreaWidget();
|
||||
removeScrollAreaBackground(scroll.getElement(), widget.getElement());
|
||||
|
||||
auto layout = widget.setLayoutType<QVBoxLayout>();
|
||||
{
|
||||
QPixmap pixmap;
|
||||
pixmap.load(":/settings/aboutlogo.png");
|
||||
|
||||
auto logo = layout.emplace<QLabel>().assign(&this->logo_);
|
||||
logo->setPixmap(pixmap);
|
||||
logo->setFixedSize(PIXMAP_WIDTH,
|
||||
PIXMAP_WIDTH * pixmap.height() / pixmap.width());
|
||||
logo->setScaledContents(true);
|
||||
|
||||
// this does nothing
|
||||
// QPalette palette;
|
||||
// palette.setColor(QPalette::Text, Qt::white);
|
||||
// palette.setColor(QPalette::Link, "#a5cdff");
|
||||
// palette.setColor(QPalette::LinkVisited, "#a5cdff");
|
||||
|
||||
/*auto xd = layout.emplace<QGroupBox>("Created by...");
|
||||
{
|
||||
auto created = xd.emplace<QLabel>();
|
||||
{
|
||||
created->setText("Created by <a
|
||||
href=\"https://github.com/fourtf\">fourtf</a><br>" "with big help from
|
||||
pajlada."); created->setTextFormat(Qt::RichText);
|
||||
created->setTextInteractionFlags(Qt::TextBrowserInteraction |
|
||||
Qt::LinksAccessibleByKeyboard |
|
||||
Qt::LinksAccessibleByKeyboard);
|
||||
created->setOpenExternalLinks(true);
|
||||
// created->setPalette(palette);
|
||||
}
|
||||
|
||||
// auto github = xd.emplace<QLabel>();
|
||||
// {
|
||||
// github->setText(
|
||||
// "<a
|
||||
href=\"https://github.com/fourtf/chatterino2\">Chatterino on
|
||||
// Github</a>");
|
||||
// github->setTextFormat(Qt::RichText);
|
||||
// github->setTextInteractionFlags(Qt::TextBrowserInteraction |
|
||||
// Qt::LinksAccessibleByKeyboard |
|
||||
// Qt::LinksAccessibleByKeyboard);
|
||||
// github->setOpenExternalLinks(true);
|
||||
// // github->setPalette(palette);
|
||||
// }
|
||||
}*/
|
||||
|
||||
auto licenses =
|
||||
layout.emplace<QGroupBox>("Open source software used...");
|
||||
{
|
||||
auto form = licenses.emplace<QFormLayout>();
|
||||
|
||||
addLicense(form.getElement(), "Qt Framework", "https://www.qt.io",
|
||||
":/licenses/qt_lgpl-3.0.txt");
|
||||
addLicense(form.getElement(), "Boost", "https://www.boost.org/",
|
||||
":/licenses/boost_boost.txt");
|
||||
addLicense(form.getElement(), "Fmt", "http://fmtlib.net/",
|
||||
":/licenses/fmt_bsd2.txt");
|
||||
addLicense(form.getElement(), "LibCommuni",
|
||||
"https://github.com/communi/libcommuni",
|
||||
":/licenses/libcommuni_BSD3.txt");
|
||||
addLicense(form.getElement(), "OpenSSL", "https://www.openssl.org/",
|
||||
":/licenses/openssl.txt");
|
||||
addLicense(form.getElement(), "RapidJson", "http://rapidjson.org/",
|
||||
":/licenses/rapidjson.txt");
|
||||
addLicense(form.getElement(), "Pajlada/Settings",
|
||||
"https://github.com/pajlada/settings",
|
||||
":/licenses/pajlada_settings.txt");
|
||||
addLicense(form.getElement(), "Pajlada/Signals",
|
||||
"https://github.com/pajlada/signals",
|
||||
":/licenses/pajlada_signals.txt");
|
||||
addLicense(form.getElement(), "Websocketpp",
|
||||
"https://www.zaphoyd.com/websocketpp/",
|
||||
":/licenses/websocketpp.txt");
|
||||
}
|
||||
|
||||
auto attributions = layout.emplace<QGroupBox>("Attributions...");
|
||||
{
|
||||
auto l = attributions.emplace<QVBoxLayout>();
|
||||
|
||||
// clang-format off
|
||||
l.emplace<QLabel>("EmojiOne 2 and 3 emojis provided by <a href=\"https://www.emojione.com/\">EmojiOne</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Twemoji emojis provided by <a href=\"https://github.com/twitter/twemoji\">Twitter's Twemoji</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Facebook emojis provided by <a href=\"https://facebook.com\">Facebook</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Apple emojis provided by <a href=\"https://apple.com\">Apple</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Google emojis provided by <a href=\"https://google.com\">Google</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Messenger emojis provided by <a href=\"https://facebook.com\">Facebook</a>")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Emoji datasource provided by <a href=\"https://www.iamcal.com/\">Cal Henderson</a>"
|
||||
"(<a href=\"https://github.com/iamcal/emoji-data/blob/master/LICENSE\">show license</a>)")->setOpenExternalLinks(true);
|
||||
l.emplace<QLabel>("Twitch emote data provided by <a href=\"https://twitchemotes.com/\">twitchemotes.com</a> through the <a href=\"https://github.com/Chatterino/api\">Chatterino API</a>")->setOpenExternalLinks(true);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
// Contributors
|
||||
auto contributors = layout.emplace<QGroupBox>("Contributors");
|
||||
{
|
||||
auto l = contributors.emplace<QVBoxLayout>();
|
||||
|
||||
QFile contributorsFile(":/contributors.txt");
|
||||
contributorsFile.open(QFile::ReadOnly);
|
||||
|
||||
QTextStream stream(&contributorsFile);
|
||||
stream.setCodec("UTF-8");
|
||||
|
||||
QString line;
|
||||
|
||||
while (stream.readLineInto(&line))
|
||||
{
|
||||
if (line.isEmpty() || line.startsWith('#'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList contributorParts = line.split("|");
|
||||
|
||||
if (contributorParts.size() != 4)
|
||||
{
|
||||
log("Missing parts in line '{}'", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
QString username = contributorParts[0].trimmed();
|
||||
QString url = contributorParts[1].trimmed();
|
||||
QString avatarUrl = contributorParts[2].trimmed();
|
||||
QString role = contributorParts[3].trimmed();
|
||||
|
||||
auto *usernameLabel =
|
||||
new QLabel("<a href=\"" + url + "\">" + username + "</a>");
|
||||
usernameLabel->setOpenExternalLinks(true);
|
||||
auto *roleLabel = new QLabel(role);
|
||||
|
||||
auto contributorBox2 = l.emplace<QHBoxLayout>();
|
||||
|
||||
const auto addAvatar = [&avatarUrl, &contributorBox2] {
|
||||
if (!avatarUrl.isEmpty())
|
||||
{
|
||||
QPixmap avatarPixmap;
|
||||
avatarPixmap.load(avatarUrl);
|
||||
|
||||
auto avatar = contributorBox2.emplace<QLabel>();
|
||||
avatar->setPixmap(avatarPixmap);
|
||||
avatar->setFixedSize(64, 64);
|
||||
avatar->setScaledContents(true);
|
||||
}
|
||||
};
|
||||
|
||||
const auto addLabels = [&contributorBox2, &usernameLabel,
|
||||
&roleLabel] {
|
||||
auto labelBox = new QVBoxLayout();
|
||||
contributorBox2->addLayout(labelBox);
|
||||
|
||||
labelBox->addWidget(usernameLabel);
|
||||
labelBox->addWidget(roleLabel);
|
||||
};
|
||||
|
||||
addLabels();
|
||||
addAvatar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto buildInfo = QStringList();
|
||||
buildInfo += "Qt " QT_VERSION_STR;
|
||||
#ifdef USEWINSDK
|
||||
buildInfo += "Windows SDK";
|
||||
#endif
|
||||
#ifdef _MSC_FULL_VER
|
||||
buildInfo += "MSVC " + QString::number(_MSC_FULL_VER, 10);
|
||||
#endif
|
||||
|
||||
auto buildText = QString("Built with " + buildInfo.join(", "));
|
||||
layout.emplace<QLabel>(buildText);
|
||||
|
||||
layout->addStretch(1);
|
||||
}
|
||||
|
||||
void AboutPage::addLicense(QFormLayout *form, const QString &name,
|
||||
const QString &website, const QString &licenseLink)
|
||||
{
|
||||
auto *a = new QLabel("<a href=\"" + website + "\">" + name + "</a>");
|
||||
a->setOpenExternalLinks(true);
|
||||
auto *b = new QLabel("<a href=\"" + licenseLink + "\">show license</a>");
|
||||
QObject::connect(b, &QLabel::linkActivated, [licenseLink] {
|
||||
auto *edit = new QTextEdit;
|
||||
|
||||
QFile file(licenseLink);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
edit->setText(file.readAll());
|
||||
edit->setReadOnly(true);
|
||||
edit->show();
|
||||
});
|
||||
|
||||
form->addRow(a, b);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
class QLabel;
|
||||
class QFormLayout;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class AboutPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
AboutPage();
|
||||
|
||||
private:
|
||||
void addLicense(QFormLayout *form, const QString &name_,
|
||||
const QString &website, const QString &licenseLink);
|
||||
|
||||
QLabel *logo_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
class QLabel;
|
||||
class QFormLayout;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class AboutPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
AboutPage();
|
||||
|
||||
private:
|
||||
void addLicense(QFormLayout *form, const QString &name_,
|
||||
const QString &website, const QString &licenseLink);
|
||||
|
||||
QLabel *logo_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,69 +1,69 @@
|
||||
#include "AccountsPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "controllers/accounts/AccountModel.hpp"
|
||||
#include "providers/twitch/TwitchCommon.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/dialogs/LoginDialog.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHeaderView>
|
||||
#include <QTableView>
|
||||
#include <QVBoxLayout>
|
||||
#include <algorithm>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
AccountsPage::AccountsPage()
|
||||
: SettingsPage("Accounts", ":/settings/accounts.svg")
|
||||
{
|
||||
auto *app = getApp();
|
||||
|
||||
LayoutCreator<AccountsPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||
|
||||
EditableModelView *view =
|
||||
layout.emplace<EditableModelView>(app->accounts->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->getTableView()->horizontalHeader()->setVisible(false);
|
||||
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
static auto loginWidget = new LoginWidget();
|
||||
|
||||
loginWidget->show();
|
||||
loginWidget->raise();
|
||||
});
|
||||
|
||||
view->getTableView()->setStyleSheet("background: #333");
|
||||
|
||||
// auto buttons = layout.emplace<QDialogButtonBox>();
|
||||
// {
|
||||
// this->addButton = buttons->addButton("Add",
|
||||
// QDialogButtonBox::YesRole); this->removeButton =
|
||||
// buttons->addButton("Remove", QDialogButtonBox::NoRole);
|
||||
// }
|
||||
|
||||
// layout.emplace<AccountSwitchWidget>(this).assign(&this->accSwitchWidget);
|
||||
|
||||
// ----
|
||||
// QObject::connect(this->addButton, &QPushButton::clicked, []() {
|
||||
// static auto loginWidget = new LoginWidget();
|
||||
// loginWidget->show();
|
||||
// });
|
||||
|
||||
// QObject::connect(this->removeButton, &QPushButton::clicked, [this] {
|
||||
// auto selectedUser = this->accSwitchWidget->currentItem()->text();
|
||||
// if (selectedUser == ANONYMOUS_USERNAME_LABEL) {
|
||||
// // Do nothing
|
||||
// return;
|
||||
// }
|
||||
|
||||
// getApp()->accounts->Twitch.removeUser(selectedUser);
|
||||
// });
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "AccountsPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "controllers/accounts/AccountModel.hpp"
|
||||
#include "providers/twitch/TwitchCommon.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/dialogs/LoginDialog.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHeaderView>
|
||||
#include <QTableView>
|
||||
#include <QVBoxLayout>
|
||||
#include <algorithm>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
AccountsPage::AccountsPage()
|
||||
: SettingsPage("Accounts", ":/settings/accounts.svg")
|
||||
{
|
||||
auto *app = getApp();
|
||||
|
||||
LayoutCreator<AccountsPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||
|
||||
EditableModelView *view =
|
||||
layout.emplace<EditableModelView>(app->accounts->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->getTableView()->horizontalHeader()->setVisible(false);
|
||||
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
static auto loginWidget = new LoginWidget();
|
||||
|
||||
loginWidget->show();
|
||||
loginWidget->raise();
|
||||
});
|
||||
|
||||
view->getTableView()->setStyleSheet("background: #333");
|
||||
|
||||
// auto buttons = layout.emplace<QDialogButtonBox>();
|
||||
// {
|
||||
// this->addButton = buttons->addButton("Add",
|
||||
// QDialogButtonBox::YesRole); this->removeButton =
|
||||
// buttons->addButton("Remove", QDialogButtonBox::NoRole);
|
||||
// }
|
||||
|
||||
// layout.emplace<AccountSwitchWidget>(this).assign(&this->accSwitchWidget);
|
||||
|
||||
// ----
|
||||
// QObject::connect(this->addButton, &QPushButton::clicked, []() {
|
||||
// static auto loginWidget = new LoginWidget();
|
||||
// loginWidget->show();
|
||||
// });
|
||||
|
||||
// QObject::connect(this->removeButton, &QPushButton::clicked, [this] {
|
||||
// auto selectedUser = this->accSwitchWidget->currentItem()->text();
|
||||
// if (selectedUser == ANONYMOUS_USERNAME_LABEL) {
|
||||
// // Do nothing
|
||||
// return;
|
||||
// }
|
||||
|
||||
// getApp()->accounts->Twitch.removeUser(selectedUser);
|
||||
// });
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/AccountSwitchWidget.hpp"
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class AccountsPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
AccountsPage();
|
||||
|
||||
private:
|
||||
QPushButton *addButton_;
|
||||
QPushButton *removeButton_;
|
||||
AccountSwitchWidget *accountSwitchWidget_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/AccountSwitchWidget.hpp"
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class AccountsPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
AccountsPage();
|
||||
|
||||
private:
|
||||
QPushButton *addButton_;
|
||||
QPushButton *removeButton_;
|
||||
AccountSwitchWidget *accountSwitchWidget_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,88 +1,88 @@
|
||||
#include "CommandPage.hpp"
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTableView>
|
||||
#include <QTextEdit>
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/commands/CommandController.hpp"
|
||||
#include "controllers/commands/CommandModel.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/StandardItemHelper.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
//#include "widgets/helper/ComboBoxItemDelegate.hpp"
|
||||
#include "util/CombinePath.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
|
||||
// clang-format off
|
||||
#define TEXT "{1} => first word {1+} => first word and after {{ => { <a href='https://chatterino.com/help/commands'>more info</a>"
|
||||
// clang-format on
|
||||
|
||||
namespace chatterino {
|
||||
namespace {
|
||||
QString c1settingsPath()
|
||||
{
|
||||
return combinePath(qgetenv("appdata"),
|
||||
"Chatterino\\Custom\\Commands.txt");
|
||||
}
|
||||
} // namespace
|
||||
|
||||
CommandPage::CommandPage()
|
||||
: SettingsPage("Commands", ":/settings/commands.svg")
|
||||
{
|
||||
auto app = getApp();
|
||||
|
||||
LayoutCreator<CommandPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
|
||||
|
||||
EditableModelView *view =
|
||||
layout.emplace<EditableModelView>(app->commands->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->setTitles({"Trigger", "Command"});
|
||||
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->commands->items_.appendItem(
|
||||
Command{"/command", "I made a new command HeyGuys"});
|
||||
});
|
||||
|
||||
if (QFile(c1settingsPath()).exists())
|
||||
{
|
||||
auto button = new QPushButton("Import commands from Chatterino 1");
|
||||
view->addCustomButton(button);
|
||||
|
||||
QObject::connect(button, &QPushButton::clicked, this, [] {
|
||||
QFile c1settings = c1settingsPath();
|
||||
c1settings.open(QIODevice::ReadOnly);
|
||||
for (auto line : QString(c1settings.readAll())
|
||||
.split(QRegularExpression("[\r\n]"),
|
||||
QString::SkipEmptyParts))
|
||||
{
|
||||
if (int index = line.indexOf(' '); index != -1)
|
||||
{
|
||||
getApp()->commands->items_.insertItem(
|
||||
Command(line.mid(0, index), line.mid(index + 1)));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
layout.append(
|
||||
this->createCheckBox("Also match the trigger at the end of the message",
|
||||
getSettings()->allowCommandsAtEnd));
|
||||
|
||||
QLabel *text = layout.emplace<QLabel>(TEXT).getElement();
|
||||
text->setWordWrap(true);
|
||||
text->setStyleSheet("color: #bbb");
|
||||
text->setOpenExternalLinks(true);
|
||||
|
||||
// ---- end of layout
|
||||
this->commandsEditTimer_.setSingleShot(true);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "CommandPage.hpp"
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTableView>
|
||||
#include <QTextEdit>
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/commands/CommandController.hpp"
|
||||
#include "controllers/commands/CommandModel.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/StandardItemHelper.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
//#include "widgets/helper/ComboBoxItemDelegate.hpp"
|
||||
#include "util/CombinePath.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
|
||||
// clang-format off
|
||||
#define TEXT "{1} => first word {1+} => first word and after {{ => { <a href='https://chatterino.com/help/commands'>more info</a>"
|
||||
// clang-format on
|
||||
|
||||
namespace chatterino {
|
||||
namespace {
|
||||
QString c1settingsPath()
|
||||
{
|
||||
return combinePath(qgetenv("appdata"),
|
||||
"Chatterino\\Custom\\Commands.txt");
|
||||
}
|
||||
} // namespace
|
||||
|
||||
CommandPage::CommandPage()
|
||||
: SettingsPage("Commands", ":/settings/commands.svg")
|
||||
{
|
||||
auto app = getApp();
|
||||
|
||||
LayoutCreator<CommandPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
|
||||
|
||||
EditableModelView *view =
|
||||
layout.emplace<EditableModelView>(app->commands->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->setTitles({"Trigger", "Command"});
|
||||
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->commands->items_.appendItem(
|
||||
Command{"/command", "I made a new command HeyGuys"});
|
||||
});
|
||||
|
||||
if (QFile(c1settingsPath()).exists())
|
||||
{
|
||||
auto button = new QPushButton("Import commands from Chatterino 1");
|
||||
view->addCustomButton(button);
|
||||
|
||||
QObject::connect(button, &QPushButton::clicked, this, [] {
|
||||
QFile c1settings = c1settingsPath();
|
||||
c1settings.open(QIODevice::ReadOnly);
|
||||
for (auto line : QString(c1settings.readAll())
|
||||
.split(QRegularExpression("[\r\n]"),
|
||||
QString::SkipEmptyParts))
|
||||
{
|
||||
if (int index = line.indexOf(' '); index != -1)
|
||||
{
|
||||
getApp()->commands->items_.insertItem(
|
||||
Command(line.mid(0, index), line.mid(index + 1)));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
layout.append(
|
||||
this->createCheckBox("Also match the trigger at the end of the message",
|
||||
getSettings()->allowCommandsAtEnd));
|
||||
|
||||
QLabel *text = layout.emplace<QLabel>(TEXT).getElement();
|
||||
text->setWordWrap(true);
|
||||
text->setStyleSheet("color: #bbb");
|
||||
text->setOpenExternalLinks(true);
|
||||
|
||||
// ---- end of layout
|
||||
this->commandsEditTimer_.setSingleShot(true);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <QTimer>
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class CommandPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
CommandPage();
|
||||
|
||||
private:
|
||||
QTimer commandsEditTimer_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <QTimer>
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class CommandPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
CommandPage();
|
||||
|
||||
private:
|
||||
QTimer commandsEditTimer_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
#include "ExternalToolsPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "util/Helpers.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
|
||||
#include <QGroupBox>
|
||||
|
||||
#define STREAMLINK_QUALITY \
|
||||
"Choose", "Source", "High", "Medium", "Low", "Audio only"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
ExternalToolsPage::ExternalToolsPage()
|
||||
: SettingsPage("External tools", ":/settings/externaltools.svg")
|
||||
{
|
||||
LayoutCreator<ExternalToolsPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
|
||||
|
||||
{
|
||||
auto group = layout.emplace<QGroupBox>("Streamlink");
|
||||
auto groupLayout = group.setLayoutType<QFormLayout>();
|
||||
|
||||
auto description = new QLabel(
|
||||
"Streamlink is a command-line utility that pipes video streams "
|
||||
"from various "
|
||||
"services into a video player, such as VLC. Make sure to edit the "
|
||||
"configuration file before you use it!");
|
||||
description->setWordWrap(true);
|
||||
description->setStyleSheet("color: #bbb");
|
||||
|
||||
auto links = new QLabel(
|
||||
createNamedLink("https://streamlink.github.io/", "Website") + " " +
|
||||
createNamedLink(
|
||||
"https://github.com/streamlink/streamlink/releases/latest",
|
||||
"Download"));
|
||||
links->setTextFormat(Qt::RichText);
|
||||
links->setTextInteractionFlags(Qt::TextBrowserInteraction |
|
||||
Qt::LinksAccessibleByKeyboard |
|
||||
Qt::LinksAccessibleByKeyboard);
|
||||
links->setOpenExternalLinks(true);
|
||||
|
||||
groupLayout->setWidget(0, QFormLayout::SpanningRole, description);
|
||||
groupLayout->setWidget(1, QFormLayout::SpanningRole, links);
|
||||
|
||||
auto customPathCb =
|
||||
this->createCheckBox("Use custom path (Enable if using "
|
||||
"non-standard streamlink installation path)",
|
||||
getSettings()->streamlinkUseCustomPath);
|
||||
groupLayout->setWidget(2, QFormLayout::SpanningRole, customPathCb);
|
||||
|
||||
auto customPath = this->createLineEdit(getSettings()->streamlinkPath);
|
||||
customPath->setPlaceholderText(
|
||||
"Path to folder where Streamlink executable can be found");
|
||||
groupLayout->addRow("Custom streamlink path:", customPath);
|
||||
groupLayout->addRow(
|
||||
"Preferred quality:",
|
||||
this->createComboBox({STREAMLINK_QUALITY},
|
||||
getSettings()->preferredQuality));
|
||||
groupLayout->addRow(
|
||||
"Additional options:",
|
||||
this->createLineEdit(getSettings()->streamlinkOpts));
|
||||
|
||||
getSettings()->streamlinkUseCustomPath.connect(
|
||||
[=](const auto &value, auto) {
|
||||
customPath->setEnabled(value); //
|
||||
},
|
||||
this->managedConnections_);
|
||||
}
|
||||
|
||||
layout->addStretch(1);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "ExternalToolsPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "util/Helpers.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
|
||||
#include <QGroupBox>
|
||||
|
||||
#define STREAMLINK_QUALITY \
|
||||
"Choose", "Source", "High", "Medium", "Low", "Audio only"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
ExternalToolsPage::ExternalToolsPage()
|
||||
: SettingsPage("External tools", ":/settings/externaltools.svg")
|
||||
{
|
||||
LayoutCreator<ExternalToolsPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
|
||||
|
||||
{
|
||||
auto group = layout.emplace<QGroupBox>("Streamlink");
|
||||
auto groupLayout = group.setLayoutType<QFormLayout>();
|
||||
|
||||
auto description = new QLabel(
|
||||
"Streamlink is a command-line utility that pipes video streams "
|
||||
"from various "
|
||||
"services into a video player, such as VLC. Make sure to edit the "
|
||||
"configuration file before you use it!");
|
||||
description->setWordWrap(true);
|
||||
description->setStyleSheet("color: #bbb");
|
||||
|
||||
auto links = new QLabel(
|
||||
createNamedLink("https://streamlink.github.io/", "Website") + " " +
|
||||
createNamedLink(
|
||||
"https://github.com/streamlink/streamlink/releases/latest",
|
||||
"Download"));
|
||||
links->setTextFormat(Qt::RichText);
|
||||
links->setTextInteractionFlags(Qt::TextBrowserInteraction |
|
||||
Qt::LinksAccessibleByKeyboard |
|
||||
Qt::LinksAccessibleByKeyboard);
|
||||
links->setOpenExternalLinks(true);
|
||||
|
||||
groupLayout->setWidget(0, QFormLayout::SpanningRole, description);
|
||||
groupLayout->setWidget(1, QFormLayout::SpanningRole, links);
|
||||
|
||||
auto customPathCb =
|
||||
this->createCheckBox("Use custom path (Enable if using "
|
||||
"non-standard streamlink installation path)",
|
||||
getSettings()->streamlinkUseCustomPath);
|
||||
groupLayout->setWidget(2, QFormLayout::SpanningRole, customPathCb);
|
||||
|
||||
auto customPath = this->createLineEdit(getSettings()->streamlinkPath);
|
||||
customPath->setPlaceholderText(
|
||||
"Path to folder where Streamlink executable can be found");
|
||||
groupLayout->addRow("Custom streamlink path:", customPath);
|
||||
groupLayout->addRow(
|
||||
"Preferred quality:",
|
||||
this->createComboBox({STREAMLINK_QUALITY},
|
||||
getSettings()->preferredQuality));
|
||||
groupLayout->addRow(
|
||||
"Additional options:",
|
||||
this->createLineEdit(getSettings()->streamlinkOpts));
|
||||
|
||||
getSettings()->streamlinkUseCustomPath.connect(
|
||||
[=](const auto &value, auto) {
|
||||
customPath->setEnabled(value); //
|
||||
},
|
||||
this->managedConnections_);
|
||||
}
|
||||
|
||||
layout->addStretch(1);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class ExternalToolsPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
ExternalToolsPage();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class ExternalToolsPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
ExternalToolsPage();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,191 +1,191 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "boost/variant.hpp"
|
||||
#include "pajlada/signals/signal.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "singletons/WindowManager.hpp"
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
class QLabel;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class TitleLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TitleLabel(const QString &text)
|
||||
: QLabel(text)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class DescriptionLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DescriptionLabel(const QString &text)
|
||||
: QLabel(text)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct DropdownArgs {
|
||||
QString value;
|
||||
int index;
|
||||
QComboBox *combobox;
|
||||
};
|
||||
|
||||
class ComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
void wheelEvent(QWheelEvent *event) override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class SettingsLayout : public QVBoxLayout
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TitleLabel *addTitle(const QString &text);
|
||||
/// @param inverse Inverses true to false and vice versa
|
||||
QCheckBox *addCheckbox(const QString &text, BoolSetting &setting,
|
||||
bool inverse = false);
|
||||
ComboBox *addDropdown(const QString &text, const QStringList &items);
|
||||
ComboBox *addDropdown(const QString &text, const QStringList &items,
|
||||
pajlada::Settings::Setting<QString> &setting,
|
||||
bool editable = false);
|
||||
|
||||
template <typename OnClick>
|
||||
QPushButton *makeButton(const QString &text, OnClick onClick)
|
||||
{
|
||||
auto button = new QPushButton(text);
|
||||
this->groups_.back().widgets.push_back({button, {text}});
|
||||
QObject::connect(button, &QPushButton::clicked, onClick);
|
||||
return button;
|
||||
}
|
||||
|
||||
template <typename OnClick>
|
||||
QPushButton *addButton(const QString &text, OnClick onClick)
|
||||
{
|
||||
auto button = makeButton(text, onClick);
|
||||
auto layout = new QHBoxLayout();
|
||||
layout->addWidget(button);
|
||||
layout->addStretch(1);
|
||||
this->addLayout(layout);
|
||||
return button;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ComboBox *addDropdown(
|
||||
const QString &text, const QStringList &items,
|
||||
pajlada::Settings::Setting<T> &setting,
|
||||
std::function<boost::variant<int, QString>(T)> getValue,
|
||||
std::function<T(DropdownArgs)> setValue, bool editable = true)
|
||||
{
|
||||
auto items2 = items;
|
||||
auto selected = getValue(setting.getValue());
|
||||
|
||||
if (selected.which() == 1)
|
||||
{
|
||||
// QString
|
||||
if (!editable && !items2.contains(boost::get<QString>(selected)))
|
||||
items2.insert(0, boost::get<QString>(selected));
|
||||
}
|
||||
|
||||
auto combo = this->addDropdown(text, items2);
|
||||
if (editable)
|
||||
combo->setEditable(true);
|
||||
|
||||
if (selected.which() == 0)
|
||||
{
|
||||
// int
|
||||
auto value = boost::get<int>(selected);
|
||||
if (value >= 0 && value < items2.size())
|
||||
combo->setCurrentIndex(value);
|
||||
}
|
||||
else if (selected.which() == 1)
|
||||
{
|
||||
// QString
|
||||
combo->setEditText(boost::get<QString>(selected));
|
||||
}
|
||||
|
||||
setting.connect(
|
||||
[getValue = std::move(getValue), combo](const T &value, auto) {
|
||||
auto var = getValue(value);
|
||||
if (var.which() == 0)
|
||||
combo->setCurrentIndex(boost::get<int>(var));
|
||||
else
|
||||
{
|
||||
combo->setCurrentText(boost::get<QString>(var));
|
||||
combo->setEditText(boost::get<QString>(var));
|
||||
}
|
||||
},
|
||||
this->managedConnections_);
|
||||
|
||||
QObject::connect(
|
||||
combo,
|
||||
QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
|
||||
// &QComboBox::editTextChanged,
|
||||
[combo, &setting,
|
||||
setValue = std::move(setValue)](const QString &newValue) {
|
||||
setting = setValue(
|
||||
DropdownArgs{newValue, combo->currentIndex(), combo});
|
||||
getApp()->windows->forceLayoutChannelViews();
|
||||
});
|
||||
|
||||
return combo;
|
||||
}
|
||||
DescriptionLabel *addDescription(const QString &text);
|
||||
|
||||
void addSeperator();
|
||||
bool filterElements(const QString &query);
|
||||
|
||||
private:
|
||||
struct Widget {
|
||||
QWidget *element;
|
||||
QStringList keywords;
|
||||
};
|
||||
|
||||
struct Group {
|
||||
QString name;
|
||||
QWidget *title{};
|
||||
std::vector<Widget> widgets;
|
||||
};
|
||||
|
||||
std::vector<Group> groups_;
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
|
||||
};
|
||||
|
||||
class GeneralPage : public SettingsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GeneralPage();
|
||||
|
||||
bool filterElements(const QString &query);
|
||||
|
||||
private:
|
||||
void initLayout(SettingsLayout &layout);
|
||||
void initExtra();
|
||||
|
||||
QString getFont(const DropdownArgs &args) const;
|
||||
|
||||
DescriptionLabel *cachePath_{};
|
||||
SettingsLayout *settingsLayout_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "boost/variant.hpp"
|
||||
#include "pajlada/signals/signal.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "singletons/WindowManager.hpp"
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
class QLabel;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class TitleLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TitleLabel(const QString &text)
|
||||
: QLabel(text)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class DescriptionLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DescriptionLabel(const QString &text)
|
||||
: QLabel(text)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct DropdownArgs {
|
||||
QString value;
|
||||
int index;
|
||||
QComboBox *combobox;
|
||||
};
|
||||
|
||||
class ComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
void wheelEvent(QWheelEvent *event) override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class SettingsLayout : public QVBoxLayout
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TitleLabel *addTitle(const QString &text);
|
||||
/// @param inverse Inverses true to false and vice versa
|
||||
QCheckBox *addCheckbox(const QString &text, BoolSetting &setting,
|
||||
bool inverse = false);
|
||||
ComboBox *addDropdown(const QString &text, const QStringList &items);
|
||||
ComboBox *addDropdown(const QString &text, const QStringList &items,
|
||||
pajlada::Settings::Setting<QString> &setting,
|
||||
bool editable = false);
|
||||
|
||||
template <typename OnClick>
|
||||
QPushButton *makeButton(const QString &text, OnClick onClick)
|
||||
{
|
||||
auto button = new QPushButton(text);
|
||||
this->groups_.back().widgets.push_back({button, {text}});
|
||||
QObject::connect(button, &QPushButton::clicked, onClick);
|
||||
return button;
|
||||
}
|
||||
|
||||
template <typename OnClick>
|
||||
QPushButton *addButton(const QString &text, OnClick onClick)
|
||||
{
|
||||
auto button = makeButton(text, onClick);
|
||||
auto layout = new QHBoxLayout();
|
||||
layout->addWidget(button);
|
||||
layout->addStretch(1);
|
||||
this->addLayout(layout);
|
||||
return button;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ComboBox *addDropdown(
|
||||
const QString &text, const QStringList &items,
|
||||
pajlada::Settings::Setting<T> &setting,
|
||||
std::function<boost::variant<int, QString>(T)> getValue,
|
||||
std::function<T(DropdownArgs)> setValue, bool editable = true)
|
||||
{
|
||||
auto items2 = items;
|
||||
auto selected = getValue(setting.getValue());
|
||||
|
||||
if (selected.which() == 1)
|
||||
{
|
||||
// QString
|
||||
if (!editable && !items2.contains(boost::get<QString>(selected)))
|
||||
items2.insert(0, boost::get<QString>(selected));
|
||||
}
|
||||
|
||||
auto combo = this->addDropdown(text, items2);
|
||||
if (editable)
|
||||
combo->setEditable(true);
|
||||
|
||||
if (selected.which() == 0)
|
||||
{
|
||||
// int
|
||||
auto value = boost::get<int>(selected);
|
||||
if (value >= 0 && value < items2.size())
|
||||
combo->setCurrentIndex(value);
|
||||
}
|
||||
else if (selected.which() == 1)
|
||||
{
|
||||
// QString
|
||||
combo->setEditText(boost::get<QString>(selected));
|
||||
}
|
||||
|
||||
setting.connect(
|
||||
[getValue = std::move(getValue), combo](const T &value, auto) {
|
||||
auto var = getValue(value);
|
||||
if (var.which() == 0)
|
||||
combo->setCurrentIndex(boost::get<int>(var));
|
||||
else
|
||||
{
|
||||
combo->setCurrentText(boost::get<QString>(var));
|
||||
combo->setEditText(boost::get<QString>(var));
|
||||
}
|
||||
},
|
||||
this->managedConnections_);
|
||||
|
||||
QObject::connect(
|
||||
combo,
|
||||
QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
|
||||
// &QComboBox::editTextChanged,
|
||||
[combo, &setting,
|
||||
setValue = std::move(setValue)](const QString &newValue) {
|
||||
setting = setValue(
|
||||
DropdownArgs{newValue, combo->currentIndex(), combo});
|
||||
getApp()->windows->forceLayoutChannelViews();
|
||||
});
|
||||
|
||||
return combo;
|
||||
}
|
||||
DescriptionLabel *addDescription(const QString &text);
|
||||
|
||||
void addSeperator();
|
||||
bool filterElements(const QString &query);
|
||||
|
||||
private:
|
||||
struct Widget {
|
||||
QWidget *element;
|
||||
QStringList keywords;
|
||||
};
|
||||
|
||||
struct Group {
|
||||
QString name;
|
||||
QWidget *title{};
|
||||
std::vector<Widget> widgets;
|
||||
};
|
||||
|
||||
std::vector<Group> groups_;
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
|
||||
};
|
||||
|
||||
class GeneralPage : public SettingsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GeneralPage();
|
||||
|
||||
bool filterElements(const QString &query);
|
||||
|
||||
private:
|
||||
void initLayout(SettingsLayout &layout);
|
||||
void initExtra();
|
||||
|
||||
QString getFont(const DropdownArgs &args) const;
|
||||
|
||||
DescriptionLabel *cachePath_{};
|
||||
SettingsLayout *settingsLayout_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,175 +1,175 @@
|
||||
#include "HighlightingPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/highlights/HighlightBlacklistModel.hpp"
|
||||
#include "controllers/highlights/HighlightController.hpp"
|
||||
#include "controllers/highlights/HighlightModel.hpp"
|
||||
#include "controllers/highlights/UserHighlightModel.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/StandardItemHelper.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTabWidget>
|
||||
#include <QTableView>
|
||||
#include <QTextEdit>
|
||||
|
||||
#define ENABLE_HIGHLIGHTS "Enable Highlighting"
|
||||
#define HIGHLIGHT_MSG "Highlight messages containing your name"
|
||||
#define PLAY_SOUND "Play sound when your name is mentioned"
|
||||
#define FLASH_TASKBAR "Flash taskbar when your name is mentioned"
|
||||
#define ALWAYS_PLAY "Play highlight sound even when Chatterino is focused"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
HighlightingPage::HighlightingPage()
|
||||
: SettingsPage("Highlights", ":/settings/notifications.svg")
|
||||
{
|
||||
auto app = getApp();
|
||||
LayoutCreator<HighlightingPage> layoutCreator(this);
|
||||
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||
{
|
||||
// GENERAL
|
||||
// layout.append(this->createCheckBox(ENABLE_HIGHLIGHTS,
|
||||
// getSettings()->enableHighlights));
|
||||
|
||||
// TABS
|
||||
auto tabs = layout.emplace<QTabWidget>();
|
||||
{
|
||||
// HIGHLIGHTS
|
||||
auto highlights = tabs.appendTab(new QVBoxLayout, "Messages");
|
||||
{
|
||||
highlights.emplace<QLabel>("Messages can be highlighted if "
|
||||
"they match a certain pattern.");
|
||||
|
||||
EditableModelView *view =
|
||||
highlights
|
||||
.emplace<EditableModelView>(
|
||||
app->highlights->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->addRegexHelpLink();
|
||||
view->setTitles({"Pattern", "Flash\ntaskbar", "Play\nsound",
|
||||
"Enable\nregex", "Case-\nsensitive"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
|
||||
// fourtf: make class extrend BaseWidget and add this to
|
||||
// dpiChanged
|
||||
QTimer::singleShot(1, [view] {
|
||||
view->getTableView()->resizeColumnsToContents();
|
||||
view->getTableView()->setColumnWidth(0, 200);
|
||||
});
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->highlights->phrases.appendItem(HighlightPhrase{
|
||||
"my phrase", true, false, false, false});
|
||||
});
|
||||
}
|
||||
|
||||
auto pingUsers = tabs.appendTab(new QVBoxLayout, "Users");
|
||||
{
|
||||
pingUsers.emplace<QLabel>(
|
||||
"Messages from a certain user can be highlighted.");
|
||||
EditableModelView *view =
|
||||
pingUsers
|
||||
.emplace<EditableModelView>(
|
||||
app->highlights->createUserModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->addRegexHelpLink();
|
||||
view->getTableView()->horizontalHeader()->hideSection(4);
|
||||
|
||||
// Case-sensitivity doesn't make sense for user names so it is
|
||||
// set to "false" by default & no checkbox is shown
|
||||
view->setTitles({"Username", "Flash\ntaskbar", "Play\nsound",
|
||||
"Enable\nregex"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
|
||||
// fourtf: make class extrend BaseWidget and add this to
|
||||
// dpiChanged
|
||||
QTimer::singleShot(1, [view] {
|
||||
view->getTableView()->resizeColumnsToContents();
|
||||
view->getTableView()->setColumnWidth(0, 200);
|
||||
});
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->highlights->highlightedUsers.appendItem(
|
||||
HighlightPhrase{"highlighted user", true, false, false,
|
||||
false});
|
||||
});
|
||||
}
|
||||
|
||||
auto disabledUsers =
|
||||
tabs.appendTab(new QVBoxLayout, "Excluded Users");
|
||||
{
|
||||
disabledUsers.emplace<QLabel>(
|
||||
"This is a list of users (e.g. bots) whose messages should "
|
||||
"<u>not</u> be highlighted.");
|
||||
EditableModelView *view =
|
||||
disabledUsers
|
||||
.emplace<EditableModelView>(
|
||||
app->highlights->createBlacklistModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->addRegexHelpLink();
|
||||
view->setTitles({"Pattern", "Enable\nregex"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
|
||||
// fourtf: make class extrend BaseWidget and add this to
|
||||
// dpiChanged
|
||||
QTimer::singleShot(1, [view] {
|
||||
view->getTableView()->resizeColumnsToContents();
|
||||
view->getTableView()->setColumnWidth(0, 200);
|
||||
});
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->highlights->blacklistedUsers.appendItem(
|
||||
HighlightBlacklistUser{"blacklisted user", false});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// MISC
|
||||
auto customSound = layout.emplace<QHBoxLayout>().withoutMargin();
|
||||
{
|
||||
customSound.append(this->createCheckBox(
|
||||
"Custom sound", getSettings()->customHighlightSound));
|
||||
auto selectFile =
|
||||
customSound.emplace<QPushButton>("Select custom sound file");
|
||||
QObject::connect(selectFile.getElement(), &QPushButton::clicked,
|
||||
this, [this] {
|
||||
auto fileName = QFileDialog::getOpenFileName(
|
||||
this, tr("Open Sound"), "",
|
||||
tr("Audio Files (*.mp3 *.wav)"));
|
||||
getSettings()->pathHighlightSound = fileName;
|
||||
});
|
||||
}
|
||||
|
||||
layout.append(createCheckBox(ALWAYS_PLAY,
|
||||
getSettings()->highlightAlwaysPlaySound));
|
||||
layout.append(createCheckBox(
|
||||
"Flash taskbar only stops highlighting when chatterino is focused",
|
||||
getSettings()->longAlerts));
|
||||
}
|
||||
|
||||
// ---- misc
|
||||
this->disabledUsersChangedTimer_.setSingleShot(true);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "HighlightingPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/highlights/HighlightBlacklistModel.hpp"
|
||||
#include "controllers/highlights/HighlightController.hpp"
|
||||
#include "controllers/highlights/HighlightModel.hpp"
|
||||
#include "controllers/highlights/UserHighlightModel.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "util/StandardItemHelper.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QHeaderView>
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTabWidget>
|
||||
#include <QTableView>
|
||||
#include <QTextEdit>
|
||||
|
||||
#define ENABLE_HIGHLIGHTS "Enable Highlighting"
|
||||
#define HIGHLIGHT_MSG "Highlight messages containing your name"
|
||||
#define PLAY_SOUND "Play sound when your name is mentioned"
|
||||
#define FLASH_TASKBAR "Flash taskbar when your name is mentioned"
|
||||
#define ALWAYS_PLAY "Play highlight sound even when Chatterino is focused"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
HighlightingPage::HighlightingPage()
|
||||
: SettingsPage("Highlights", ":/settings/notifications.svg")
|
||||
{
|
||||
auto app = getApp();
|
||||
LayoutCreator<HighlightingPage> layoutCreator(this);
|
||||
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||
{
|
||||
// GENERAL
|
||||
// layout.append(this->createCheckBox(ENABLE_HIGHLIGHTS,
|
||||
// getSettings()->enableHighlights));
|
||||
|
||||
// TABS
|
||||
auto tabs = layout.emplace<QTabWidget>();
|
||||
{
|
||||
// HIGHLIGHTS
|
||||
auto highlights = tabs.appendTab(new QVBoxLayout, "Messages");
|
||||
{
|
||||
highlights.emplace<QLabel>("Messages can be highlighted if "
|
||||
"they match a certain pattern.");
|
||||
|
||||
EditableModelView *view =
|
||||
highlights
|
||||
.emplace<EditableModelView>(
|
||||
app->highlights->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->addRegexHelpLink();
|
||||
view->setTitles({"Pattern", "Flash\ntaskbar", "Play\nsound",
|
||||
"Enable\nregex", "Case-\nsensitive"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
|
||||
// fourtf: make class extrend BaseWidget and add this to
|
||||
// dpiChanged
|
||||
QTimer::singleShot(1, [view] {
|
||||
view->getTableView()->resizeColumnsToContents();
|
||||
view->getTableView()->setColumnWidth(0, 200);
|
||||
});
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->highlights->phrases.appendItem(HighlightPhrase{
|
||||
"my phrase", true, false, false, false});
|
||||
});
|
||||
}
|
||||
|
||||
auto pingUsers = tabs.appendTab(new QVBoxLayout, "Users");
|
||||
{
|
||||
pingUsers.emplace<QLabel>(
|
||||
"Messages from a certain user can be highlighted.");
|
||||
EditableModelView *view =
|
||||
pingUsers
|
||||
.emplace<EditableModelView>(
|
||||
app->highlights->createUserModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->addRegexHelpLink();
|
||||
view->getTableView()->horizontalHeader()->hideSection(4);
|
||||
|
||||
// Case-sensitivity doesn't make sense for user names so it is
|
||||
// set to "false" by default & no checkbox is shown
|
||||
view->setTitles({"Username", "Flash\ntaskbar", "Play\nsound",
|
||||
"Enable\nregex"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
|
||||
// fourtf: make class extrend BaseWidget and add this to
|
||||
// dpiChanged
|
||||
QTimer::singleShot(1, [view] {
|
||||
view->getTableView()->resizeColumnsToContents();
|
||||
view->getTableView()->setColumnWidth(0, 200);
|
||||
});
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->highlights->highlightedUsers.appendItem(
|
||||
HighlightPhrase{"highlighted user", true, false, false,
|
||||
false});
|
||||
});
|
||||
}
|
||||
|
||||
auto disabledUsers =
|
||||
tabs.appendTab(new QVBoxLayout, "Excluded Users");
|
||||
{
|
||||
disabledUsers.emplace<QLabel>(
|
||||
"This is a list of users (e.g. bots) whose messages should "
|
||||
"<u>not</u> be highlighted.");
|
||||
EditableModelView *view =
|
||||
disabledUsers
|
||||
.emplace<EditableModelView>(
|
||||
app->highlights->createBlacklistModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->addRegexHelpLink();
|
||||
view->setTitles({"Pattern", "Enable\nregex"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
|
||||
// fourtf: make class extrend BaseWidget and add this to
|
||||
// dpiChanged
|
||||
QTimer::singleShot(1, [view] {
|
||||
view->getTableView()->resizeColumnsToContents();
|
||||
view->getTableView()->setColumnWidth(0, 200);
|
||||
});
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->highlights->blacklistedUsers.appendItem(
|
||||
HighlightBlacklistUser{"blacklisted user", false});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// MISC
|
||||
auto customSound = layout.emplace<QHBoxLayout>().withoutMargin();
|
||||
{
|
||||
customSound.append(this->createCheckBox(
|
||||
"Custom sound", getSettings()->customHighlightSound));
|
||||
auto selectFile =
|
||||
customSound.emplace<QPushButton>("Select custom sound file");
|
||||
QObject::connect(selectFile.getElement(), &QPushButton::clicked,
|
||||
this, [this] {
|
||||
auto fileName = QFileDialog::getOpenFileName(
|
||||
this, tr("Open Sound"), "",
|
||||
tr("Audio Files (*.mp3 *.wav)"));
|
||||
getSettings()->pathHighlightSound = fileName;
|
||||
});
|
||||
}
|
||||
|
||||
layout.append(createCheckBox(ALWAYS_PLAY,
|
||||
getSettings()->highlightAlwaysPlaySound));
|
||||
layout.append(createCheckBox(
|
||||
"Flash taskbar only stops highlighting when chatterino is focused",
|
||||
getSettings()->longAlerts));
|
||||
}
|
||||
|
||||
// ---- misc
|
||||
this->disabledUsersChangedTimer_.setSingleShot(true);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QTimer>
|
||||
|
||||
class QPushButton;
|
||||
class QListWidget;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class HighlightingPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
HighlightingPage();
|
||||
|
||||
private:
|
||||
QTimer disabledUsersChangedTimer_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QTimer>
|
||||
|
||||
class QPushButton;
|
||||
class QListWidget;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class HighlightingPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
HighlightingPage();
|
||||
|
||||
private:
|
||||
QTimer disabledUsersChangedTimer_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,133 +1,133 @@
|
||||
#include "IgnoresPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "controllers/ignores/IgnoreController.hpp"
|
||||
#include "controllers/ignores/IgnoreModel.hpp"
|
||||
#include "providers/twitch/TwitchAccount.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QGroupBox>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QListView>
|
||||
#include <QPushButton>
|
||||
#include <QTableView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
// clang-format off
|
||||
#define INFO "/ignore <user> in chat ignores a user.\n/unignore <user> in chat unignores a user.\nYou can also click on a user to open the usercard."
|
||||
// clang-format on
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
static void addPhrasesTab(LayoutCreator<QVBoxLayout> box);
|
||||
static void addUsersTab(IgnoresPage &page, LayoutCreator<QVBoxLayout> box,
|
||||
QStringListModel &model);
|
||||
|
||||
IgnoresPage::IgnoresPage()
|
||||
: SettingsPage("Ignores", ":/settings/ignore.svg")
|
||||
{
|
||||
LayoutCreator<IgnoresPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
|
||||
auto tabs = layout.emplace<QTabWidget>();
|
||||
|
||||
addPhrasesTab(tabs.appendTab(new QVBoxLayout, "Messages"));
|
||||
addUsersTab(*this, tabs.appendTab(new QVBoxLayout, "Users"),
|
||||
this->userListModel_);
|
||||
}
|
||||
|
||||
void addPhrasesTab(LayoutCreator<QVBoxLayout> layout)
|
||||
{
|
||||
layout.emplace<QLabel>("Messages can be ignored if "
|
||||
"they match a certain pattern.");
|
||||
EditableModelView *view =
|
||||
layout
|
||||
.emplace<EditableModelView>(getApp()->ignores->createModel(nullptr))
|
||||
.getElement();
|
||||
view->setTitles(
|
||||
{"Pattern", "Regex", "Case Sensitive", "Block", "Replacement"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
view->addRegexHelpLink();
|
||||
|
||||
QTimer::singleShot(1, [view] {
|
||||
view->getTableView()->resizeColumnsToContents();
|
||||
view->getTableView()->setColumnWidth(0, 200);
|
||||
});
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->ignores->phrases.appendItem(
|
||||
IgnorePhrase{"my pattern", false, false,
|
||||
getSettings()->ignoredPhraseReplace.getValue(), true});
|
||||
});
|
||||
}
|
||||
|
||||
void addUsersTab(IgnoresPage &page, LayoutCreator<QVBoxLayout> users,
|
||||
QStringListModel &userModel)
|
||||
{
|
||||
auto label = users.emplace<QLabel>(INFO);
|
||||
label->setWordWrap(true);
|
||||
users.append(page.createCheckBox("Enable twitch ignored users",
|
||||
getSettings()->enableTwitchIgnoredUsers));
|
||||
|
||||
auto anyways = users.emplace<QHBoxLayout>().withoutMargin();
|
||||
{
|
||||
anyways.emplace<QLabel>("Show messages from ignored users anyways:");
|
||||
|
||||
auto combo = anyways.emplace<QComboBox>().getElement();
|
||||
combo->addItems(
|
||||
{"Never", "If you are Moderator", "If you are Broadcaster"});
|
||||
|
||||
auto &setting = getSettings()->showIgnoredUsersMessages;
|
||||
|
||||
setting.connect(
|
||||
[combo](const int value) { combo->setCurrentIndex(value); });
|
||||
|
||||
QObject::connect(combo,
|
||||
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
[&setting](int index) {
|
||||
if (index != -1)
|
||||
setting = index;
|
||||
});
|
||||
|
||||
anyways->addStretch(1);
|
||||
}
|
||||
|
||||
/*auto addremove = users.emplace<QHBoxLayout>().withoutMargin();
|
||||
{
|
||||
auto add = addremove.emplace<QPushButton>("Ignore user");
|
||||
auto remove = addremove.emplace<QPushButton>("Unignore User");
|
||||
addremove->addStretch(1);
|
||||
}*/
|
||||
|
||||
users.emplace<QLabel>("List of ignored users:");
|
||||
users.emplace<QListView>()->setModel(&userModel);
|
||||
}
|
||||
|
||||
void IgnoresPage::onShow()
|
||||
{
|
||||
auto app = getApp();
|
||||
|
||||
auto user = app->accounts->twitch.getCurrent();
|
||||
|
||||
if (user->isAnon())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList users;
|
||||
for (const auto &ignoredUser : user->getIgnores())
|
||||
{
|
||||
users << ignoredUser.name;
|
||||
}
|
||||
users.sort(Qt::CaseInsensitive);
|
||||
this->userListModel_.setStringList(users);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "IgnoresPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "controllers/ignores/IgnoreController.hpp"
|
||||
#include "controllers/ignores/IgnoreModel.hpp"
|
||||
#include "providers/twitch/TwitchAccount.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QGroupBox>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QListView>
|
||||
#include <QPushButton>
|
||||
#include <QTableView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
// clang-format off
|
||||
#define INFO "/ignore <user> in chat ignores a user.\n/unignore <user> in chat unignores a user.\nYou can also click on a user to open the usercard."
|
||||
// clang-format on
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
static void addPhrasesTab(LayoutCreator<QVBoxLayout> box);
|
||||
static void addUsersTab(IgnoresPage &page, LayoutCreator<QVBoxLayout> box,
|
||||
QStringListModel &model);
|
||||
|
||||
IgnoresPage::IgnoresPage()
|
||||
: SettingsPage("Ignores", ":/settings/ignore.svg")
|
||||
{
|
||||
LayoutCreator<IgnoresPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
|
||||
auto tabs = layout.emplace<QTabWidget>();
|
||||
|
||||
addPhrasesTab(tabs.appendTab(new QVBoxLayout, "Messages"));
|
||||
addUsersTab(*this, tabs.appendTab(new QVBoxLayout, "Users"),
|
||||
this->userListModel_);
|
||||
}
|
||||
|
||||
void addPhrasesTab(LayoutCreator<QVBoxLayout> layout)
|
||||
{
|
||||
layout.emplace<QLabel>("Messages can be ignored if "
|
||||
"they match a certain pattern.");
|
||||
EditableModelView *view =
|
||||
layout
|
||||
.emplace<EditableModelView>(getApp()->ignores->createModel(nullptr))
|
||||
.getElement();
|
||||
view->setTitles(
|
||||
{"Pattern", "Regex", "Case Sensitive", "Block", "Replacement"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
view->addRegexHelpLink();
|
||||
|
||||
QTimer::singleShot(1, [view] {
|
||||
view->getTableView()->resizeColumnsToContents();
|
||||
view->getTableView()->setColumnWidth(0, 200);
|
||||
});
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->ignores->phrases.appendItem(
|
||||
IgnorePhrase{"my pattern", false, false,
|
||||
getSettings()->ignoredPhraseReplace.getValue(), true});
|
||||
});
|
||||
}
|
||||
|
||||
void addUsersTab(IgnoresPage &page, LayoutCreator<QVBoxLayout> users,
|
||||
QStringListModel &userModel)
|
||||
{
|
||||
auto label = users.emplace<QLabel>(INFO);
|
||||
label->setWordWrap(true);
|
||||
users.append(page.createCheckBox("Enable twitch ignored users",
|
||||
getSettings()->enableTwitchIgnoredUsers));
|
||||
|
||||
auto anyways = users.emplace<QHBoxLayout>().withoutMargin();
|
||||
{
|
||||
anyways.emplace<QLabel>("Show messages from ignored users anyways:");
|
||||
|
||||
auto combo = anyways.emplace<QComboBox>().getElement();
|
||||
combo->addItems(
|
||||
{"Never", "If you are Moderator", "If you are Broadcaster"});
|
||||
|
||||
auto &setting = getSettings()->showIgnoredUsersMessages;
|
||||
|
||||
setting.connect(
|
||||
[combo](const int value) { combo->setCurrentIndex(value); });
|
||||
|
||||
QObject::connect(combo,
|
||||
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
[&setting](int index) {
|
||||
if (index != -1)
|
||||
setting = index;
|
||||
});
|
||||
|
||||
anyways->addStretch(1);
|
||||
}
|
||||
|
||||
/*auto addremove = users.emplace<QHBoxLayout>().withoutMargin();
|
||||
{
|
||||
auto add = addremove.emplace<QPushButton>("Ignore user");
|
||||
auto remove = addremove.emplace<QPushButton>("Unignore User");
|
||||
addremove->addStretch(1);
|
||||
}*/
|
||||
|
||||
users.emplace<QLabel>("List of ignored users:");
|
||||
users.emplace<QListView>()->setModel(&userModel);
|
||||
}
|
||||
|
||||
void IgnoresPage::onShow()
|
||||
{
|
||||
auto app = getApp();
|
||||
|
||||
auto user = app->accounts->twitch.getCurrent();
|
||||
|
||||
if (user->isAnon())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList users;
|
||||
for (const auto &ignoredUser : user->getIgnores())
|
||||
{
|
||||
users << ignoredUser.name;
|
||||
}
|
||||
users.sort(Qt::CaseInsensitive);
|
||||
this->userListModel_.setStringList(users);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
#include <QStringListModel>
|
||||
|
||||
class QVBoxLayout;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class IgnoresPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
IgnoresPage();
|
||||
|
||||
void onShow() final;
|
||||
|
||||
private:
|
||||
QStringListModel userListModel_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
#include <QStringListModel>
|
||||
|
||||
class QVBoxLayout;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class IgnoresPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
IgnoresPage();
|
||||
|
||||
void onShow() final;
|
||||
|
||||
private:
|
||||
QStringListModel userListModel_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
#include "KeyboardSettingsPage.hpp"
|
||||
|
||||
#include "util/LayoutCreator.hpp"
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
KeyboardSettingsPage::KeyboardSettingsPage()
|
||||
: SettingsPage("Keybindings", ":/settings/keybinds.svg")
|
||||
{
|
||||
auto layout =
|
||||
LayoutCreator<KeyboardSettingsPage>(this).setLayoutType<QVBoxLayout>();
|
||||
|
||||
auto form = layout.emplace<QFormLayout>().withoutMargin();
|
||||
|
||||
form->addRow(new QLabel("Hold Ctrl"), new QLabel("Show resize handles"));
|
||||
form->addRow(new QLabel("Hold Ctrl + Alt"),
|
||||
new QLabel("Show split overlay"));
|
||||
|
||||
form->addItem(new QSpacerItem(16, 16));
|
||||
form->addRow(new QLabel("Ctrl + T"), new QLabel("Create new split"));
|
||||
form->addRow(new QLabel("Ctrl + W"), new QLabel("Close current split"));
|
||||
|
||||
form->addRow(new QLabel("Ctrl + Shift + T"), new QLabel("Create new tab"));
|
||||
form->addRow(new QLabel("Ctrl + Shift + W"),
|
||||
new QLabel("Close current tab"));
|
||||
|
||||
form->addItem(new QSpacerItem(16, 16));
|
||||
form->addRow(new QLabel("Ctrl + 1/2/3/..."),
|
||||
new QLabel("Select tab 1/2/3/..."));
|
||||
form->addRow(new QLabel("Ctrl + Tab"), new QLabel("Select next tab"));
|
||||
form->addRow(new QLabel("Ctrl + Shift + Tab"),
|
||||
new QLabel("Select previous tab"));
|
||||
|
||||
form->addRow(new QLabel("Alt + Left/Up/Right/Down"),
|
||||
new QLabel("Select split left/up/right/down"));
|
||||
|
||||
form->addItem(new QSpacerItem(16, 16));
|
||||
form->addRow(new QLabel("Ctrl + R"), new QLabel("Change channel"));
|
||||
form->addRow(new QLabel("Ctrl + F"),
|
||||
new QLabel("Search in current channel"));
|
||||
form->addRow(new QLabel("Ctrl + E"), new QLabel("Open Emote menu"));
|
||||
form->addRow(new QLabel("Ctrl + P"), new QLabel("Open Settings menu"));
|
||||
form->addRow(new QLabel("F5"),
|
||||
new QLabel("Reload subscriber and channel emotes"));
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "KeyboardSettingsPage.hpp"
|
||||
|
||||
#include "util/LayoutCreator.hpp"
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
KeyboardSettingsPage::KeyboardSettingsPage()
|
||||
: SettingsPage("Keybindings", ":/settings/keybinds.svg")
|
||||
{
|
||||
auto layout =
|
||||
LayoutCreator<KeyboardSettingsPage>(this).setLayoutType<QVBoxLayout>();
|
||||
|
||||
auto form = layout.emplace<QFormLayout>().withoutMargin();
|
||||
|
||||
form->addRow(new QLabel("Hold Ctrl"), new QLabel("Show resize handles"));
|
||||
form->addRow(new QLabel("Hold Ctrl + Alt"),
|
||||
new QLabel("Show split overlay"));
|
||||
|
||||
form->addItem(new QSpacerItem(16, 16));
|
||||
form->addRow(new QLabel("Ctrl + T"), new QLabel("Create new split"));
|
||||
form->addRow(new QLabel("Ctrl + W"), new QLabel("Close current split"));
|
||||
|
||||
form->addRow(new QLabel("Ctrl + Shift + T"), new QLabel("Create new tab"));
|
||||
form->addRow(new QLabel("Ctrl + Shift + W"),
|
||||
new QLabel("Close current tab"));
|
||||
|
||||
form->addItem(new QSpacerItem(16, 16));
|
||||
form->addRow(new QLabel("Ctrl + 1/2/3/..."),
|
||||
new QLabel("Select tab 1/2/3/..."));
|
||||
form->addRow(new QLabel("Ctrl + Tab"), new QLabel("Select next tab"));
|
||||
form->addRow(new QLabel("Ctrl + Shift + Tab"),
|
||||
new QLabel("Select previous tab"));
|
||||
|
||||
form->addRow(new QLabel("Alt + Left/Up/Right/Down"),
|
||||
new QLabel("Select split left/up/right/down"));
|
||||
|
||||
form->addItem(new QSpacerItem(16, 16));
|
||||
form->addRow(new QLabel("Ctrl + R"), new QLabel("Change channel"));
|
||||
form->addRow(new QLabel("Ctrl + F"),
|
||||
new QLabel("Search in current channel"));
|
||||
form->addRow(new QLabel("Ctrl + E"), new QLabel("Open Emote menu"));
|
||||
form->addRow(new QLabel("Ctrl + P"), new QLabel("Open Settings menu"));
|
||||
form->addRow(new QLabel("F5"),
|
||||
new QLabel("Reload subscriber and channel emotes"));
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class KeyboardSettingsPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
KeyboardSettingsPage();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class KeyboardSettingsPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
KeyboardSettingsPage();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,216 +1,216 @@
|
||||
#include "ModerationPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/moderationactions/ModerationActionModel.hpp"
|
||||
#include "controllers/moderationactions/ModerationActions.hpp"
|
||||
#include "controllers/taggedusers/TaggedUsersController.hpp"
|
||||
#include "controllers/taggedusers/TaggedUsersModel.hpp"
|
||||
#include "singletons/Logging.hpp"
|
||||
#include "singletons/Paths.hpp"
|
||||
#include "util/Helpers.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QListView>
|
||||
#include <QPushButton>
|
||||
#include <QTableView>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
qint64 dirSize(QString dirPath)
|
||||
{
|
||||
qint64 size = 0;
|
||||
QDir dir(dirPath);
|
||||
// calculate total size of current directories' files
|
||||
QDir::Filters fileFilters = QDir::Files | QDir::System | QDir::Hidden;
|
||||
for (QString filePath : dir.entryList(fileFilters))
|
||||
{
|
||||
QFileInfo fi(dir, filePath);
|
||||
size += fi.size();
|
||||
}
|
||||
// add size of child directories recursively
|
||||
QDir::Filters dirFilters =
|
||||
QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden;
|
||||
for (QString childDirPath : dir.entryList(dirFilters))
|
||||
size += dirSize(dirPath + QDir::separator() + childDirPath);
|
||||
return size;
|
||||
}
|
||||
|
||||
QString formatSize(qint64 size)
|
||||
{
|
||||
QStringList units = {"Bytes", "KB", "MB", "GB", "TB", "PB"};
|
||||
int i;
|
||||
double outputSize = size;
|
||||
for (i = 0; i < units.size() - 1; i++)
|
||||
{
|
||||
if (outputSize < 1024)
|
||||
break;
|
||||
outputSize = outputSize / 1024;
|
||||
}
|
||||
return QString("%0 %1").arg(outputSize, 0, 'f', 2).arg(units[i]);
|
||||
}
|
||||
|
||||
QString fetchLogDirectorySize()
|
||||
{
|
||||
QString logPathDirectory = getSettings()->logPath.getValue().isEmpty()
|
||||
? getPaths()->messageLogDirectory
|
||||
: getSettings()->logPath;
|
||||
|
||||
qint64 logsSize = dirSize(logPathDirectory);
|
||||
QString logsSizeLabel = "Your logs currently take up ";
|
||||
logsSizeLabel += formatSize(logsSize);
|
||||
logsSizeLabel += " of space";
|
||||
return logsSizeLabel;
|
||||
}
|
||||
|
||||
ModerationPage::ModerationPage()
|
||||
: SettingsPage("Moderation", ":/settings/moderation.svg")
|
||||
{
|
||||
auto app = getApp();
|
||||
LayoutCreator<ModerationPage> layoutCreator(this);
|
||||
|
||||
auto tabs = layoutCreator.emplace<QTabWidget>();
|
||||
this->tabWidget_ = tabs.getElement();
|
||||
|
||||
auto logs = tabs.appendTab(new QVBoxLayout, "Logs");
|
||||
{
|
||||
logs.append(this->createCheckBox("Enable logging",
|
||||
getSettings()->enableLogging));
|
||||
auto logsPathLabel = logs.emplace<QLabel>();
|
||||
|
||||
// Logs (copied from LoggingMananger)
|
||||
getSettings()->logPath.connect([logsPathLabel](const QString &logPath,
|
||||
auto) mutable {
|
||||
QString pathOriginal =
|
||||
logPath.isEmpty() ? getPaths()->messageLogDirectory : logPath;
|
||||
|
||||
QString pathShortened =
|
||||
"Logs are saved at <a href=\"file:///" + pathOriginal +
|
||||
"\"><span style=\"color: white;\">" +
|
||||
shortenString(pathOriginal, 50) + "</span></a>";
|
||||
|
||||
logsPathLabel->setText(pathShortened);
|
||||
logsPathLabel->setToolTip(pathOriginal);
|
||||
});
|
||||
|
||||
logsPathLabel->setTextFormat(Qt::RichText);
|
||||
logsPathLabel->setTextInteractionFlags(Qt::TextBrowserInteraction |
|
||||
Qt::LinksAccessibleByKeyboard);
|
||||
logsPathLabel->setOpenExternalLinks(true);
|
||||
|
||||
auto buttons = logs.emplace<QHBoxLayout>().withoutMargin();
|
||||
|
||||
// Select and Reset
|
||||
auto selectDir = buttons.emplace<QPushButton>("Select log directory ");
|
||||
auto resetDir = buttons.emplace<QPushButton>("Reset");
|
||||
|
||||
getSettings()->logPath.connect(
|
||||
[element = resetDir.getElement()](const QString &path) {
|
||||
element->setEnabled(!path.isEmpty());
|
||||
});
|
||||
|
||||
buttons->addStretch();
|
||||
logs->addStretch(1);
|
||||
|
||||
// Show how big (size-wise) the logs are
|
||||
auto logsPathSizeLabel = logs.emplace<QLabel>();
|
||||
logsPathSizeLabel->setText(
|
||||
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
|
||||
|
||||
// Select event
|
||||
QObject::connect(
|
||||
selectDir.getElement(), &QPushButton::clicked, this,
|
||||
[this, logsPathSizeLabel]() mutable {
|
||||
auto dirName = QFileDialog::getExistingDirectory(this);
|
||||
|
||||
getSettings()->logPath = dirName;
|
||||
|
||||
// Refresh: Show how big (size-wise) the logs are
|
||||
logsPathSizeLabel->setText(
|
||||
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
|
||||
});
|
||||
|
||||
buttons->addSpacing(16);
|
||||
|
||||
// Reset custom logpath
|
||||
QObject::connect(resetDir.getElement(), &QPushButton::clicked, this,
|
||||
[logsPathSizeLabel]() mutable {
|
||||
getSettings()->logPath = "";
|
||||
|
||||
// Refresh: Show how big (size-wise) the logs are
|
||||
logsPathSizeLabel->setText(QtConcurrent::run(
|
||||
[] { return fetchLogDirectorySize(); }));
|
||||
});
|
||||
|
||||
} // logs end
|
||||
|
||||
auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation buttons");
|
||||
{
|
||||
// clang-format off
|
||||
auto label = modMode.emplace<QLabel>(
|
||||
"Moderation mode is enabled by clicking <img width='18' height='18' src=':/buttons/modModeDisabled.png'> in a channel that you moderate.<br><br>"
|
||||
"Moderation buttons can be bound to chat commands such as \"/ban {user}\", \"/timeout {user} 1000\", \"/w someusername !report {user} was bad in channel {channel}\" or any other custom text commands.<br>"
|
||||
"For deleting messages use /delete {msg-id}.");
|
||||
label->setWordWrap(true);
|
||||
label->setStyleSheet("color: #bbb");
|
||||
// clang-format on
|
||||
|
||||
// auto form = modMode.emplace<QFormLayout>();
|
||||
// {
|
||||
// form->addRow("Action on timed out messages
|
||||
// (unimplemented):",
|
||||
// this->createComboBox({"Disable", "Hide"},
|
||||
// getSettings()->timeoutAction));
|
||||
// }
|
||||
|
||||
EditableModelView *view =
|
||||
modMode
|
||||
.emplace<EditableModelView>(
|
||||
app->moderationActions->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->setTitles({"Actions"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->moderationActions->items.appendItem(
|
||||
ModerationAction("/timeout {user} 300"));
|
||||
});
|
||||
|
||||
/*auto taggedUsers = tabs.appendTab(new QVBoxLayout, "Tagged users");
|
||||
{
|
||||
EditableModelView *view = *taggedUsers.emplace<EditableModelView>(
|
||||
app->taggedUsers->createModel(nullptr));
|
||||
|
||||
view->setTitles({"Name"});
|
||||
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->taggedUsers->users.appendItem(
|
||||
TaggedUser(ProviderId::Twitch, "example", "xD"));
|
||||
});
|
||||
}*/
|
||||
}
|
||||
|
||||
// ---- misc
|
||||
this->itemsChangedTimer_.setSingleShot(true);
|
||||
}
|
||||
|
||||
void ModerationPage::selectModerationActions()
|
||||
{
|
||||
this->tabWidget_->setCurrentIndex(1);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "ModerationPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "controllers/moderationactions/ModerationActionModel.hpp"
|
||||
#include "controllers/moderationactions/ModerationActions.hpp"
|
||||
#include "controllers/taggedusers/TaggedUsersController.hpp"
|
||||
#include "controllers/taggedusers/TaggedUsersModel.hpp"
|
||||
#include "singletons/Logging.hpp"
|
||||
#include "singletons/Paths.hpp"
|
||||
#include "util/Helpers.hpp"
|
||||
#include "util/LayoutCreator.hpp"
|
||||
#include "widgets/helper/EditableModelView.hpp"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QListView>
|
||||
#include <QPushButton>
|
||||
#include <QTableView>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
qint64 dirSize(QString dirPath)
|
||||
{
|
||||
qint64 size = 0;
|
||||
QDir dir(dirPath);
|
||||
// calculate total size of current directories' files
|
||||
QDir::Filters fileFilters = QDir::Files | QDir::System | QDir::Hidden;
|
||||
for (QString filePath : dir.entryList(fileFilters))
|
||||
{
|
||||
QFileInfo fi(dir, filePath);
|
||||
size += fi.size();
|
||||
}
|
||||
// add size of child directories recursively
|
||||
QDir::Filters dirFilters =
|
||||
QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden;
|
||||
for (QString childDirPath : dir.entryList(dirFilters))
|
||||
size += dirSize(dirPath + QDir::separator() + childDirPath);
|
||||
return size;
|
||||
}
|
||||
|
||||
QString formatSize(qint64 size)
|
||||
{
|
||||
QStringList units = {"Bytes", "KB", "MB", "GB", "TB", "PB"};
|
||||
int i;
|
||||
double outputSize = size;
|
||||
for (i = 0; i < units.size() - 1; i++)
|
||||
{
|
||||
if (outputSize < 1024)
|
||||
break;
|
||||
outputSize = outputSize / 1024;
|
||||
}
|
||||
return QString("%0 %1").arg(outputSize, 0, 'f', 2).arg(units[i]);
|
||||
}
|
||||
|
||||
QString fetchLogDirectorySize()
|
||||
{
|
||||
QString logPathDirectory = getSettings()->logPath.getValue().isEmpty()
|
||||
? getPaths()->messageLogDirectory
|
||||
: getSettings()->logPath;
|
||||
|
||||
qint64 logsSize = dirSize(logPathDirectory);
|
||||
QString logsSizeLabel = "Your logs currently take up ";
|
||||
logsSizeLabel += formatSize(logsSize);
|
||||
logsSizeLabel += " of space";
|
||||
return logsSizeLabel;
|
||||
}
|
||||
|
||||
ModerationPage::ModerationPage()
|
||||
: SettingsPage("Moderation", ":/settings/moderation.svg")
|
||||
{
|
||||
auto app = getApp();
|
||||
LayoutCreator<ModerationPage> layoutCreator(this);
|
||||
|
||||
auto tabs = layoutCreator.emplace<QTabWidget>();
|
||||
this->tabWidget_ = tabs.getElement();
|
||||
|
||||
auto logs = tabs.appendTab(new QVBoxLayout, "Logs");
|
||||
{
|
||||
logs.append(this->createCheckBox("Enable logging",
|
||||
getSettings()->enableLogging));
|
||||
auto logsPathLabel = logs.emplace<QLabel>();
|
||||
|
||||
// Logs (copied from LoggingMananger)
|
||||
getSettings()->logPath.connect([logsPathLabel](const QString &logPath,
|
||||
auto) mutable {
|
||||
QString pathOriginal =
|
||||
logPath.isEmpty() ? getPaths()->messageLogDirectory : logPath;
|
||||
|
||||
QString pathShortened =
|
||||
"Logs are saved at <a href=\"file:///" + pathOriginal +
|
||||
"\"><span style=\"color: white;\">" +
|
||||
shortenString(pathOriginal, 50) + "</span></a>";
|
||||
|
||||
logsPathLabel->setText(pathShortened);
|
||||
logsPathLabel->setToolTip(pathOriginal);
|
||||
});
|
||||
|
||||
logsPathLabel->setTextFormat(Qt::RichText);
|
||||
logsPathLabel->setTextInteractionFlags(Qt::TextBrowserInteraction |
|
||||
Qt::LinksAccessibleByKeyboard);
|
||||
logsPathLabel->setOpenExternalLinks(true);
|
||||
|
||||
auto buttons = logs.emplace<QHBoxLayout>().withoutMargin();
|
||||
|
||||
// Select and Reset
|
||||
auto selectDir = buttons.emplace<QPushButton>("Select log directory ");
|
||||
auto resetDir = buttons.emplace<QPushButton>("Reset");
|
||||
|
||||
getSettings()->logPath.connect(
|
||||
[element = resetDir.getElement()](const QString &path) {
|
||||
element->setEnabled(!path.isEmpty());
|
||||
});
|
||||
|
||||
buttons->addStretch();
|
||||
logs->addStretch(1);
|
||||
|
||||
// Show how big (size-wise) the logs are
|
||||
auto logsPathSizeLabel = logs.emplace<QLabel>();
|
||||
logsPathSizeLabel->setText(
|
||||
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
|
||||
|
||||
// Select event
|
||||
QObject::connect(
|
||||
selectDir.getElement(), &QPushButton::clicked, this,
|
||||
[this, logsPathSizeLabel]() mutable {
|
||||
auto dirName = QFileDialog::getExistingDirectory(this);
|
||||
|
||||
getSettings()->logPath = dirName;
|
||||
|
||||
// Refresh: Show how big (size-wise) the logs are
|
||||
logsPathSizeLabel->setText(
|
||||
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
|
||||
});
|
||||
|
||||
buttons->addSpacing(16);
|
||||
|
||||
// Reset custom logpath
|
||||
QObject::connect(resetDir.getElement(), &QPushButton::clicked, this,
|
||||
[logsPathSizeLabel]() mutable {
|
||||
getSettings()->logPath = "";
|
||||
|
||||
// Refresh: Show how big (size-wise) the logs are
|
||||
logsPathSizeLabel->setText(QtConcurrent::run(
|
||||
[] { return fetchLogDirectorySize(); }));
|
||||
});
|
||||
|
||||
} // logs end
|
||||
|
||||
auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation buttons");
|
||||
{
|
||||
// clang-format off
|
||||
auto label = modMode.emplace<QLabel>(
|
||||
"Moderation mode is enabled by clicking <img width='18' height='18' src=':/buttons/modModeDisabled.png'> in a channel that you moderate.<br><br>"
|
||||
"Moderation buttons can be bound to chat commands such as \"/ban {user}\", \"/timeout {user} 1000\", \"/w someusername !report {user} was bad in channel {channel}\" or any other custom text commands.<br>"
|
||||
"For deleting messages use /delete {msg-id}.");
|
||||
label->setWordWrap(true);
|
||||
label->setStyleSheet("color: #bbb");
|
||||
// clang-format on
|
||||
|
||||
// auto form = modMode.emplace<QFormLayout>();
|
||||
// {
|
||||
// form->addRow("Action on timed out messages
|
||||
// (unimplemented):",
|
||||
// this->createComboBox({"Disable", "Hide"},
|
||||
// getSettings()->timeoutAction));
|
||||
// }
|
||||
|
||||
EditableModelView *view =
|
||||
modMode
|
||||
.emplace<EditableModelView>(
|
||||
app->moderationActions->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->setTitles({"Actions"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::Fixed);
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
0, QHeaderView::Stretch);
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->moderationActions->items.appendItem(
|
||||
ModerationAction("/timeout {user} 300"));
|
||||
});
|
||||
|
||||
/*auto taggedUsers = tabs.appendTab(new QVBoxLayout, "Tagged users");
|
||||
{
|
||||
EditableModelView *view = *taggedUsers.emplace<EditableModelView>(
|
||||
app->taggedUsers->createModel(nullptr));
|
||||
|
||||
view->setTitles({"Name"});
|
||||
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
|
||||
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->taggedUsers->users.appendItem(
|
||||
TaggedUser(ProviderId::Twitch, "example", "xD"));
|
||||
});
|
||||
}*/
|
||||
}
|
||||
|
||||
// ---- misc
|
||||
this->itemsChangedTimer_.setSingleShot(true);
|
||||
}
|
||||
|
||||
void ModerationPage::selectModerationActions()
|
||||
{
|
||||
this->tabWidget_->setCurrentIndex(1);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
class QTabWidget;
|
||||
class QPushButton;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class ModerationPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
ModerationPage();
|
||||
|
||||
void selectModerationActions();
|
||||
|
||||
private:
|
||||
QTimer itemsChangedTimer_;
|
||||
QTabWidget *tabWidget_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "widgets/settingspages/SettingsPage.hpp"
|
||||
|
||||
class QTabWidget;
|
||||
class QPushButton;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class ModerationPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
ModerationPage();
|
||||
|
||||
void selectModerationActions();
|
||||
|
||||
private:
|
||||
QTimer itemsChangedTimer_;
|
||||
QTabWidget *tabWidget_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,176 +1,176 @@
|
||||
#include "SettingsPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "singletons/WindowManager.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <util/FunctionEventFilter.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
bool filterItemsRec(QObject *object, const QString &query)
|
||||
{
|
||||
bool any{};
|
||||
|
||||
for (auto &&child : object->children())
|
||||
{
|
||||
auto setOpacity = [&](auto *widget, bool condition) {
|
||||
any |= condition;
|
||||
widget->greyedOut = !condition;
|
||||
widget->update();
|
||||
};
|
||||
|
||||
if (auto x = dynamic_cast<SCheckBox *>(child); x)
|
||||
{
|
||||
setOpacity(x, x->text().contains(query, Qt::CaseInsensitive));
|
||||
}
|
||||
else if (auto x = dynamic_cast<SLabel *>(child); x)
|
||||
{
|
||||
setOpacity(x, x->text().contains(query, Qt::CaseInsensitive));
|
||||
}
|
||||
else if (auto x = dynamic_cast<SComboBox *>(child); x)
|
||||
{
|
||||
setOpacity(x, [=]() {
|
||||
for (int i = 0; i < x->count(); i++)
|
||||
{
|
||||
if (x->itemText(i).contains(query, Qt::CaseInsensitive))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}());
|
||||
}
|
||||
else if (auto x = dynamic_cast<QTabWidget *>(child); x)
|
||||
{
|
||||
for (int i = 0; i < x->count(); i++)
|
||||
{
|
||||
bool tabAny{};
|
||||
|
||||
if (x->tabText(i).contains(query, Qt::CaseInsensitive))
|
||||
{
|
||||
tabAny = true;
|
||||
}
|
||||
auto widget = x->widget(i);
|
||||
tabAny |= filterItemsRec(widget, query);
|
||||
|
||||
any |= tabAny;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
any |= filterItemsRec(child, query);
|
||||
}
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
SettingsPage::SettingsPage(const QString &name, const QString &iconResource)
|
||||
: name_(name)
|
||||
, iconResource_(iconResource)
|
||||
{
|
||||
}
|
||||
|
||||
bool SettingsPage::filterElements(const QString &query)
|
||||
{
|
||||
return filterItemsRec(this, query) || query.isEmpty() ||
|
||||
this->name_.contains(query, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
const QString &SettingsPage::getName()
|
||||
{
|
||||
return this->name_;
|
||||
}
|
||||
|
||||
const QString &SettingsPage::getIconResource()
|
||||
{
|
||||
return this->iconResource_;
|
||||
}
|
||||
|
||||
SettingsDialogTab *SettingsPage::tab() const
|
||||
{
|
||||
return this->tab_;
|
||||
}
|
||||
|
||||
void SettingsPage::setTab(SettingsDialogTab *tab)
|
||||
{
|
||||
this->tab_ = tab;
|
||||
}
|
||||
|
||||
void SettingsPage::cancel()
|
||||
{
|
||||
this->onCancel_.invoke();
|
||||
}
|
||||
|
||||
QCheckBox *SettingsPage::createCheckBox(
|
||||
const QString &text, pajlada::Settings::Setting<bool> &setting)
|
||||
{
|
||||
QCheckBox *checkbox = new SCheckBox(text);
|
||||
|
||||
// update when setting changes
|
||||
setting.connect(
|
||||
[checkbox](const bool &value, auto) {
|
||||
checkbox->setChecked(value); //
|
||||
},
|
||||
this->managedConnections_);
|
||||
|
||||
// update setting on toggle
|
||||
QObject::connect(checkbox, &QCheckBox::toggled, this,
|
||||
[&setting](bool state) {
|
||||
setting = state;
|
||||
getApp()->windows->forceLayoutChannelViews();
|
||||
});
|
||||
|
||||
return checkbox;
|
||||
}
|
||||
|
||||
QComboBox *SettingsPage::createComboBox(
|
||||
const QStringList &items, pajlada::Settings::Setting<QString> &setting)
|
||||
{
|
||||
QComboBox *combo = new SComboBox();
|
||||
|
||||
// update setting on toogle
|
||||
combo->addItems(items);
|
||||
|
||||
// update when setting changes
|
||||
setting.connect(
|
||||
[combo](const QString &value, auto) { combo->setCurrentText(value); },
|
||||
this->managedConnections_);
|
||||
|
||||
QObject::connect(
|
||||
combo, &QComboBox::currentTextChanged,
|
||||
[&setting](const QString &newValue) { setting = newValue; });
|
||||
|
||||
return combo;
|
||||
}
|
||||
|
||||
QLineEdit *SettingsPage::createLineEdit(
|
||||
pajlada::Settings::Setting<QString> &setting)
|
||||
{
|
||||
QLineEdit *edit = new QLineEdit();
|
||||
|
||||
edit->setText(setting);
|
||||
|
||||
// update when setting changes
|
||||
QObject::connect(
|
||||
edit, &QLineEdit::textChanged,
|
||||
[&setting](const QString &newValue) { setting = newValue; });
|
||||
|
||||
return edit;
|
||||
}
|
||||
|
||||
QSpinBox *SettingsPage::createSpinBox(pajlada::Settings::Setting<int> &setting,
|
||||
int min, int max)
|
||||
{
|
||||
QSpinBox *w = new QSpinBox;
|
||||
|
||||
w->setMinimum(min);
|
||||
w->setMaximum(max);
|
||||
|
||||
setting.connect([w](const int &value, auto) { w->setValue(value); });
|
||||
QObject::connect(w, QOverload<int>::of(&QSpinBox::valueChanged),
|
||||
[&setting](int value) { setting.setValue(value); });
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "SettingsPage.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "singletons/WindowManager.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <util/FunctionEventFilter.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
bool filterItemsRec(QObject *object, const QString &query)
|
||||
{
|
||||
bool any{};
|
||||
|
||||
for (auto &&child : object->children())
|
||||
{
|
||||
auto setOpacity = [&](auto *widget, bool condition) {
|
||||
any |= condition;
|
||||
widget->greyedOut = !condition;
|
||||
widget->update();
|
||||
};
|
||||
|
||||
if (auto x = dynamic_cast<SCheckBox *>(child); x)
|
||||
{
|
||||
setOpacity(x, x->text().contains(query, Qt::CaseInsensitive));
|
||||
}
|
||||
else if (auto x = dynamic_cast<SLabel *>(child); x)
|
||||
{
|
||||
setOpacity(x, x->text().contains(query, Qt::CaseInsensitive));
|
||||
}
|
||||
else if (auto x = dynamic_cast<SComboBox *>(child); x)
|
||||
{
|
||||
setOpacity(x, [=]() {
|
||||
for (int i = 0; i < x->count(); i++)
|
||||
{
|
||||
if (x->itemText(i).contains(query, Qt::CaseInsensitive))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}());
|
||||
}
|
||||
else if (auto x = dynamic_cast<QTabWidget *>(child); x)
|
||||
{
|
||||
for (int i = 0; i < x->count(); i++)
|
||||
{
|
||||
bool tabAny{};
|
||||
|
||||
if (x->tabText(i).contains(query, Qt::CaseInsensitive))
|
||||
{
|
||||
tabAny = true;
|
||||
}
|
||||
auto widget = x->widget(i);
|
||||
tabAny |= filterItemsRec(widget, query);
|
||||
|
||||
any |= tabAny;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
any |= filterItemsRec(child, query);
|
||||
}
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
SettingsPage::SettingsPage(const QString &name, const QString &iconResource)
|
||||
: name_(name)
|
||||
, iconResource_(iconResource)
|
||||
{
|
||||
}
|
||||
|
||||
bool SettingsPage::filterElements(const QString &query)
|
||||
{
|
||||
return filterItemsRec(this, query) || query.isEmpty() ||
|
||||
this->name_.contains(query, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
const QString &SettingsPage::getName()
|
||||
{
|
||||
return this->name_;
|
||||
}
|
||||
|
||||
const QString &SettingsPage::getIconResource()
|
||||
{
|
||||
return this->iconResource_;
|
||||
}
|
||||
|
||||
SettingsDialogTab *SettingsPage::tab() const
|
||||
{
|
||||
return this->tab_;
|
||||
}
|
||||
|
||||
void SettingsPage::setTab(SettingsDialogTab *tab)
|
||||
{
|
||||
this->tab_ = tab;
|
||||
}
|
||||
|
||||
void SettingsPage::cancel()
|
||||
{
|
||||
this->onCancel_.invoke();
|
||||
}
|
||||
|
||||
QCheckBox *SettingsPage::createCheckBox(
|
||||
const QString &text, pajlada::Settings::Setting<bool> &setting)
|
||||
{
|
||||
QCheckBox *checkbox = new SCheckBox(text);
|
||||
|
||||
// update when setting changes
|
||||
setting.connect(
|
||||
[checkbox](const bool &value, auto) {
|
||||
checkbox->setChecked(value); //
|
||||
},
|
||||
this->managedConnections_);
|
||||
|
||||
// update setting on toggle
|
||||
QObject::connect(checkbox, &QCheckBox::toggled, this,
|
||||
[&setting](bool state) {
|
||||
setting = state;
|
||||
getApp()->windows->forceLayoutChannelViews();
|
||||
});
|
||||
|
||||
return checkbox;
|
||||
}
|
||||
|
||||
QComboBox *SettingsPage::createComboBox(
|
||||
const QStringList &items, pajlada::Settings::Setting<QString> &setting)
|
||||
{
|
||||
QComboBox *combo = new SComboBox();
|
||||
|
||||
// update setting on toogle
|
||||
combo->addItems(items);
|
||||
|
||||
// update when setting changes
|
||||
setting.connect(
|
||||
[combo](const QString &value, auto) { combo->setCurrentText(value); },
|
||||
this->managedConnections_);
|
||||
|
||||
QObject::connect(
|
||||
combo, &QComboBox::currentTextChanged,
|
||||
[&setting](const QString &newValue) { setting = newValue; });
|
||||
|
||||
return combo;
|
||||
}
|
||||
|
||||
QLineEdit *SettingsPage::createLineEdit(
|
||||
pajlada::Settings::Setting<QString> &setting)
|
||||
{
|
||||
QLineEdit *edit = new QLineEdit();
|
||||
|
||||
edit->setText(setting);
|
||||
|
||||
// update when setting changes
|
||||
QObject::connect(
|
||||
edit, &QLineEdit::textChanged,
|
||||
[&setting](const QString &newValue) { setting = newValue; });
|
||||
|
||||
return edit;
|
||||
}
|
||||
|
||||
QSpinBox *SettingsPage::createSpinBox(pajlada::Settings::Setting<int> &setting,
|
||||
int min, int max)
|
||||
{
|
||||
QSpinBox *w = new QSpinBox;
|
||||
|
||||
w->setMinimum(min);
|
||||
w->setMaximum(max);
|
||||
|
||||
setting.connect([w](const int &value, auto) { w->setValue(value); });
|
||||
QObject::connect(w, QOverload<int>::of(&QSpinBox::valueChanged),
|
||||
[&setting](int value) { setting.setValue(value); });
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,84 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
#include "singletons/Settings.hpp"
|
||||
|
||||
#define SETTINGS_PAGE_WIDGET_BOILERPLATE(type, parent) \
|
||||
class type : public parent \
|
||||
{ \
|
||||
using parent::parent; \
|
||||
\
|
||||
public: \
|
||||
bool greyedOut{}; \
|
||||
\
|
||||
protected: \
|
||||
void paintEvent(QPaintEvent *e) override \
|
||||
{ \
|
||||
parent::paintEvent(e); \
|
||||
\
|
||||
if (this->greyedOut) \
|
||||
{ \
|
||||
QPainter painter(this); \
|
||||
QColor color = QColor("#222222"); \
|
||||
color.setAlphaF(0.7); \
|
||||
painter.fillRect(this->rect(), color); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
// S* widgets are the same as their Q* counterparts,
|
||||
// but they can be greyed out and will be if you search.
|
||||
SETTINGS_PAGE_WIDGET_BOILERPLATE(SCheckBox, QCheckBox)
|
||||
SETTINGS_PAGE_WIDGET_BOILERPLATE(SLabel, QLabel)
|
||||
SETTINGS_PAGE_WIDGET_BOILERPLATE(SComboBox, QComboBox)
|
||||
SETTINGS_PAGE_WIDGET_BOILERPLATE(SPushButton, QPushButton)
|
||||
|
||||
class SettingsDialogTab;
|
||||
|
||||
class SettingsPage : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsPage(const QString &name, const QString &iconResource);
|
||||
|
||||
const QString &getName();
|
||||
const QString &getIconResource();
|
||||
|
||||
virtual bool filterElements(const QString &query);
|
||||
|
||||
SettingsDialogTab *tab() const;
|
||||
void setTab(SettingsDialogTab *tab);
|
||||
|
||||
void cancel();
|
||||
|
||||
QCheckBox *createCheckBox(const QString &text,
|
||||
pajlada::Settings::Setting<bool> &setting);
|
||||
QComboBox *createComboBox(const QStringList &items,
|
||||
pajlada::Settings::Setting<QString> &setting);
|
||||
QLineEdit *createLineEdit(pajlada::Settings::Setting<QString> &setting);
|
||||
QSpinBox *createSpinBox(pajlada::Settings::Setting<int> &setting,
|
||||
int min = 0, int max = 2500);
|
||||
|
||||
virtual void onShow()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
QString name_;
|
||||
QString iconResource_;
|
||||
|
||||
SettingsDialogTab *tab_;
|
||||
|
||||
pajlada::Signals::NoArgSignal onCancel_;
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
#include "singletons/Settings.hpp"
|
||||
|
||||
#define SETTINGS_PAGE_WIDGET_BOILERPLATE(type, parent) \
|
||||
class type : public parent \
|
||||
{ \
|
||||
using parent::parent; \
|
||||
\
|
||||
public: \
|
||||
bool greyedOut{}; \
|
||||
\
|
||||
protected: \
|
||||
void paintEvent(QPaintEvent *e) override \
|
||||
{ \
|
||||
parent::paintEvent(e); \
|
||||
\
|
||||
if (this->greyedOut) \
|
||||
{ \
|
||||
QPainter painter(this); \
|
||||
QColor color = QColor("#222222"); \
|
||||
color.setAlphaF(0.7); \
|
||||
painter.fillRect(this->rect(), color); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
// S* widgets are the same as their Q* counterparts,
|
||||
// but they can be greyed out and will be if you search.
|
||||
SETTINGS_PAGE_WIDGET_BOILERPLATE(SCheckBox, QCheckBox)
|
||||
SETTINGS_PAGE_WIDGET_BOILERPLATE(SLabel, QLabel)
|
||||
SETTINGS_PAGE_WIDGET_BOILERPLATE(SComboBox, QComboBox)
|
||||
SETTINGS_PAGE_WIDGET_BOILERPLATE(SPushButton, QPushButton)
|
||||
|
||||
class SettingsDialogTab;
|
||||
|
||||
class SettingsPage : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsPage(const QString &name, const QString &iconResource);
|
||||
|
||||
const QString &getName();
|
||||
const QString &getIconResource();
|
||||
|
||||
virtual bool filterElements(const QString &query);
|
||||
|
||||
SettingsDialogTab *tab() const;
|
||||
void setTab(SettingsDialogTab *tab);
|
||||
|
||||
void cancel();
|
||||
|
||||
QCheckBox *createCheckBox(const QString &text,
|
||||
pajlada::Settings::Setting<bool> &setting);
|
||||
QComboBox *createComboBox(const QStringList &items,
|
||||
pajlada::Settings::Setting<QString> &setting);
|
||||
QLineEdit *createLineEdit(pajlada::Settings::Setting<QString> &setting);
|
||||
QSpinBox *createSpinBox(pajlada::Settings::Setting<int> &setting,
|
||||
int min = 0, int max = 2500);
|
||||
|
||||
virtual void onShow()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
QString name_;
|
||||
QString iconResource_;
|
||||
|
||||
SettingsDialogTab *tab_;
|
||||
|
||||
pajlada::Signals::NoArgSignal onCancel_;
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
+254
-254
@@ -1,254 +1,254 @@
|
||||
#include "SplitOverlay.hpp"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QGraphicsBlurEffect>
|
||||
#include <QGraphicsEffect>
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <QGridLayout>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "singletons/Resources.hpp"
|
||||
#include "singletons/Theme.hpp"
|
||||
#include "widgets/splits/Split.hpp"
|
||||
#include "widgets/splits/SplitContainer.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
SplitOverlay::SplitOverlay(Split *parent)
|
||||
: BaseWidget(parent)
|
||||
, split_(parent)
|
||||
{
|
||||
QGridLayout *layout = new QGridLayout(this);
|
||||
this->layout_ = layout;
|
||||
layout->setMargin(1);
|
||||
layout->setSpacing(1);
|
||||
|
||||
layout->setRowStretch(1, 1);
|
||||
layout->setRowStretch(3, 1);
|
||||
layout->setColumnStretch(1, 1);
|
||||
layout->setColumnStretch(3, 1);
|
||||
|
||||
auto *move = new QPushButton(getApp()->resources->split.move, QString());
|
||||
auto *left = this->left_ =
|
||||
new QPushButton(getApp()->resources->split.left, QString());
|
||||
auto *right = this->right_ =
|
||||
new QPushButton(getApp()->resources->split.right, QString());
|
||||
auto *up = this->up_ =
|
||||
new QPushButton(getApp()->resources->split.up, QString());
|
||||
auto *down = this->down_ =
|
||||
new QPushButton(getApp()->resources->split.down, QString());
|
||||
|
||||
move->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
left->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
right->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
up->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
down->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
|
||||
move->setFlat(true);
|
||||
left->setFlat(true);
|
||||
right->setFlat(true);
|
||||
up->setFlat(true);
|
||||
down->setFlat(true);
|
||||
|
||||
layout->addWidget(move, 2, 2);
|
||||
layout->addWidget(left, 2, 0);
|
||||
layout->addWidget(right, 2, 4);
|
||||
layout->addWidget(up, 0, 2);
|
||||
layout->addWidget(down, 4, 2);
|
||||
|
||||
move->installEventFilter(new ButtonEventFilter(this, SplitMove));
|
||||
left->installEventFilter(new ButtonEventFilter(this, SplitLeft));
|
||||
right->installEventFilter(new ButtonEventFilter(this, SplitRight));
|
||||
up->installEventFilter(new ButtonEventFilter(this, SplitUp));
|
||||
down->installEventFilter(new ButtonEventFilter(this, SplitDown));
|
||||
|
||||
move->setFocusPolicy(Qt::NoFocus);
|
||||
left->setFocusPolicy(Qt::NoFocus);
|
||||
right->setFocusPolicy(Qt::NoFocus);
|
||||
up->setFocusPolicy(Qt::NoFocus);
|
||||
down->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
move->setCursor(Qt::SizeAllCursor);
|
||||
left->setCursor(Qt::PointingHandCursor);
|
||||
right->setCursor(Qt::PointingHandCursor);
|
||||
up->setCursor(Qt::PointingHandCursor);
|
||||
down->setCursor(Qt::PointingHandCursor);
|
||||
|
||||
this->managedConnect(this->scaleChanged, [=](float _scale) {
|
||||
int a = int(_scale * 30);
|
||||
QSize size(a, a);
|
||||
|
||||
move->setIconSize(size);
|
||||
left->setIconSize(size);
|
||||
right->setIconSize(size);
|
||||
up->setIconSize(size);
|
||||
down->setIconSize(size);
|
||||
});
|
||||
|
||||
this->setMouseTracking(true);
|
||||
|
||||
this->setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
|
||||
void SplitOverlay::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
if (this->theme->isLightTheme())
|
||||
{
|
||||
painter.fillRect(this->rect(), QColor(255, 255, 255, 200));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.fillRect(this->rect(), QColor(0, 0, 0, 150));
|
||||
}
|
||||
|
||||
QRect rect;
|
||||
switch (this->hoveredElement_)
|
||||
{
|
||||
case SplitLeft:
|
||||
{
|
||||
rect = QRect(0, 0, this->width() / 2, this->height());
|
||||
}
|
||||
break;
|
||||
|
||||
case SplitRight:
|
||||
{
|
||||
rect =
|
||||
QRect(this->width() / 2, 0, this->width() / 2, this->height());
|
||||
}
|
||||
break;
|
||||
|
||||
case SplitUp:
|
||||
{
|
||||
rect = QRect(0, 0, this->width(), this->height() / 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case SplitDown:
|
||||
{
|
||||
rect =
|
||||
QRect(0, this->height() / 2, this->width(), this->height() / 2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:;
|
||||
}
|
||||
|
||||
rect.setRight(rect.right() - 1);
|
||||
rect.setBottom(rect.bottom() - 1);
|
||||
|
||||
if (!rect.isNull())
|
||||
{
|
||||
painter.setPen(getApp()->themes->splits.dropPreviewBorder);
|
||||
painter.setBrush(getApp()->themes->splits.dropPreview);
|
||||
painter.drawRect(rect);
|
||||
}
|
||||
}
|
||||
|
||||
void SplitOverlay::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
float _scale = this->scale();
|
||||
bool wideEnough = event->size().width() > 150 * _scale;
|
||||
bool highEnough = event->size().height() > 150 * _scale;
|
||||
|
||||
this->left_->setVisible(wideEnough);
|
||||
this->right_->setVisible(wideEnough);
|
||||
this->up_->setVisible(highEnough);
|
||||
this->down_->setVisible(highEnough);
|
||||
}
|
||||
|
||||
void SplitOverlay::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
BaseWidget::mouseMoveEvent(event);
|
||||
|
||||
// qDebug() << QGuiApplication::queryKeyboardModifiers();
|
||||
|
||||
// if ((QGuiApplication::queryKeyboardModifiers() & Qt::AltModifier) ==
|
||||
// Qt::AltModifier) {
|
||||
// this->hide();
|
||||
// }
|
||||
}
|
||||
|
||||
SplitOverlay::ButtonEventFilter::ButtonEventFilter(SplitOverlay *_parent,
|
||||
HoveredElement _element)
|
||||
: QObject(_parent)
|
||||
, parent(_parent)
|
||||
, hoveredElement(_element)
|
||||
{
|
||||
}
|
||||
|
||||
bool SplitOverlay::ButtonEventFilter::eventFilter(QObject *watched,
|
||||
QEvent *event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::Enter:
|
||||
{
|
||||
QGraphicsOpacityEffect *effect =
|
||||
dynamic_cast<QGraphicsOpacityEffect *>(
|
||||
((QWidget *)watched)->graphicsEffect());
|
||||
|
||||
if (effect != nullptr)
|
||||
{
|
||||
effect->setOpacity(0.99);
|
||||
}
|
||||
|
||||
this->parent->hoveredElement_ = this->hoveredElement;
|
||||
this->parent->update();
|
||||
}
|
||||
break;
|
||||
case QEvent::Leave:
|
||||
{
|
||||
QGraphicsOpacityEffect *effect =
|
||||
dynamic_cast<QGraphicsOpacityEffect *>(
|
||||
((QWidget *)watched)->graphicsEffect());
|
||||
|
||||
if (effect != nullptr)
|
||||
{
|
||||
effect->setOpacity(0.7);
|
||||
}
|
||||
|
||||
this->parent->hoveredElement_ = HoveredElement::None;
|
||||
this->parent->update();
|
||||
}
|
||||
break;
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
if (this->hoveredElement == HoveredElement::SplitMove)
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
if (mouseEvent->button() == Qt::LeftButton)
|
||||
{
|
||||
this->parent->split_->drag();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
if (this->hoveredElement != HoveredElement::SplitMove)
|
||||
{
|
||||
SplitContainer *container =
|
||||
this->parent->split_->getContainer();
|
||||
|
||||
if (container != nullptr)
|
||||
{
|
||||
auto *_split = new Split(container);
|
||||
auto dir = SplitContainer::Direction(this->hoveredElement +
|
||||
SplitContainer::Left -
|
||||
SplitLeft);
|
||||
container->insertSplit(_split, dir, this->parent->split_);
|
||||
this->parent->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
#include "SplitOverlay.hpp"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QGraphicsBlurEffect>
|
||||
#include <QGraphicsEffect>
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <QGridLayout>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "singletons/Resources.hpp"
|
||||
#include "singletons/Theme.hpp"
|
||||
#include "widgets/splits/Split.hpp"
|
||||
#include "widgets/splits/SplitContainer.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
SplitOverlay::SplitOverlay(Split *parent)
|
||||
: BaseWidget(parent)
|
||||
, split_(parent)
|
||||
{
|
||||
QGridLayout *layout = new QGridLayout(this);
|
||||
this->layout_ = layout;
|
||||
layout->setMargin(1);
|
||||
layout->setSpacing(1);
|
||||
|
||||
layout->setRowStretch(1, 1);
|
||||
layout->setRowStretch(3, 1);
|
||||
layout->setColumnStretch(1, 1);
|
||||
layout->setColumnStretch(3, 1);
|
||||
|
||||
auto *move = new QPushButton(getApp()->resources->split.move, QString());
|
||||
auto *left = this->left_ =
|
||||
new QPushButton(getApp()->resources->split.left, QString());
|
||||
auto *right = this->right_ =
|
||||
new QPushButton(getApp()->resources->split.right, QString());
|
||||
auto *up = this->up_ =
|
||||
new QPushButton(getApp()->resources->split.up, QString());
|
||||
auto *down = this->down_ =
|
||||
new QPushButton(getApp()->resources->split.down, QString());
|
||||
|
||||
move->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
left->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
right->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
up->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
down->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
|
||||
move->setFlat(true);
|
||||
left->setFlat(true);
|
||||
right->setFlat(true);
|
||||
up->setFlat(true);
|
||||
down->setFlat(true);
|
||||
|
||||
layout->addWidget(move, 2, 2);
|
||||
layout->addWidget(left, 2, 0);
|
||||
layout->addWidget(right, 2, 4);
|
||||
layout->addWidget(up, 0, 2);
|
||||
layout->addWidget(down, 4, 2);
|
||||
|
||||
move->installEventFilter(new ButtonEventFilter(this, SplitMove));
|
||||
left->installEventFilter(new ButtonEventFilter(this, SplitLeft));
|
||||
right->installEventFilter(new ButtonEventFilter(this, SplitRight));
|
||||
up->installEventFilter(new ButtonEventFilter(this, SplitUp));
|
||||
down->installEventFilter(new ButtonEventFilter(this, SplitDown));
|
||||
|
||||
move->setFocusPolicy(Qt::NoFocus);
|
||||
left->setFocusPolicy(Qt::NoFocus);
|
||||
right->setFocusPolicy(Qt::NoFocus);
|
||||
up->setFocusPolicy(Qt::NoFocus);
|
||||
down->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
move->setCursor(Qt::SizeAllCursor);
|
||||
left->setCursor(Qt::PointingHandCursor);
|
||||
right->setCursor(Qt::PointingHandCursor);
|
||||
up->setCursor(Qt::PointingHandCursor);
|
||||
down->setCursor(Qt::PointingHandCursor);
|
||||
|
||||
this->managedConnect(this->scaleChanged, [=](float _scale) {
|
||||
int a = int(_scale * 30);
|
||||
QSize size(a, a);
|
||||
|
||||
move->setIconSize(size);
|
||||
left->setIconSize(size);
|
||||
right->setIconSize(size);
|
||||
up->setIconSize(size);
|
||||
down->setIconSize(size);
|
||||
});
|
||||
|
||||
this->setMouseTracking(true);
|
||||
|
||||
this->setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
|
||||
void SplitOverlay::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
if (this->theme->isLightTheme())
|
||||
{
|
||||
painter.fillRect(this->rect(), QColor(255, 255, 255, 200));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.fillRect(this->rect(), QColor(0, 0, 0, 150));
|
||||
}
|
||||
|
||||
QRect rect;
|
||||
switch (this->hoveredElement_)
|
||||
{
|
||||
case SplitLeft:
|
||||
{
|
||||
rect = QRect(0, 0, this->width() / 2, this->height());
|
||||
}
|
||||
break;
|
||||
|
||||
case SplitRight:
|
||||
{
|
||||
rect =
|
||||
QRect(this->width() / 2, 0, this->width() / 2, this->height());
|
||||
}
|
||||
break;
|
||||
|
||||
case SplitUp:
|
||||
{
|
||||
rect = QRect(0, 0, this->width(), this->height() / 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case SplitDown:
|
||||
{
|
||||
rect =
|
||||
QRect(0, this->height() / 2, this->width(), this->height() / 2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:;
|
||||
}
|
||||
|
||||
rect.setRight(rect.right() - 1);
|
||||
rect.setBottom(rect.bottom() - 1);
|
||||
|
||||
if (!rect.isNull())
|
||||
{
|
||||
painter.setPen(getApp()->themes->splits.dropPreviewBorder);
|
||||
painter.setBrush(getApp()->themes->splits.dropPreview);
|
||||
painter.drawRect(rect);
|
||||
}
|
||||
}
|
||||
|
||||
void SplitOverlay::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
float _scale = this->scale();
|
||||
bool wideEnough = event->size().width() > 150 * _scale;
|
||||
bool highEnough = event->size().height() > 150 * _scale;
|
||||
|
||||
this->left_->setVisible(wideEnough);
|
||||
this->right_->setVisible(wideEnough);
|
||||
this->up_->setVisible(highEnough);
|
||||
this->down_->setVisible(highEnough);
|
||||
}
|
||||
|
||||
void SplitOverlay::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
BaseWidget::mouseMoveEvent(event);
|
||||
|
||||
// qDebug() << QGuiApplication::queryKeyboardModifiers();
|
||||
|
||||
// if ((QGuiApplication::queryKeyboardModifiers() & Qt::AltModifier) ==
|
||||
// Qt::AltModifier) {
|
||||
// this->hide();
|
||||
// }
|
||||
}
|
||||
|
||||
SplitOverlay::ButtonEventFilter::ButtonEventFilter(SplitOverlay *_parent,
|
||||
HoveredElement _element)
|
||||
: QObject(_parent)
|
||||
, parent(_parent)
|
||||
, hoveredElement(_element)
|
||||
{
|
||||
}
|
||||
|
||||
bool SplitOverlay::ButtonEventFilter::eventFilter(QObject *watched,
|
||||
QEvent *event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::Enter:
|
||||
{
|
||||
QGraphicsOpacityEffect *effect =
|
||||
dynamic_cast<QGraphicsOpacityEffect *>(
|
||||
((QWidget *)watched)->graphicsEffect());
|
||||
|
||||
if (effect != nullptr)
|
||||
{
|
||||
effect->setOpacity(0.99);
|
||||
}
|
||||
|
||||
this->parent->hoveredElement_ = this->hoveredElement;
|
||||
this->parent->update();
|
||||
}
|
||||
break;
|
||||
case QEvent::Leave:
|
||||
{
|
||||
QGraphicsOpacityEffect *effect =
|
||||
dynamic_cast<QGraphicsOpacityEffect *>(
|
||||
((QWidget *)watched)->graphicsEffect());
|
||||
|
||||
if (effect != nullptr)
|
||||
{
|
||||
effect->setOpacity(0.7);
|
||||
}
|
||||
|
||||
this->parent->hoveredElement_ = HoveredElement::None;
|
||||
this->parent->update();
|
||||
}
|
||||
break;
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
if (this->hoveredElement == HoveredElement::SplitMove)
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
if (mouseEvent->button() == Qt::LeftButton)
|
||||
{
|
||||
this->parent->split_->drag();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
if (this->hoveredElement != HoveredElement::SplitMove)
|
||||
{
|
||||
SplitContainer *container =
|
||||
this->parent->split_->getContainer();
|
||||
|
||||
if (container != nullptr)
|
||||
{
|
||||
auto *_split = new Split(container);
|
||||
auto dir = SplitContainer::Direction(this->hoveredElement +
|
||||
SplitContainer::Left -
|
||||
SplitLeft);
|
||||
container->insertSplit(_split, dir, this->parent->split_);
|
||||
this->parent->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,58 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "pajlada/signals/signalholder.hpp"
|
||||
#include "widgets/BaseWidget.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Split;
|
||||
|
||||
class SplitOverlay : public BaseWidget, pajlada::Signals::SignalHolder
|
||||
{
|
||||
public:
|
||||
explicit SplitOverlay(Split *parent = nullptr);
|
||||
|
||||
protected:
|
||||
// bool event(QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
// fourtf: !!! preserve the order of left, up, right and down
|
||||
enum HoveredElement {
|
||||
None,
|
||||
SplitMove,
|
||||
SplitLeft,
|
||||
SplitUp,
|
||||
SplitRight,
|
||||
SplitDown
|
||||
};
|
||||
|
||||
class ButtonEventFilter : public QObject
|
||||
{
|
||||
SplitOverlay *parent;
|
||||
HoveredElement hoveredElement;
|
||||
|
||||
public:
|
||||
ButtonEventFilter(SplitOverlay *parent, HoveredElement hoveredElement);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
};
|
||||
|
||||
HoveredElement hoveredElement_ = None;
|
||||
Split *split_;
|
||||
QGridLayout *layout_;
|
||||
QPushButton *left_;
|
||||
QPushButton *up_;
|
||||
QPushButton *right_;
|
||||
QPushButton *down_;
|
||||
|
||||
friend class ButtonEventFilter;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
#pragma once
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "pajlada/signals/signalholder.hpp"
|
||||
#include "widgets/BaseWidget.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Split;
|
||||
|
||||
class SplitOverlay : public BaseWidget, pajlada::Signals::SignalHolder
|
||||
{
|
||||
public:
|
||||
explicit SplitOverlay(Split *parent = nullptr);
|
||||
|
||||
protected:
|
||||
// bool event(QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
// fourtf: !!! preserve the order of left, up, right and down
|
||||
enum HoveredElement {
|
||||
None,
|
||||
SplitMove,
|
||||
SplitLeft,
|
||||
SplitUp,
|
||||
SplitRight,
|
||||
SplitDown
|
||||
};
|
||||
|
||||
class ButtonEventFilter : public QObject
|
||||
{
|
||||
SplitOverlay *parent;
|
||||
HoveredElement hoveredElement;
|
||||
|
||||
public:
|
||||
ButtonEventFilter(SplitOverlay *parent, HoveredElement hoveredElement);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
};
|
||||
|
||||
HoveredElement hoveredElement_ = None;
|
||||
Split *split_;
|
||||
QGridLayout *layout_;
|
||||
QPushButton *left_;
|
||||
QPushButton *up_;
|
||||
QPushButton *right_;
|
||||
QPushButton *down_;
|
||||
|
||||
friend class ButtonEventFilter;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
Reference in New Issue
Block a user