mirror-chatterino2/src/widgets/helper/notebooktab.cpp
Rasmus Karlsson 6ea3a1df08 Switch some c-style includes to c++-style includes (i.e. stdint.h to
cstdint)

Make MessageElement to a class to fit better with the derived classes.
Make MessageLayoutElement to a class to fit better with the derived
classes.

Remove virtual from override functions

Replace all instances of boost::signals2 with pajlada::Signals. This
lets us properly use clang code model to check for issues.

Add missing virtual destructor to AbstractIrcServer
Add missing virtual destructor to MessageLayoutElement

Remove unused "connectedConnection" connection in TwitchChannel

Fix typo in TrimChannelName function
Fix typo in MessageParseArgs

Replace some raw pointers with unique pointers where it made more sense.
This allowed us to remove some manually written destructors whose only
purpose was to delete that raw pointer.

Reformat: Add namespace comments
Reformat: Add empty empty lines between main namespace beginning and end
Reformat: Re-order includes
Reformat: Fix some includes that used quotes where they should use angle
brackets
Reformat: Replace some typedef's with using's

Filter out more useless warnings
2018-04-11 22:54:34 +02:00

371 lines
11 KiB
C++

#include "widgets/helper/notebooktab.hpp"
#include "common.hpp"
#include "debug/log.hpp"
#include "singletons/settingsmanager.hpp"
#include "singletons/thememanager.hpp"
#include "util/helpers.hpp"
#include "widgets/notebook.hpp"
#include "widgets/settingsdialog.hpp"
#include "widgets/textinputdialog.hpp"
#include <QApplication>
#include <QDebug>
#include <QLinearGradient>
#include <QPainter>
#include <boost/bind.hpp>
namespace chatterino {
namespace widgets {
NotebookTab::NotebookTab(Notebook *_notebook, const std::string &_uuid)
: BaseWidget(_notebook)
, uuid(_uuid)
, settingRoot(fS("/containers/{}/tab", this->uuid))
, positionChangedAnimation(this, "pos")
, notebook(_notebook)
, title(fS("{}/title", this->settingRoot), "")
, useDefaultBehaviour(fS("{}/useDefaultBehaviour", this->settingRoot), true)
, menu(this)
{
this->setAcceptDrops(true);
this->positionChangedAnimation.setEasingCurve(QEasingCurve(QEasingCurve::InCubic));
singletons::SettingManager::getInstance().hideTabX.connect(
boost::bind(&NotebookTab::hideTabXChanged, this, _1), this->managedConnections);
this->setMouseTracking(true);
this->menu.addAction("Rename", [this]() {
TextInputDialog d(this);
d.setWindowTitle("Change tab title (Leave empty for default behaviour)");
if (this->useDefaultBehaviour) {
d.setText("");
} else {
d.setText(this->getTitle());
}
if (d.exec() == QDialog::Accepted) {
QString newTitle = d.getText();
if (newTitle.isEmpty()) {
this->useDefaultBehaviour = true;
this->page->refreshTitle();
} else {
this->useDefaultBehaviour = false;
this->setTitle(newTitle);
}
}
});
QAction *enableHighlightsOnNewMessageAction =
new QAction("Enable highlights on new message", &this->menu);
enableHighlightsOnNewMessageAction->setCheckable(true);
this->menu.addAction("Close", [=]() { this->notebook->removePage(this->page); });
this->menu.addAction(enableHighlightsOnNewMessageAction);
QObject::connect(enableHighlightsOnNewMessageAction, &QAction::toggled, [this](bool newValue) {
debug::Log("New value is {}", newValue); //
});
}
void NotebookTab::themeRefreshEvent()
{
this->update();
}
void NotebookTab::updateSize()
{
float scale = getScale();
int width;
QString qTitle(qS(this->title));
if (singletons::SettingManager::getInstance().hideTabX) {
width = (int)((fontMetrics().width(qTitle) + 16 /*+ 16*/) * scale);
} else {
width = (int)((fontMetrics().width(qTitle) + 8 + 24 /*+ 16*/) * scale);
}
this->resize(std::min((int)(150 * scale), width), (int)(24 * scale));
if (this->parent() != nullptr) {
(static_cast<Notebook *>(this->parent()))->performLayout(true);
}
}
QString NotebookTab::getTitle() const
{
return qS(this->title);
}
void NotebookTab::setTitle(const QString &newTitle)
{
this->title = newTitle.toStdString();
this->updateSize();
}
bool NotebookTab::isSelected() const
{
return this->selected;
}
void NotebookTab::setSelected(bool value)
{
this->selected = value;
this->highlightState = HighlightState::None;
this->update();
}
void NotebookTab::setHighlightState(HighlightState newHighlightStyle)
{
if (this->isSelected()) {
return;
}
if (this->highlightState != HighlightState::Highlighted) {
this->highlightState = newHighlightStyle;
this->update();
}
}
QRect NotebookTab::getDesiredRect() const
{
return QRect(positionAnimationDesiredPoint, size());
}
void NotebookTab::hideTabXChanged(bool)
{
this->updateSize();
this->update();
}
void NotebookTab::moveAnimated(QPoint pos, bool animated)
{
this->positionAnimationDesiredPoint = pos;
QWidget *w = this->window();
if ((w != nullptr && !w->isVisible()) || !animated || !positionChangedAnimationRunning) {
this->move(pos);
this->positionChangedAnimationRunning = true;
return;
}
if (this->positionChangedAnimation.endValue() == pos) {
return;
}
this->positionChangedAnimation.stop();
this->positionChangedAnimation.setDuration(75);
this->positionChangedAnimation.setStartValue(this->pos());
this->positionChangedAnimation.setEndValue(pos);
this->positionChangedAnimation.start();
}
void NotebookTab::paintEvent(QPaintEvent *)
{
singletons::SettingManager &settingManager = singletons::SettingManager::getInstance();
QPainter painter(this);
float scale = this->getScale();
int height = (int)(scale * 24);
// int fullHeight = (int)(scale * 48);
// select the right tab colors
singletons::ThemeManager::TabColors colors;
singletons::ThemeManager::TabColors regular = this->themeManager.tabs.regular;
if (this->selected) {
colors = this->themeManager.tabs.selected;
} else if (this->highlightState == HighlightState::Highlighted) {
colors = this->themeManager.tabs.highlighted;
} else if (this->highlightState == HighlightState::NewMessage) {
colors = this->themeManager.tabs.newMessage;
} else {
colors = this->themeManager.tabs.regular;
}
bool windowFocused = this->window() == QApplication::activeWindow();
// || SettingsDialog::getHandle() == QApplication::activeWindow();
QBrush tabBackground = this->mouseOver ? colors.backgrounds.hover
: (windowFocused ? colors.backgrounds.regular
: colors.backgrounds.unfocused);
if (true) {
painter.fillRect(rect(), this->mouseOver ? regular.backgrounds.hover
: (windowFocused ? regular.backgrounds.regular
: regular.backgrounds.unfocused));
// fill the tab background
painter.fillRect(rect(), tabBackground);
// draw border
painter.setPen(QPen("#ccc"));
QPainterPath path(QPointF(0, height));
path.lineTo(0, 0);
path.lineTo(this->width() - 1, 0);
path.lineTo(this->width() - 1, this->height() - 1);
path.lineTo(0, this->height() - 1);
painter.drawPath(path);
} else {
// QPainterPath path(QPointF(0, height));
// path.lineTo(8 * scale, 0);
// path.lineTo(this->width() - 8 * scale, 0);
// path.lineTo(this->width(), height);
// painter.fillPath(path, this->mouseOver ? regular.backgrounds.hover
// : (windowFocused ?
// regular.backgrounds.regular
// :
// regular.backgrounds.unfocused));
// // fill the tab background
// painter.fillPath(path, tabBackground);
// painter.setPen(QColor("#FFF"));
// painter.setRenderHint(QPainter::Antialiasing);
// painter.drawPath(path);
// // painter.setBrush(QColor("#000"));
// QLinearGradient gradient(0, height, 0, fullHeight);
// gradient.setColorAt(0, tabBackground.color());
// gradient.setColorAt(1, "#fff");
// QBrush brush(gradient);
// painter.fillRect(0, height, this->width(), fullHeight - height,
// brush);
}
// set the pen color
painter.setPen(colors.text);
// set area for text
int rectW = (settingManager.hideTabX ? 0 : static_cast<int>(16) * scale);
QRect rect(0, 0, this->width() - rectW, height);
// draw text
if (true) { // legacy
// painter.drawText(rect, this->getTitle(), QTextOption(Qt::AlignCenter));
int offset = (int)(scale * 8);
QRect textRect(offset, 0, this->width() - offset - offset, height);
QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
option.setWrapMode(QTextOption::NoWrap);
painter.drawText(textRect, this->getTitle(), option);
} else {
// QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
// option.setWrapMode(QTextOption::NoWrap);
// int offset = (int)(scale * 16);
// QRect textRect(offset, 0, this->width() - offset - offset, height);
// painter.drawText(textRect, this->getTitle(), option);
}
// draw close x
if (!settingManager.hideTabX && (mouseOver || selected)) {
QRect xRect = this->getXRect();
if (mouseOverX) {
painter.fillRect(xRect, QColor(0, 0, 0, 64));
if (mouseDownX) {
painter.fillRect(xRect, QColor(0, 0, 0, 64));
}
}
int a = static_cast<int>(scale * 4);
painter.drawLine(xRect.topLeft() + QPoint(a, a), xRect.bottomRight() + QPoint(-a, -a));
painter.drawLine(xRect.topRight() + QPoint(-a, a), xRect.bottomLeft() + QPoint(a, -a));
}
} // namespace widgets
void NotebookTab::mousePressEvent(QMouseEvent *event)
{
this->mouseDown = true;
this->mouseDownX = this->getXRect().contains(event->pos());
this->update();
this->notebook->select(page);
switch (event->button()) {
case Qt::RightButton: {
this->menu.popup(event->globalPos());
} break;
}
}
void NotebookTab::mouseReleaseEvent(QMouseEvent *event)
{
this->mouseDown = false;
if (event->button() == Qt::MiddleButton) {
if (this->rect().contains(event->pos())) {
this->notebook->removePage(this->page);
}
} else {
if (!singletons::SettingManager::getInstance().hideTabX && this->mouseDownX &&
this->getXRect().contains(event->pos())) {
this->mouseDownX = false;
this->notebook->removePage(this->page);
} else {
this->update();
}
}
}
void NotebookTab::enterEvent(QEvent *)
{
this->mouseOver = true;
this->update();
}
void NotebookTab::leaveEvent(QEvent *)
{
this->mouseOverX = false;
this->mouseOver = false;
this->update();
}
void NotebookTab::dragEnterEvent(QDragEnterEvent *)
{
this->notebook->select(this->page);
}
void NotebookTab::mouseMoveEvent(QMouseEvent *event)
{
if (!singletons::SettingManager::getInstance().hideTabX) {
bool overX = this->getXRect().contains(event->pos());
if (overX != this->mouseOverX) {
// Over X state has been changed (we either left or entered it;
this->mouseOverX = overX;
this->update();
}
}
QPoint relPoint = this->mapToParent(event->pos());
if (this->mouseDown && !this->getDesiredRect().contains(relPoint)) {
int index;
SplitContainer *clickedPage = notebook->tabAt(relPoint, index, this->width());
if (clickedPage != nullptr && clickedPage != this->page) {
this->notebook->rearrangePage(this->page, index);
}
}
}
} // namespace widgets
} // namespace chatterino