Merge branch 'master' of https://github.com/fourtf/chatterino2
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include "widgets/split.hpp"
|
||||
#include "widgets/tooltipwidget.hpp"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QGraphicsBlurEffect>
|
||||
@@ -24,8 +25,7 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#define LAYOUT_WIDTH \
|
||||
(this->width() - (this->scrollBar.isVisible() ? 16 : 4) * this->getDpiMultiplier())
|
||||
#define LAYOUT_WIDTH (this->width() - (this->scrollBar.isVisible() ? 16 : 4) * this->getScale())
|
||||
|
||||
using namespace chatterino::messages;
|
||||
|
||||
@@ -96,6 +96,9 @@ ChannelView::ChannelView(BaseWidget *parent)
|
||||
auto e = new QResizeEvent(this->size(), this->size());
|
||||
this->resizeEvent(e);
|
||||
delete e;
|
||||
|
||||
singletons::SettingManager::getInstance().showLastMessageIndicator.connect(
|
||||
[this](auto, auto) { this->update(); }, this->managedConnections);
|
||||
}
|
||||
|
||||
ChannelView::~ChannelView()
|
||||
@@ -111,6 +114,13 @@ ChannelView::~ChannelView()
|
||||
this->messageReplacedConnection.disconnect();
|
||||
}
|
||||
|
||||
void ChannelView::themeRefreshEvent()
|
||||
{
|
||||
BaseWidget::themeRefreshEvent();
|
||||
|
||||
this->layoutMessages();
|
||||
}
|
||||
|
||||
void ChannelView::queueUpdate()
|
||||
{
|
||||
if (this->updateTimer.isActive()) {
|
||||
@@ -164,7 +174,7 @@ void ChannelView::actuallyLayoutMessages()
|
||||
for (size_t i = start; i < messagesSnapshot.getLength(); ++i) {
|
||||
auto message = messagesSnapshot[i];
|
||||
|
||||
redrawRequired |= message->layout(layoutWidth, this->getDpiMultiplier(), flags);
|
||||
redrawRequired |= message->layout(layoutWidth, this->getScale(), flags);
|
||||
|
||||
y += message->getHeight();
|
||||
|
||||
@@ -180,7 +190,7 @@ void ChannelView::actuallyLayoutMessages()
|
||||
for (int i = (int)messagesSnapshot.getLength() - 1; i >= 0; i--) {
|
||||
auto *message = messagesSnapshot[i].get();
|
||||
|
||||
message->layout(layoutWidth, this->getDpiMultiplier(), flags);
|
||||
message->layout(layoutWidth, this->getScale(), flags);
|
||||
|
||||
h -= message->getHeight();
|
||||
|
||||
@@ -281,6 +291,16 @@ bool ChannelView::getEnableScrollingToBottom() const
|
||||
return this->enableScrollingToBottom;
|
||||
}
|
||||
|
||||
void ChannelView::setOverrideFlags(boost::optional<messages::MessageElement::Flags> value)
|
||||
{
|
||||
this->overrideFlags = value;
|
||||
}
|
||||
|
||||
const boost::optional<messages::MessageElement::Flags> &ChannelView::getOverrideFlags() const
|
||||
{
|
||||
return this->overrideFlags;
|
||||
}
|
||||
|
||||
messages::LimitedQueueSnapshot<MessageLayoutPtr> ChannelView::getMessagesSnapshot()
|
||||
{
|
||||
if (!this->paused) {
|
||||
@@ -290,7 +310,7 @@ messages::LimitedQueueSnapshot<MessageLayoutPtr> ChannelView::getMessagesSnapsho
|
||||
return this->snapshot;
|
||||
}
|
||||
|
||||
void ChannelView::setChannel(SharedChannel newChannel)
|
||||
void ChannelView::setChannel(ChannelPtr newChannel)
|
||||
{
|
||||
if (this->channel) {
|
||||
this->detachChannel();
|
||||
@@ -328,7 +348,6 @@ void ChannelView::setChannel(SharedChannel newChannel)
|
||||
newChannel->messagesAddedAtStart.connect([this](std::vector<MessagePtr> &messages) {
|
||||
std::vector<MessageLayoutPtr> messageRefs;
|
||||
messageRefs.resize(messages.size());
|
||||
qDebug() << messages.size();
|
||||
for (size_t i = 0; i < messages.size(); i++) {
|
||||
messageRefs.at(i) = MessageLayoutPtr(new MessageLayout(messages.at(i)));
|
||||
}
|
||||
@@ -410,6 +429,17 @@ void ChannelView::pause(int msecTimeout)
|
||||
this->pauseTimeout.start(msecTimeout);
|
||||
}
|
||||
|
||||
void ChannelView::updateLastReadMessage()
|
||||
{
|
||||
auto _snapshot = this->getMessagesSnapshot();
|
||||
|
||||
if (_snapshot.getLength() > 0) {
|
||||
this->lastReadMessage = _snapshot[_snapshot.getLength() - 1];
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
|
||||
void ChannelView::resizeEvent(QResizeEvent *)
|
||||
{
|
||||
this->scrollBar.resize(this->scrollBar.width(), height());
|
||||
@@ -434,6 +464,10 @@ void ChannelView::setSelection(const SelectionItem &start, const SelectionItem &
|
||||
|
||||
messages::MessageElement::Flags ChannelView::getFlags() const
|
||||
{
|
||||
if (this->overrideFlags) {
|
||||
return this->overrideFlags.get();
|
||||
}
|
||||
|
||||
MessageElement::Flags flags = singletons::SettingManager::getInstance().getWordFlags();
|
||||
|
||||
Split *split = dynamic_cast<Split *>(this->parentWidget());
|
||||
@@ -442,6 +476,9 @@ messages::MessageElement::Flags ChannelView::getFlags() const
|
||||
if (split->getModerationMode()) {
|
||||
flags = (MessageElement::Flags)(flags | MessageElement::ModeratorTools);
|
||||
}
|
||||
if (this->channel == singletons::ChannelManager::getInstance().mentionsChannel) {
|
||||
flags = (MessageElement::Flags)(flags | MessageElement::ChannelName);
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
@@ -477,11 +514,17 @@ void ChannelView::drawMessages(QPainter &painter)
|
||||
(fmod(this->scrollBar.getCurrentValue(), 1)));
|
||||
|
||||
messages::MessageLayout *end = nullptr;
|
||||
bool windowFocused = this->window() == QApplication::activeWindow();
|
||||
|
||||
for (size_t i = start; i < messagesSnapshot.getLength(); ++i) {
|
||||
messages::MessageLayout *layout = messagesSnapshot[i].get();
|
||||
|
||||
layout->paint(painter, y, i, this->selection);
|
||||
bool isLastMessage = false;
|
||||
if (singletons::SettingManager::getInstance().showLastMessageIndicator) {
|
||||
isLastMessage = this->lastReadMessage.get() == layout;
|
||||
}
|
||||
|
||||
layout->paint(painter, y, i, this->selection, isLastMessage, windowFocused);
|
||||
|
||||
y += layout->getHeight();
|
||||
|
||||
@@ -551,8 +594,7 @@ void ChannelView::wheelEvent(QWheelEvent *event)
|
||||
if (i == 0) {
|
||||
desired = 0;
|
||||
} else {
|
||||
snapshot[i - 1]->layout(LAYOUT_WIDTH, this->getDpiMultiplier(),
|
||||
this->getFlags());
|
||||
snapshot[i - 1]->layout(LAYOUT_WIDTH, this->getScale(), this->getFlags());
|
||||
scrollFactor = 1;
|
||||
currentScrollLeft = snapshot[i - 1]->getHeight();
|
||||
}
|
||||
@@ -574,8 +616,7 @@ void ChannelView::wheelEvent(QWheelEvent *event)
|
||||
if (i == snapshotLength - 1) {
|
||||
desired = snapshot.getLength();
|
||||
} else {
|
||||
snapshot[i + 1]->layout(LAYOUT_WIDTH, this->getDpiMultiplier(),
|
||||
this->getFlags());
|
||||
snapshot[i + 1]->layout(LAYOUT_WIDTH, this->getScale(), this->getFlags());
|
||||
|
||||
scrollFactor = 1;
|
||||
currentScrollLeft = snapshot[i + 1]->getHeight();
|
||||
@@ -782,12 +823,50 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
auto &link = hoverLayoutElement->getLink();
|
||||
if (event->button() != Qt::LeftButton ||
|
||||
!singletons::SettingManager::getInstance().linksDoubleClickOnly) {
|
||||
this->handleLinkClick(event, link, layout.get());
|
||||
}
|
||||
|
||||
this->linkClicked.invoke(link);
|
||||
}
|
||||
|
||||
void ChannelView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
if (singletons::SettingManager::getInstance().linksDoubleClickOnly) {
|
||||
std::shared_ptr<messages::MessageLayout> layout;
|
||||
QPoint relativePos;
|
||||
int messageIndex;
|
||||
|
||||
if (!tryGetMessageAt(event->pos(), layout, relativePos, messageIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// message under cursor is collapsed
|
||||
if (layout->getFlags() & MessageLayout::Collapsed) {
|
||||
return;
|
||||
}
|
||||
|
||||
const messages::MessageLayoutElement *hoverLayoutElement =
|
||||
layout->getElementAt(relativePos);
|
||||
|
||||
if (hoverLayoutElement == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &link = hoverLayoutElement->getLink();
|
||||
this->handleLinkClick(event, link, layout.get());
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelView::handleLinkClick(QMouseEvent *event, const messages::Link &link,
|
||||
messages::MessageLayout *layout)
|
||||
{
|
||||
switch (link.getType()) {
|
||||
case messages::Link::UserInfo: {
|
||||
auto user = link.getValue();
|
||||
this->userPopupWidget.setName(user);
|
||||
this->userPopupWidget.move(event->screenPos().toPoint());
|
||||
this->userPopupWidget.moveTo(this, event->screenPos().toPoint());
|
||||
this->userPopupWidget.show();
|
||||
this->userPopupWidget.setFocus();
|
||||
|
||||
@@ -795,7 +874,24 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
|
||||
break;
|
||||
}
|
||||
case messages::Link::Url: {
|
||||
QDesktopServices::openUrl(QUrl(link.getValue()));
|
||||
if (event->button() == Qt::RightButton) {
|
||||
static QMenu *menu = nullptr;
|
||||
static QString url;
|
||||
|
||||
if (menu == nullptr) {
|
||||
menu = new QMenu;
|
||||
menu->addAction("Open in browser",
|
||||
[] { QDesktopServices::openUrl(QUrl(url)); });
|
||||
menu->addAction("Copy to clipboard",
|
||||
[] { QApplication::clipboard()->setText(url); });
|
||||
}
|
||||
|
||||
url = link.getValue();
|
||||
menu->move(QCursor::pos());
|
||||
menu->show();
|
||||
} else {
|
||||
QDesktopServices::openUrl(QUrl(link.getValue()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case messages::Link::UserAction: {
|
||||
|
||||
@@ -38,9 +38,12 @@ public:
|
||||
void clearSelection();
|
||||
void setEnableScrollingToBottom(bool);
|
||||
bool getEnableScrollingToBottom() const;
|
||||
void setOverrideFlags(boost::optional<messages::MessageElement::Flags> value);
|
||||
const boost::optional<messages::MessageElement::Flags> &getOverrideFlags() const;
|
||||
void pause(int msecTimeout);
|
||||
void updateLastReadMessage();
|
||||
|
||||
void setChannel(SharedChannel channel);
|
||||
void setChannel(ChannelPtr channel);
|
||||
messages::LimitedQueueSnapshot<messages::MessageLayoutPtr> getMessagesSnapshot();
|
||||
void layoutMessages();
|
||||
|
||||
@@ -49,8 +52,11 @@ public:
|
||||
boost::signals2::signal<void(QMouseEvent *)> mouseDown;
|
||||
boost::signals2::signal<void()> selectionChanged;
|
||||
pajlada::Signals::NoArgSignal highlightedMessageReceived;
|
||||
pajlada::Signals::Signal<const messages::Link &> linkClicked;
|
||||
|
||||
protected:
|
||||
virtual void themeRefreshEvent() override;
|
||||
|
||||
virtual void resizeEvent(QResizeEvent *) override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *) override;
|
||||
@@ -62,6 +68,10 @@ protected:
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
void handleLinkClick(QMouseEvent *event, const messages::Link &link,
|
||||
messages::MessageLayout *layout);
|
||||
|
||||
bool tryGetMessageAt(QPoint p, std::shared_ptr<messages::MessageLayout> &message,
|
||||
QPoint &relativePos, int &index);
|
||||
@@ -72,6 +82,8 @@ private:
|
||||
bool messageWasAdded = false;
|
||||
bool paused = false;
|
||||
QTimer pauseTimeout;
|
||||
boost::optional<messages::MessageElement::Flags> overrideFlags;
|
||||
messages::MessageLayoutPtr lastReadMessage;
|
||||
|
||||
messages::LimitedQueueSnapshot<messages::MessageLayoutPtr> snapshot;
|
||||
|
||||
@@ -82,7 +94,7 @@ private:
|
||||
void setSelection(const messages::SelectionItem &start, const messages::SelectionItem &end);
|
||||
messages::MessageElement::Flags getFlags() const;
|
||||
|
||||
SharedChannel channel;
|
||||
ChannelPtr channel;
|
||||
|
||||
Scrollbar scrollBar;
|
||||
RippleEffectLabel *goToBottom;
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "label.hpp"
|
||||
#include "singletons/fontmanager.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
Label::Label(BaseWidget *parent)
|
||||
: BaseWidget(parent)
|
||||
{
|
||||
singletons::FontManager::getInstance().fontChanged.connect(
|
||||
[this]() { this->scaleChangedEvent(this->getScale()); });
|
||||
}
|
||||
|
||||
const QString &Label::getText() const
|
||||
{
|
||||
return this->text;
|
||||
}
|
||||
|
||||
void Label::setText(const QString &value)
|
||||
{
|
||||
this->text = value;
|
||||
this->scaleChangedEvent(this->getScale());
|
||||
}
|
||||
|
||||
FontStyle Label::getFontStyle() const
|
||||
{
|
||||
return this->fontStyle;
|
||||
}
|
||||
|
||||
void Label::setFontStyle(FontStyle style)
|
||||
{
|
||||
this->fontStyle = style;
|
||||
this->scaleChangedEvent(this->getScale());
|
||||
}
|
||||
|
||||
void Label::scaleChangedEvent(float scale)
|
||||
{
|
||||
QFontMetrics metrics =
|
||||
singletons::FontManager::getInstance().getFontMetrics(this->fontStyle, scale);
|
||||
|
||||
this->preferedSize = QSize(metrics.width(this->text), metrics.height());
|
||||
|
||||
this->updateGeometry();
|
||||
}
|
||||
|
||||
QSize Label::sizeHint() const
|
||||
{
|
||||
return this->preferedSize;
|
||||
}
|
||||
|
||||
QSize Label::minimumSizeHint() const
|
||||
{
|
||||
return this->preferedSize;
|
||||
}
|
||||
|
||||
void Label::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setFont(singletons::FontManager::getInstance().getFont(
|
||||
this->fontStyle, this->getScale() / painter.device()->devicePixelRatioF()));
|
||||
|
||||
int width = singletons::FontManager::getInstance()
|
||||
.getFontMetrics(this->fontStyle, this->getScale())
|
||||
.width(this->text);
|
||||
|
||||
int flags = Qt::TextSingleLine;
|
||||
|
||||
if (this->width() < width) {
|
||||
flags |= Qt::AlignLeft | Qt::AlignVCenter;
|
||||
} else {
|
||||
flags |= Qt::AlignCenter;
|
||||
}
|
||||
|
||||
painter.drawText(this->rect(), flags, this->text);
|
||||
}
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "singletons/fontmanager.hpp"
|
||||
#include "widgets/basewidget.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
|
||||
class Label : public BaseWidget
|
||||
{
|
||||
public:
|
||||
Label(BaseWidget *parent);
|
||||
|
||||
const QString &getText() const;
|
||||
void setText(const QString &text);
|
||||
|
||||
FontStyle getFontStyle() const;
|
||||
void setFontStyle(FontStyle style);
|
||||
|
||||
protected:
|
||||
virtual void scaleChangedEvent(float scale) override;
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
virtual QSize sizeHint() const override;
|
||||
virtual QSize minimumSizeHint() const override;
|
||||
|
||||
private:
|
||||
QSize preferedSize;
|
||||
QString text;
|
||||
FontStyle fontStyle = FontStyle::Medium;
|
||||
};
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
||||
@@ -1,12 +1,16 @@
|
||||
#include "widgets/helper/notebookbutton.hpp"
|
||||
#include "singletons/thememanager.hpp"
|
||||
#include "widgets/helper/rippleeffectbutton.hpp"
|
||||
#include "widgets/notebook.hpp"
|
||||
#include "widgets/splitcontainer.hpp"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QRadialGradient>
|
||||
|
||||
#define nuuls nullptr
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
|
||||
@@ -14,6 +18,8 @@ NotebookButton::NotebookButton(BaseWidget *parent)
|
||||
: RippleEffectButton(parent)
|
||||
{
|
||||
setMouseEffectColor(QColor(0, 0, 0));
|
||||
|
||||
this->setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void NotebookButton::paintEvent(QPaintEvent *)
|
||||
@@ -97,5 +103,46 @@ void NotebookButton::mouseReleaseEvent(QMouseEvent *event)
|
||||
RippleEffectButton::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void NotebookButton::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
if (!event->mimeData()->hasFormat("chatterino/split"))
|
||||
return;
|
||||
|
||||
event->acceptProposedAction();
|
||||
|
||||
auto e = new QMouseEvent(QMouseEvent::MouseButtonPress,
|
||||
QPointF(this->width() / 2, this->height() / 2), Qt::LeftButton,
|
||||
Qt::LeftButton, 0);
|
||||
RippleEffectButton::mousePressEvent(e);
|
||||
delete e;
|
||||
}
|
||||
|
||||
void NotebookButton::dragLeaveEvent(QDragLeaveEvent *)
|
||||
{
|
||||
this->mouseDown = true;
|
||||
this->update();
|
||||
|
||||
auto e = new QMouseEvent(QMouseEvent::MouseButtonRelease,
|
||||
QPointF(this->width() / 2, this->height() / 2), Qt::LeftButton,
|
||||
Qt::LeftButton, 0);
|
||||
RippleEffectButton::mouseReleaseEvent(e);
|
||||
delete e;
|
||||
}
|
||||
|
||||
void NotebookButton::dropEvent(QDropEvent *event)
|
||||
{
|
||||
if (SplitContainer::isDraggingSplit) {
|
||||
event->acceptProposedAction();
|
||||
|
||||
Notebook *notebook = dynamic_cast<Notebook *>(this->parentWidget());
|
||||
|
||||
if (notebook != nuuls) {
|
||||
SplitContainer *tab = notebook->addNewPage();
|
||||
|
||||
SplitContainer::draggingSplit->setParent(tab);
|
||||
tab->addToLayout(SplitContainer::draggingSplit);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -21,8 +21,11 @@ public:
|
||||
NotebookButton(BaseWidget *parent);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void paintEvent(QPaintEvent *) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *) override;
|
||||
virtual void dragEnterEvent(QDragEnterEvent *) override;
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *) override;
|
||||
virtual void dropEvent(QDropEvent *) override;
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
|
||||
@@ -25,7 +25,6 @@ NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid)
|
||||
, useDefaultBehaviour(fS("{}/useDefaultBehaviour", this->settingRoot), true)
|
||||
, menu(this)
|
||||
{
|
||||
this->calcSize();
|
||||
this->setAcceptDrops(true);
|
||||
|
||||
this->positionChangedAnimation.setEasingCurve(QEasingCurve(QEasingCurve::InCubic));
|
||||
@@ -65,22 +64,25 @@ NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid)
|
||||
|
||||
this->menu.addAction(enableHighlightsOnNewMessageAction);
|
||||
|
||||
connect(enableHighlightsOnNewMessageAction, &QAction::toggled, [this](bool newValue) {
|
||||
QObject::connect(enableHighlightsOnNewMessageAction, &QAction::toggled, [this](bool newValue) {
|
||||
debug::Log("New value is {}", newValue); //
|
||||
});
|
||||
}
|
||||
|
||||
void NotebookTab::calcSize()
|
||||
void NotebookTab::themeRefreshEvent()
|
||||
{
|
||||
float scale = getDpiMultiplier();
|
||||
this->update();
|
||||
}
|
||||
|
||||
void NotebookTab::updateSize()
|
||||
{
|
||||
float scale = getScale();
|
||||
QString qTitle(qS(this->title));
|
||||
|
||||
if (singletons::SettingManager::getInstance().hideTabX) {
|
||||
this->resize(static_cast<int>((fontMetrics().width(qTitle) + 16) * scale),
|
||||
static_cast<int>(24 * scale));
|
||||
this->resize((int)((fontMetrics().width(qTitle) + 16) * scale), (int)(24 * scale));
|
||||
} else {
|
||||
this->resize(static_cast<int>((fontMetrics().width(qTitle) + 8 + 24) * scale),
|
||||
static_cast<int>(24 * scale));
|
||||
this->resize((int)((fontMetrics().width(qTitle) + 8 + 24) * scale), (int)(24 * scale));
|
||||
}
|
||||
|
||||
if (this->parent() != nullptr) {
|
||||
@@ -97,7 +99,7 @@ void NotebookTab::setTitle(const QString &newTitle)
|
||||
{
|
||||
this->title = newTitle.toStdString();
|
||||
|
||||
this->calcSize();
|
||||
this->updateSize();
|
||||
}
|
||||
|
||||
bool NotebookTab::isSelected() const
|
||||
@@ -134,7 +136,7 @@ QRect NotebookTab::getDesiredRect() const
|
||||
|
||||
void NotebookTab::hideTabXChanged(bool)
|
||||
{
|
||||
this->calcSize();
|
||||
this->updateSize();
|
||||
this->update();
|
||||
}
|
||||
|
||||
@@ -197,7 +199,7 @@ void NotebookTab::paintEvent(QPaintEvent *)
|
||||
painter.setPen(colors.text);
|
||||
|
||||
// set area for text
|
||||
float scale = this->getDpiMultiplier();
|
||||
float scale = this->getScale();
|
||||
int rectW = (settingManager.hideTabX ? 0 : static_cast<int>(16) * scale);
|
||||
QRect rect(0, 0, this->width() - rectW, this->height());
|
||||
|
||||
@@ -291,14 +293,14 @@ void NotebookTab::mouseMoveEvent(QMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
if (this->mouseDown && !this->getDesiredRect().contains(event->pos())) {
|
||||
QPoint relPoint = this->mapToParent(event->pos());
|
||||
QPoint relPoint = this->mapToParent(event->pos());
|
||||
|
||||
if (this->mouseDown && !this->getDesiredRect().contains(relPoint)) {
|
||||
int index;
|
||||
SplitContainer *clickedPage = notebook->tabAt(relPoint, index);
|
||||
SplitContainer *clickedPage = notebook->tabAt(relPoint, index, this->width());
|
||||
|
||||
if (clickedPage != nullptr && clickedPage != this->page) {
|
||||
this->notebook->rearrangePage(clickedPage, index);
|
||||
this->notebook->rearrangePage(this->page, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class NotebookTab : public BaseWidget
|
||||
public:
|
||||
explicit NotebookTab(Notebook *_notebook, const std::string &_uuid);
|
||||
|
||||
void calcSize();
|
||||
void updateSize();
|
||||
|
||||
SplitContainer *page;
|
||||
|
||||
@@ -42,16 +42,18 @@ public:
|
||||
void hideTabXChanged(bool);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *) override;
|
||||
virtual void themeRefreshEvent() override;
|
||||
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void enterEvent(QEvent *) override;
|
||||
void leaveEvent(QEvent *) override;
|
||||
virtual void paintEvent(QPaintEvent *) override;
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void enterEvent(QEvent *) override;
|
||||
virtual void leaveEvent(QEvent *) override;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections;
|
||||
@@ -80,7 +82,7 @@ private:
|
||||
|
||||
QRect getXRect()
|
||||
{
|
||||
float scale = this->getDpiMultiplier();
|
||||
float scale = this->getScale();
|
||||
return QRect(this->width() - static_cast<int>(20 * scale), static_cast<int>(4 * scale),
|
||||
static_cast<int>(16 * scale), static_cast<int>(16 * scale));
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ void RippleEffectButton::paintEvent(QPaintEvent *)
|
||||
|
||||
if (this->pixmap != nullptr) {
|
||||
QRect rect = this->rect();
|
||||
int xD = 6 * this->getDpiMultiplier();
|
||||
int xD = 6 * this->getScale();
|
||||
|
||||
rect.moveLeft(xD);
|
||||
rect.setRight(rect.right() - xD - xD);
|
||||
@@ -57,6 +57,8 @@ void RippleEffectButton::paintEvent(QPaintEvent *)
|
||||
|
||||
void RippleEffectButton::fancyPaint(QPainter &painter)
|
||||
{
|
||||
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
QColor c;
|
||||
|
||||
if (this->mouseEffectColor) {
|
||||
|
||||
@@ -58,7 +58,7 @@ void SearchPopup::initLayout()
|
||||
}
|
||||
}
|
||||
|
||||
void SearchPopup::setChannel(SharedChannel channel)
|
||||
void SearchPopup::setChannel(ChannelPtr channel)
|
||||
{
|
||||
this->snapshot = channel->getMessageSnapshot();
|
||||
this->performSearch();
|
||||
@@ -70,7 +70,7 @@ void SearchPopup::performSearch()
|
||||
{
|
||||
QString text = searchInput->text();
|
||||
|
||||
SharedChannel channel(new Channel("search"));
|
||||
ChannelPtr channel(new Channel("search"));
|
||||
|
||||
for (size_t i = 0; i < this->snapshot.getLength(); i++) {
|
||||
messages::MessagePtr message = this->snapshot[i];
|
||||
|
||||
@@ -10,7 +10,8 @@ namespace widgets {
|
||||
|
||||
SettingsDialogTab::SettingsDialogTab(SettingsDialog *_dialog, settingspages::SettingsPage *_page,
|
||||
QString imageFileName)
|
||||
: dialog(_dialog)
|
||||
: BaseWidget(_dialog)
|
||||
, dialog(_dialog)
|
||||
, page(_page)
|
||||
{
|
||||
this->ui.labelText = page->getName();
|
||||
@@ -47,8 +48,8 @@ void SettingsDialogTab::paintEvent(QPaintEvent *)
|
||||
|
||||
this->style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
|
||||
|
||||
int a = (this->height() - 20) / 2;
|
||||
QPixmap pixmap = this->ui.icon.pixmap(QSize(20, 20));
|
||||
int a = (this->height() - (20 * this->getScale())) / 2;
|
||||
QPixmap pixmap = this->ui.icon.pixmap(QSize(this->height() - a * 2, this->height() - a * 2));
|
||||
|
||||
painter.drawPixmap(a, a, pixmap);
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <QPaintEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#include "widgets/basewidget.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
@@ -12,7 +14,7 @@ class SettingsPage;
|
||||
|
||||
class SettingsDialog;
|
||||
|
||||
class SettingsDialogTab : public QWidget
|
||||
class SettingsDialogTab : public BaseWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "twitch/twitchchannel.hpp"
|
||||
#include "util/layoutcreator.hpp"
|
||||
#include "util/urlfetch.hpp"
|
||||
#include "widgets/helper/label.hpp"
|
||||
#include "widgets/split.hpp"
|
||||
#include "widgets/splitcontainer.hpp"
|
||||
#include "widgets/tooltipwidget.hpp"
|
||||
@@ -47,7 +48,9 @@ SplitHeader::SplitHeader(Split *_split)
|
||||
layout->addStretch(1);
|
||||
|
||||
// channel name label
|
||||
// auto title = layout.emplace<Label>(this).assign(&this->titleLabel);
|
||||
auto title = layout.emplace<SignalLabel>().assign(&this->titleLabel);
|
||||
title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
title->setMouseTracking(true);
|
||||
QObject::connect(this->titleLabel, &SignalLabel::mouseDoubleClick, this,
|
||||
&SplitHeader::mouseDoubleClickEvent);
|
||||
@@ -66,7 +69,8 @@ SplitHeader::SplitHeader(Split *_split)
|
||||
|
||||
// ---- misc
|
||||
this->layout()->setMargin(0);
|
||||
this->refreshTheme();
|
||||
this->themeRefreshEvent();
|
||||
this->scaleChangedEvent(this->getScale());
|
||||
|
||||
this->updateChannelText();
|
||||
|
||||
@@ -93,7 +97,7 @@ void SplitHeader::addDropdownItems(RippleEffectButton *label)
|
||||
this->dropdownMenu.addSeparator();
|
||||
#ifdef USEWEBENGINE
|
||||
this->dropdownMenu.addAction("Start watching", this, [this]{
|
||||
SharedChannel _channel = this->split->getChannel();
|
||||
ChannelPtr _channel = this->split->getChannel();
|
||||
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(_channel.get());
|
||||
|
||||
if (tc != nullptr) {
|
||||
@@ -133,13 +137,15 @@ void SplitHeader::initializeChannelSignals()
|
||||
}
|
||||
}
|
||||
|
||||
void SplitHeader::resizeEvent(QResizeEvent *event)
|
||||
void SplitHeader::scaleChangedEvent(float scale)
|
||||
{
|
||||
int w = 28 * getDpiMultiplier();
|
||||
int w = 28 * scale;
|
||||
|
||||
this->setFixedHeight(w);
|
||||
this->dropdownButton->setFixedWidth(w);
|
||||
this->moderationButton->setFixedWidth(w);
|
||||
// this->titleLabel->setFont(
|
||||
// singletons::FontManager::getInstance().getFont(FontStyle::Medium, scale));
|
||||
}
|
||||
|
||||
void SplitHeader::updateChannelText()
|
||||
@@ -180,7 +186,7 @@ void SplitHeader::updateModerationModeIcon()
|
||||
: resourceManager.moderationmode_disabled->getPixmap());
|
||||
|
||||
bool modButtonVisible = false;
|
||||
SharedChannel channel = this->split->getChannel();
|
||||
ChannelPtr channel = this->split->getChannel();
|
||||
|
||||
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(channel.get());
|
||||
|
||||
@@ -242,7 +248,7 @@ void SplitHeader::rightButtonClicked()
|
||||
{
|
||||
}
|
||||
|
||||
void SplitHeader::refreshTheme()
|
||||
void SplitHeader::themeRefreshEvent()
|
||||
{
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::Foreground, this->themeManager.splits.header.text);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/basewidget.hpp"
|
||||
#include "widgets/helper/label.hpp"
|
||||
#include "widgets/helper/rippleeffectlabel.hpp"
|
||||
#include "widgets/helper/signallabel.hpp"
|
||||
|
||||
@@ -34,12 +35,14 @@ public:
|
||||
void updateModerationModeIcon();
|
||||
|
||||
protected:
|
||||
virtual void scaleChangedEvent(float) override;
|
||||
virtual void themeRefreshEvent() override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void leaveEvent(QEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
private:
|
||||
Split *const split;
|
||||
@@ -50,6 +53,7 @@ private:
|
||||
boost::signals2::connection onlineStatusChangedConnection;
|
||||
|
||||
RippleEffectButton *dropdownButton;
|
||||
// Label *titleLabel;
|
||||
SignalLabel *titleLabel;
|
||||
RippleEffectButton *moderationButton;
|
||||
|
||||
@@ -57,8 +61,6 @@ private:
|
||||
|
||||
void rightButtonClicked();
|
||||
|
||||
virtual void refreshTheme() override;
|
||||
|
||||
void initializeChannelSignals();
|
||||
|
||||
QString tooltip;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "singletons/ircmanager.hpp"
|
||||
#include "singletons/settingsmanager.hpp"
|
||||
#include "singletons/thememanager.hpp"
|
||||
#include "util/layoutcreator.hpp"
|
||||
#include "widgets/notebook.hpp"
|
||||
#include "widgets/split.hpp"
|
||||
#include "widgets/splitcontainer.hpp"
|
||||
@@ -17,68 +18,124 @@ namespace widgets {
|
||||
SplitInput::SplitInput(Split *_chatWidget)
|
||||
: BaseWidget(_chatWidget)
|
||||
, chatWidget(_chatWidget)
|
||||
, emotesLabel(this)
|
||||
{
|
||||
this->setLayout(&this->hbox);
|
||||
this->initLayout();
|
||||
|
||||
this->hbox.setMargin(4);
|
||||
// auto completion
|
||||
auto completer = new QCompleter(
|
||||
singletons::CompletionManager::getInstance().createModel(this->chatWidget->channelName));
|
||||
|
||||
this->hbox.addLayout(&this->editContainer);
|
||||
this->hbox.addLayout(&this->vbox);
|
||||
this->ui.textEdit->setCompleter(completer);
|
||||
|
||||
// misc
|
||||
this->installKeyPressedEvent();
|
||||
this->themeRefreshEvent();
|
||||
this->scaleChangedEvent(this->getScale());
|
||||
}
|
||||
|
||||
void SplitInput::initLayout()
|
||||
{
|
||||
auto &fontManager = singletons::FontManager::getInstance();
|
||||
util::LayoutCreator<SplitInput> layoutCreator(this);
|
||||
|
||||
auto layout = layoutCreator.setLayoutType<QHBoxLayout>().withoutMargin().assign(&this->ui.hbox);
|
||||
|
||||
// input
|
||||
auto textEdit = layout.emplace<ResizingTextEdit>().assign(&this->ui.textEdit);
|
||||
connect(textEdit.getElement(), &ResizingTextEdit::textChanged, this,
|
||||
&SplitInput::editTextChanged);
|
||||
|
||||
// right box
|
||||
auto box = layout.emplace<QVBoxLayout>().withoutMargin();
|
||||
box->setSpacing(0);
|
||||
{
|
||||
auto textEditLength = box.emplace<QLabel>().assign(&this->ui.textEditLength);
|
||||
textEditLength->setAlignment(Qt::AlignRight);
|
||||
|
||||
box->addStretch(1);
|
||||
box.emplace<RippleEffectLabel>().assign(&this->ui.emoteButton);
|
||||
}
|
||||
|
||||
this->ui.emoteButton->getLabel().setTextFormat(Qt::RichText);
|
||||
|
||||
// ---- misc
|
||||
|
||||
// set edit font
|
||||
this->ui.textEdit->setFont(
|
||||
fontManager.getFont(singletons::FontManager::Type::Medium, this->getScale()));
|
||||
|
||||
this->textInput.setFont(
|
||||
fontManager.getFont(singletons::FontManager::Type::Medium, this->getDpiMultiplier()));
|
||||
this->managedConnections.emplace_back(fontManager.fontChanged.connect([this, &fontManager]() {
|
||||
this->textInput.setFont(
|
||||
fontManager.getFont(singletons::FontManager::Type::Medium, this->getDpiMultiplier()));
|
||||
this->ui.textEdit->setFont(
|
||||
fontManager.getFont(singletons::FontManager::Type::Medium, this->getScale()));
|
||||
}));
|
||||
|
||||
this->editContainer.addWidget(&this->textInput);
|
||||
this->editContainer.setMargin(2);
|
||||
|
||||
this->emotesLabel.setMinimumHeight(24);
|
||||
|
||||
this->vbox.addWidget(&this->textLengthLabel);
|
||||
this->vbox.addStretch(1);
|
||||
this->vbox.addWidget(&this->emotesLabel);
|
||||
|
||||
this->textLengthLabel.setText("");
|
||||
this->textLengthLabel.setAlignment(Qt::AlignRight);
|
||||
|
||||
this->emotesLabel.getLabel().setTextFormat(Qt::RichText);
|
||||
this->emotesLabel.getLabel().setText("<img src=':/images/emote.svg' width='12' height='12' "
|
||||
"/>");
|
||||
|
||||
connect(&this->emotesLabel, &RippleEffectLabel::clicked, [this] {
|
||||
if (this->emotePopup == nullptr) {
|
||||
this->emotePopup = new EmotePopup(this->themeManager);
|
||||
// open emote popup
|
||||
QObject::connect(this->ui.emoteButton, &RippleEffectLabel::clicked, [this] {
|
||||
if (!this->emotePopup) {
|
||||
this->emotePopup = std::make_unique<EmotePopup>(this->themeManager);
|
||||
this->emotePopup->linkClicked.connect([this](const messages::Link &link) {
|
||||
if (link.getType() == messages::Link::InsertText) {
|
||||
this->insertText(link.getValue() + " ");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this->emotePopup->resize((int)(300 * this->emotePopup->getDpiMultiplier()),
|
||||
(int)(500 * this->emotePopup->getDpiMultiplier()));
|
||||
this->emotePopup->resize((int)(300 * this->emotePopup->getScale()),
|
||||
(int)(500 * this->emotePopup->getScale()));
|
||||
this->emotePopup->loadChannel(this->chatWidget->getChannel());
|
||||
this->emotePopup->show();
|
||||
});
|
||||
|
||||
connect(&textInput, &ResizingTextEdit::textChanged, this, &SplitInput::editTextChanged);
|
||||
// clear channelview selection when selecting in the input
|
||||
QObject::connect(this->ui.textEdit, &QTextEdit::copyAvailable, [this](bool available) {
|
||||
if (available) {
|
||||
this->chatWidget->view.clearSelection();
|
||||
}
|
||||
});
|
||||
|
||||
this->refreshTheme();
|
||||
textLengthLabel.setHidden(!singletons::SettingManager::getInstance().showMessageLength);
|
||||
// textEditLength visibility
|
||||
singletons::SettingManager::getInstance().showMessageLength.connect(
|
||||
[this](const bool &value, auto) { this->ui.textEditLength->setHidden(!value); },
|
||||
this->managedConnections);
|
||||
}
|
||||
|
||||
auto completer = new QCompleter(
|
||||
singletons::CompletionManager::getInstance().createModel(this->chatWidget->channelName));
|
||||
void SplitInput::scaleChangedEvent(float scale)
|
||||
{
|
||||
// update the icon size of the emote button
|
||||
QString text = "<img src=':/images/emote.svg' width='xD' height='xD' />";
|
||||
text.replace("xD", QString::number((int)12 * scale));
|
||||
|
||||
this->textInput.setCompleter(completer);
|
||||
this->ui.emoteButton->getLabel().setText(text);
|
||||
this->ui.emoteButton->setFixedHeight((int)18 * scale);
|
||||
|
||||
this->textInput.keyPressed.connect([this](QKeyEvent *event) {
|
||||
// set maximum height
|
||||
this->setMaximumHeight((int)(150 * this->getScale()));
|
||||
|
||||
this->themeRefreshEvent();
|
||||
}
|
||||
|
||||
void SplitInput::themeRefreshEvent()
|
||||
{
|
||||
QPalette palette;
|
||||
|
||||
palette.setColor(QPalette::Foreground, this->themeManager.splits.input.text);
|
||||
|
||||
this->ui.textEditLength->setPalette(palette);
|
||||
|
||||
this->ui.textEdit->setStyleSheet(this->themeManager.splits.input.styleSheet);
|
||||
|
||||
this->ui.hbox->setMargin((this->themeManager.isLightTheme() ? 4 : 2) * this->getScale());
|
||||
}
|
||||
|
||||
void SplitInput::installKeyPressedEvent()
|
||||
{
|
||||
this->ui.textEdit->keyPressed.connect([this](QKeyEvent *event) {
|
||||
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
|
||||
auto c = this->chatWidget->getChannel();
|
||||
if (c == nullptr) {
|
||||
return;
|
||||
}
|
||||
QString message = textInput.toPlainText();
|
||||
QString message = ui.textEdit->toPlainText();
|
||||
|
||||
QString sendMessage =
|
||||
singletons::CommandManager::getInstance().execCommand(message, c, false);
|
||||
@@ -89,9 +146,9 @@ SplitInput::SplitInput(Split *_chatWidget)
|
||||
|
||||
event->accept();
|
||||
if (!(event->modifiers() == Qt::ControlModifier)) {
|
||||
this->textInput.setText(QString());
|
||||
this->ui.textEdit->setText(QString());
|
||||
this->prevIndex = 0;
|
||||
} else if (this->textInput.toPlainText() ==
|
||||
} else if (this->ui.textEdit->toPlainText() ==
|
||||
this->prevMsg.at(this->prevMsg.size() - 1)) {
|
||||
this->prevMsg.removeLast();
|
||||
}
|
||||
@@ -110,7 +167,7 @@ SplitInput::SplitInput(Split *_chatWidget)
|
||||
} else {
|
||||
if (this->prevMsg.size() && this->prevIndex) {
|
||||
this->prevIndex--;
|
||||
this->textInput.setText(this->prevMsg.at(this->prevIndex));
|
||||
this->ui.textEdit->setText(this->prevMsg.at(this->prevIndex));
|
||||
}
|
||||
}
|
||||
} else if (event->key() == Qt::Key_Down) {
|
||||
@@ -128,10 +185,10 @@ SplitInput::SplitInput(Split *_chatWidget)
|
||||
if (this->prevIndex != (this->prevMsg.size() - 1) &&
|
||||
this->prevIndex != this->prevMsg.size()) {
|
||||
this->prevIndex++;
|
||||
this->textInput.setText(this->prevMsg.at(this->prevIndex));
|
||||
this->ui.textEdit->setText(this->prevMsg.at(this->prevIndex));
|
||||
} else {
|
||||
this->prevIndex = this->prevMsg.size();
|
||||
this->textInput.setText(QString());
|
||||
this->ui.textEdit->setText(QString());
|
||||
}
|
||||
}
|
||||
} else if (event->key() == Qt::Key_Left) {
|
||||
@@ -183,49 +240,32 @@ SplitInput::SplitInput(Split *_chatWidget)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
singletons::SettingManager::getInstance().showMessageLength.connect(
|
||||
[this](const bool &value, auto) { this->textLengthLabel.setHidden(!value); },
|
||||
this->managedConnections);
|
||||
|
||||
QObject::connect(&this->textInput, &QTextEdit::copyAvailable, [this](bool available) {
|
||||
if (available) {
|
||||
this->chatWidget->view.clearSelection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SplitInput::clearSelection()
|
||||
{
|
||||
QTextCursor c = this->textInput.textCursor();
|
||||
QTextCursor c = this->ui.textEdit->textCursor();
|
||||
|
||||
c.setPosition(c.position());
|
||||
c.setPosition(c.position(), QTextCursor::KeepAnchor);
|
||||
|
||||
this->textInput.setTextCursor(c);
|
||||
this->ui.textEdit->setTextCursor(c);
|
||||
}
|
||||
|
||||
QString SplitInput::getInputText() const
|
||||
{
|
||||
return this->textInput.toPlainText();
|
||||
return this->ui.textEdit->toPlainText();
|
||||
}
|
||||
|
||||
void SplitInput::refreshTheme()
|
||||
void SplitInput::insertText(const QString &text)
|
||||
{
|
||||
QPalette palette;
|
||||
|
||||
palette.setColor(QPalette::Foreground, this->themeManager.splits.input.text);
|
||||
|
||||
this->textLengthLabel.setPalette(palette);
|
||||
|
||||
this->textInput.setStyleSheet(this->themeManager.splits.input.styleSheet);
|
||||
|
||||
this->hbox.setMargin((this->themeManager.isLightTheme() ? 4 : 2) * this->getDpiMultiplier());
|
||||
this->ui.textEdit->insertPlainText(text);
|
||||
}
|
||||
|
||||
void SplitInput::editTextChanged()
|
||||
{
|
||||
QString text = this->textInput.toPlainText();
|
||||
// set textLengthLabel value
|
||||
QString text = this->ui.textEdit->toPlainText();
|
||||
|
||||
this->textChanged.invoke(text);
|
||||
|
||||
@@ -244,7 +284,7 @@ void SplitInput::editTextChanged()
|
||||
labelText = QString::number(text.length());
|
||||
}
|
||||
|
||||
this->textLengthLabel.setText(labelText);
|
||||
this->ui.textEditLength->setText(labelText);
|
||||
}
|
||||
|
||||
void SplitInput::paintEvent(QPaintEvent *)
|
||||
@@ -255,7 +295,7 @@ void SplitInput::paintEvent(QPaintEvent *)
|
||||
|
||||
QPen pen(this->themeManager.splits.input.border);
|
||||
if (this->themeManager.isLightTheme()) {
|
||||
pen.setWidth((int)(6 * this->getDpiMultiplier()));
|
||||
pen.setWidth((int)(6 * this->getScale()));
|
||||
}
|
||||
painter.setPen(pen);
|
||||
painter.drawRect(0, 0, this->width() - 1, this->height() - 1);
|
||||
@@ -264,14 +304,10 @@ void SplitInput::paintEvent(QPaintEvent *)
|
||||
void SplitInput::resizeEvent(QResizeEvent *)
|
||||
{
|
||||
if (this->height() == this->maximumHeight()) {
|
||||
this->textInput.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
this->ui.textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
} else {
|
||||
this->textInput.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
this->ui.textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
|
||||
this->setMaximumHeight((int)(150 * this->getDpiMultiplier()));
|
||||
|
||||
this->refreshTheme();
|
||||
}
|
||||
|
||||
void SplitInput::mousePressEvent(QMouseEvent *)
|
||||
|
||||
@@ -27,10 +27,13 @@ public:
|
||||
|
||||
void clearSelection();
|
||||
QString getInputText() const;
|
||||
void insertText(const QString &text);
|
||||
|
||||
pajlada::Signals::Signal<const QString &> textChanged;
|
||||
|
||||
protected:
|
||||
virtual void scaleChangedEvent(float scale) override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *) override;
|
||||
virtual void resizeEvent(QResizeEvent *) override;
|
||||
|
||||
@@ -38,18 +41,29 @@ protected:
|
||||
|
||||
private:
|
||||
Split *const chatWidget;
|
||||
EmotePopup *emotePopup = nullptr;
|
||||
std::unique_ptr<EmotePopup> emotePopup;
|
||||
|
||||
struct {
|
||||
ResizingTextEdit *textEdit;
|
||||
QLabel *textEditLength;
|
||||
RippleEffectLabel *emoteButton;
|
||||
|
||||
QHBoxLayout *hbox;
|
||||
} ui;
|
||||
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections;
|
||||
QHBoxLayout hbox;
|
||||
QVBoxLayout vbox;
|
||||
QHBoxLayout editContainer;
|
||||
ResizingTextEdit textInput;
|
||||
QLabel textLengthLabel;
|
||||
RippleEffectLabel emotesLabel;
|
||||
// QHBoxLayout hbox;
|
||||
// QVBoxLayout vbox;
|
||||
// QHBoxLayout editContainer;
|
||||
// ResizingTextEdit textInput;
|
||||
// QLabel textLengthLabel;
|
||||
// RippleEffectLabel emotesLabel;
|
||||
QStringList prevMsg;
|
||||
int prevIndex = 0;
|
||||
virtual void refreshTheme() override;
|
||||
|
||||
void initLayout();
|
||||
void installKeyPressedEvent();
|
||||
virtual void themeRefreshEvent() override;
|
||||
|
||||
private slots:
|
||||
void editTextChanged();
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "titlebarbutton.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
TitleBarButton::TitleBarButton()
|
||||
: RippleEffectButton(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
TitleBarButton::Style TitleBarButton::getButtonStyle() const
|
||||
{
|
||||
return this->style;
|
||||
}
|
||||
|
||||
void TitleBarButton::setButtonStyle(Style _style)
|
||||
{
|
||||
this->style = _style;
|
||||
this->update();
|
||||
}
|
||||
|
||||
void TitleBarButton::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
||||
QColor color = "#000";
|
||||
QColor background = "#fff";
|
||||
|
||||
int xD = this->height() / 3;
|
||||
int centerX = this->width() / 2;
|
||||
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
switch (this->style) {
|
||||
case Minimize: {
|
||||
painter.fillRect(centerX - xD / 2, xD * 3 / 2, xD, 1, color);
|
||||
break;
|
||||
}
|
||||
case Maximize: {
|
||||
painter.setPen(color);
|
||||
painter.drawRect(centerX - xD / 2, xD, xD - 1, xD - 1);
|
||||
break;
|
||||
}
|
||||
case Unmaximize: {
|
||||
int xD2 = xD * 1 / 5;
|
||||
int xD3 = xD * 4 / 5;
|
||||
|
||||
painter.drawRect(centerX - xD / 2 + xD2, xD, xD3, xD3);
|
||||
painter.fillRect(centerX - xD / 2, xD + xD2, xD3, xD3, QColor("#fff"));
|
||||
painter.drawRect(centerX - xD / 2, xD + xD2, xD3, xD3);
|
||||
break;
|
||||
}
|
||||
case Close: {
|
||||
QRect rect(centerX - xD / 2, xD, xD - 1, xD - 1);
|
||||
painter.setPen(QPen(color, 1));
|
||||
|
||||
painter.drawLine(rect.topLeft(), rect.bottomRight());
|
||||
painter.drawLine(rect.topRight(), rect.bottomLeft());
|
||||
break;
|
||||
}
|
||||
case User: {
|
||||
color = QColor("#333");
|
||||
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||
|
||||
auto a = xD / 3;
|
||||
QPainterPath path;
|
||||
|
||||
painter.save();
|
||||
painter.translate(3, 3);
|
||||
|
||||
path.arcMoveTo(a, 4 * a, 6 * a, 6 * a, 0);
|
||||
path.arcTo(a, 4 * a, 6 * a, 6 * a, 0, 180);
|
||||
|
||||
painter.fillPath(path, color);
|
||||
|
||||
painter.setBrush(background);
|
||||
painter.drawEllipse(2 * a, 1 * a, 4 * a, 4 * a);
|
||||
|
||||
painter.setBrush(color);
|
||||
painter.drawEllipse(2.5 * a, 1.5 * a, 3 * a + 1, 3 * a);
|
||||
painter.restore();
|
||||
|
||||
break;
|
||||
}
|
||||
case Settings: {
|
||||
color = QColor("#333");
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||
|
||||
painter.save();
|
||||
painter.translate(3, 3);
|
||||
|
||||
auto a = xD / 3;
|
||||
QPainterPath path;
|
||||
|
||||
path.arcMoveTo(a, a, 6 * a, 6 * a, 0 - (360 / 32.0));
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
path.arcTo(a, a, 6 * a, 6 * a, i * (360 / 8.0) - (360 / 32.0), (360 / 32.0));
|
||||
path.arcTo(2 * a, 2 * a, 4 * a, 4 * a, i * (360 / 8.0) + (360 / 32.0),
|
||||
(360 / 32.0));
|
||||
}
|
||||
|
||||
painter.strokePath(path, color);
|
||||
painter.fillPath(path, color);
|
||||
|
||||
painter.setBrush(background);
|
||||
painter.drawEllipse(3 * a, 3 * a, 2 * a, 2 * a);
|
||||
painter.restore();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->fancyPaint(painter);
|
||||
}
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "widgets/helper/rippleeffectbutton.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
class TitleBarButton : public RippleEffectButton
|
||||
{
|
||||
public:
|
||||
enum Style { Minimize = 1, Maximize = 2, Unmaximize = 4, Close = 8, User = 16, Settings = 32 };
|
||||
|
||||
TitleBarButton();
|
||||
|
||||
Style getButtonStyle() const;
|
||||
void setButtonStyle(Style style);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *) override;
|
||||
|
||||
private:
|
||||
Style style;
|
||||
};
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
||||
Reference in New Issue
Block a user