added namespaces

This commit is contained in:
fourtf
2017-01-18 21:30:23 +01:00
parent 82338baaa3
commit 2e8dc63a95
82 changed files with 681 additions and 459 deletions
+83
View File
@@ -0,0 +1,83 @@
#include "widgets/chatwidget.h"
#include "channels.h"
#include "colorscheme.h"
#include "widgets/textinputdialog.h"
#include <QFont>
#include <QFontDatabase>
#include <QPainter>
#include <QVBoxLayout>
namespace chatterino {
namespace widgets {
ChatWidget::ChatWidget(QWidget *parent)
: QWidget(parent)
, channel(NULL)
, channelName(QString())
, vbox(this)
, header(this)
, view(this)
, input()
{
this->vbox.setSpacing(0);
this->vbox.setMargin(1);
this->vbox.addWidget(&header);
this->vbox.addWidget(&view);
this->vbox.addWidget(&input);
}
ChatWidget::~ChatWidget()
{
}
void
ChatWidget::setChannelName(const QString &name)
{
QString channel = name.trimmed();
if (QString::compare(channel, this->channelName, Qt::CaseInsensitive) ==
0) {
this->channelName = channel;
this->header.updateChannelText();
return;
}
this->channelName = channel;
this->header.updateChannelText();
this->view.layoutMessages();
if (!this->channelName.isEmpty()) {
Channels::removeChannel(this->channelName);
}
if (channel.isEmpty()) {
this->channel = NULL;
} else {
this->channel = Channels::addChannel(channel);
}
}
void
ChatWidget::showChangeChannelPopup()
{
TextInputDialog dialog(this);
dialog.setText(this->channelName);
if (dialog.exec() == QDialog::Accepted) {
setChannelName(dialog.getText());
}
}
void
ChatWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.fillRect(this->rect(), ColorScheme::instance().ChatBackground);
}
}
}
+62
View File
@@ -0,0 +1,62 @@
#ifndef CHATWIDGET_H
#define CHATWIDGET_H
#include "channel.h"
#include "widgets/chatwidgetheader.h"
#include "widgets/chatwidgetinput.h"
#include "widgets/chatwidgetview.h"
#include <QFont>
#include <QVBoxLayout>
#include <QWidget>
namespace chatterino {
namespace widgets {
class ChatWidget : public QWidget
{
Q_OBJECT
public:
ChatWidget(QWidget *parent = 0);
~ChatWidget();
ChatWidgetView &
getView()
{
return view;
}
Channel *
getChannel() const
{
return channel;
}
const QString &
getChannelName() const
{
return channelName;
}
void setChannelName(const QString &name);
void showChangeChannelPopup();
protected:
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
private:
Channel *channel;
QString channelName;
QFont font;
QVBoxLayout vbox;
ChatWidgetHeader header;
ChatWidgetView view;
ChatWidgetInput input;
};
}
}
#endif // CHATWIDGET_H
+216
View File
@@ -0,0 +1,216 @@
#include "widgets/chatwidgetheader.h"
#include "colorscheme.h"
#include "widgets/chatwidget.h"
#include "widgets/notebookpage.h"
#include <QByteArray>
#include <QDrag>
#include <QMimeData>
#include <QPainter>
namespace chatterino {
namespace widgets {
ChatWidgetHeader::ChatWidgetHeader(ChatWidget *parent)
: QWidget()
, chatWidget(parent)
, dragStart()
, dragging(false)
, leftLabel()
, middleLabel()
, rightLabel()
, leftMenu(this)
, rightMenu(this)
{
setFixedHeight(32);
updateColors();
updateChannelText();
setLayout(&this->hbox);
this->hbox.setMargin(0);
this->hbox.addWidget(&this->leftLabel);
this->hbox.addWidget(&this->middleLabel, 1);
this->hbox.addWidget(&this->rightLabel);
// left
this->leftLabel.getLabel().setTextFormat(Qt::RichText);
this->leftLabel.getLabel().setText(
"<img src=':/images/tool_moreCollapser_off16.png' />");
QObject::connect(&this->leftLabel, &ChatWidgetHeaderButton::clicked, this,
&ChatWidgetHeader::leftButtonClicked);
this->leftMenu.addAction("Add new split", this, SLOT(menuAddSplit()),
QKeySequence(tr("Ctrl+T")));
this->leftMenu.addAction("Close split", this, SLOT(menuCloseSplit()),
QKeySequence(tr("Ctrl+W")));
this->leftMenu.addAction("Move split", this, SLOT(menuMoveSplit()));
this->leftMenu.addSeparator();
this->leftMenu.addAction("Change channel", this, SLOT(menuChangeChannel()),
QKeySequence(tr("Ctrl+R")));
this->leftMenu.addAction("Clear chat", this, SLOT(menuClearChat()));
this->leftMenu.addAction("Open channel", this, SLOT(menuOpenChannel()));
this->leftMenu.addAction("Open pop-out player", this,
SLOT(menuPopupPlayer()));
this->leftMenu.addSeparator();
this->leftMenu.addAction("Reload channel emotes", this,
SLOT(menuReloadChannelEmotes()));
this->leftMenu.addAction("Manual reconnect", this,
SLOT(menuManualReconnect()));
this->leftMenu.addSeparator();
this->leftMenu.addAction("Show changelog", this, SLOT(menuShowChangelog()));
// middle
this->middleLabel.setAlignment(Qt::AlignCenter);
/*QObject::connect(&this->middleLabel,
* SIGNAL(mouseDoubleClickEvent(QMouseEvent)), this,
* SLOT(mouseDoubleClickEvent));
* mouseDoubleClickEvent is not a signal, its an event handler
*/
connect(&this->middleLabel, &SignalLabel::mouseDoubleClick, this,
&ChatWidgetHeader::mouseDoubleClickEvent);
// right
this->rightLabel.setMinimumWidth(height());
this->rightLabel.getLabel().setTextFormat(Qt::RichText);
this->rightLabel.getLabel().setText("ayy");
}
void
ChatWidgetHeader::updateColors()
{
QPalette palette;
palette.setColor(QPalette::Foreground, ColorScheme::instance().Text);
this->leftLabel.setPalette(palette);
this->middleLabel.setPalette(palette);
this->rightLabel.setPalette(palette);
}
void
ChatWidgetHeader::updateChannelText()
{
const QString &c = this->chatWidget->getChannelName();
this->middleLabel.setText(c.isEmpty() ? "<no channel>" : c);
}
void
ChatWidgetHeader::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.fillRect(rect(), ColorScheme::instance().ChatHeaderBackground);
painter.setPen(ColorScheme::instance().ChatHeaderBorder);
painter.drawRect(0, 0, width() - 1, height() - 1);
}
void
ChatWidgetHeader::mousePressEvent(QMouseEvent *event)
{
this->dragging = true;
this->dragStart = event->pos();
}
void
ChatWidgetHeader::mouseMoveEvent(QMouseEvent *event)
{
if (this->dragging) {
if (std::abs(this->dragStart.x() - event->pos().x()) > 12 ||
std::abs(this->dragStart.y() - event->pos().y()) > 12) {
auto chatWidget = this->chatWidget;
auto page = static_cast<NotebookPage *>(chatWidget->parentWidget());
if (page != NULL) {
NotebookPage::isDraggingSplit = true;
NotebookPage::draggingSplit = chatWidget;
auto originalLocation = page->removeFromLayout(chatWidget);
// page->repaint();
QDrag *drag = new QDrag(chatWidget);
QMimeData *mimeData = new QMimeData;
mimeData->setData("chatterino/split", "xD");
drag->setMimeData(mimeData);
Qt::DropAction dropAction = drag->exec(Qt::MoveAction);
if (dropAction == Qt::IgnoreAction) {
page->addToLayout(chatWidget, originalLocation);
}
NotebookPage::isDraggingSplit = false;
}
}
}
}
void
ChatWidgetHeader::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
this->chatWidget->showChangeChannelPopup();
}
}
void
ChatWidgetHeader::leftButtonClicked()
{
this->leftMenu.move(
this->leftLabel.mapToGlobal(QPoint(0, this->leftLabel.height())));
this->leftMenu.show();
}
void
ChatWidgetHeader::rightButtonClicked()
{
}
void
ChatWidgetHeader::menuAddSplit()
{
}
void
ChatWidgetHeader::menuCloseSplit()
{
}
void
ChatWidgetHeader::menuMoveSplit()
{
}
void
ChatWidgetHeader::menuChangeChannel()
{
this->chatWidget->showChangeChannelPopup();
}
void
ChatWidgetHeader::menuClearChat()
{
}
void
ChatWidgetHeader::menuOpenChannel()
{
}
void
ChatWidgetHeader::menuPopupPlayer()
{
}
void
ChatWidgetHeader::menuReloadChannelEmotes()
{
}
void
ChatWidgetHeader::menuManualReconnect()
{
}
void
ChatWidgetHeader::menuShowChangelog()
{
}
}
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef CHATWIDGETHEADER_H
#define CHATWIDGETHEADER_H
#include "signallabel.h"
#include "widgets/chatwidgetheaderbutton.h"
#include <QAction>
#include <QHBoxLayout>
#include <QLabel>
#include <QMenu>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QPoint>
#include <QWidget>
namespace chatterino {
namespace widgets {
class ChatWidget;
class ChatWidgetHeader : public QWidget
{
Q_OBJECT
public:
explicit ChatWidgetHeader(ChatWidget *parent);
ChatWidget *
getChatWidget()
{
return chatWidget;
}
void updateColors();
void updateChannelText();
protected:
void paintEvent(QPaintEvent *);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
private:
ChatWidget *chatWidget;
QPoint dragStart;
bool dragging;
QHBoxLayout hbox;
ChatWidgetHeaderButton leftLabel;
SignalLabel middleLabel;
ChatWidgetHeaderButton rightLabel;
QMenu leftMenu;
QMenu rightMenu;
void leftButtonClicked();
void rightButtonClicked();
private slots:
void menuAddSplit();
void menuCloseSplit();
void menuMoveSplit();
void menuChangeChannel();
void menuClearChat();
void menuOpenChannel();
void menuPopupPlayer();
void menuReloadChannelEmotes();
void menuManualReconnect();
void menuShowChangelog();
};
}
}
#endif // CHATWIDGETHEADER_H
+104
View File
@@ -0,0 +1,104 @@
#include "widgets/chatwidgetheaderbutton.h"
#include "colorscheme.h"
#include <QBrush>
#include <QPainter>
namespace chatterino {
namespace widgets {
ChatWidgetHeaderButton::ChatWidgetHeaderButton()
: QWidget()
, hbox()
, label()
, mouseOver(false)
, mouseDown(false)
{
setLayout(&hbox);
hbox.setMargin(0);
hbox.addSpacing(6);
hbox.addWidget(&this->label);
hbox.addSpacing(6);
QObject::connect(&this->label, &ChatWidgetHeaderButtonLabel::mouseUp, this,
&ChatWidgetHeaderButton::labelMouseUp);
QObject::connect(&this->label, &ChatWidgetHeaderButtonLabel::mouseDown,
this, &ChatWidgetHeaderButton::labelMouseDown);
}
void
ChatWidgetHeaderButton::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QBrush brush(ColorScheme::instance().IsLightTheme
? QColor(0, 0, 0, 32)
: QColor(255, 255, 255, 32));
if (this->mouseDown) {
painter.fillRect(rect(), brush);
}
if (this->mouseOver) {
painter.fillRect(rect(), brush);
}
}
void
ChatWidgetHeaderButton::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
this->mouseDown = true;
repaint();
}
}
void
ChatWidgetHeaderButton::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
this->mouseDown = false;
repaint();
emit clicked();
}
}
void
ChatWidgetHeaderButton::enterEvent(QEvent *)
{
this->mouseOver = true;
repaint();
}
void
ChatWidgetHeaderButton::leaveEvent(QEvent *)
{
this->mouseOver = false;
repaint();
}
void
ChatWidgetHeaderButton::labelMouseUp()
{
this->mouseDown = false;
repaint();
emit clicked();
}
void
ChatWidgetHeaderButton::labelMouseDown()
{
this->mouseDown = true;
repaint();
}
}
}
+52
View File
@@ -0,0 +1,52 @@
#ifndef CHATWIDGETHEADERBUTTON_H
#define CHATWIDGETHEADERBUTTON_H
#include "widgets/chatwidgetheaderbuttonlabel.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPaintEvent>
#include <QWidget>
namespace chatterino {
namespace widgets {
class ChatWidgetHeaderButton : public QWidget
{
Q_OBJECT
public:
ChatWidgetHeaderButton();
ChatWidgetHeaderButtonLabel &
getLabel()
{
return label;
}
signals:
void clicked();
protected:
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
void enterEvent(QEvent *) Q_DECL_OVERRIDE;
void leaveEvent(QEvent *) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
private:
QHBoxLayout hbox;
ChatWidgetHeaderButtonLabel label;
bool mouseOver;
bool mouseDown;
void labelMouseUp();
void labelMouseDown();
};
}
}
#endif // CHATWIDGETHEADERBUTTON_H
+27
View File
@@ -0,0 +1,27 @@
#include "widgets/chatwidgetheaderbuttonlabel.h"
namespace chatterino {
namespace widgets {
ChatWidgetHeaderButtonLabel::ChatWidgetHeaderButtonLabel()
{
setAlignment(Qt::AlignCenter);
}
void
ChatWidgetHeaderButtonLabel::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
emit mouseDown();
}
}
void
ChatWidgetHeaderButtonLabel::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
emit mouseUp();
}
}
}
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef CHATWIDGETHEADERBUTTONLABEL_H
#define CHATWIDGETHEADERBUTTONLABEL_H
#include <QLabel>
#include <QMouseEvent>
namespace chatterino {
namespace widgets {
class ChatWidgetHeaderButtonLabel : public QLabel
{
Q_OBJECT
public:
ChatWidgetHeaderButtonLabel();
signals:
void mouseDown();
void mouseUp();
protected:
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
};
}
}
#endif // CHATWIDGETHEADERBUTTONLABEL_H
+24
View File
@@ -0,0 +1,24 @@
#include "widgets/chatwidgetinput.h"
#include "colorscheme.h"
#include <QPainter>
namespace chatterino {
namespace widgets {
ChatWidgetInput::ChatWidgetInput()
{
setFixedHeight(38);
}
void
ChatWidgetInput::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.fillRect(rect(), ColorScheme::instance().ChatInputBackground);
painter.setPen(ColorScheme::instance().ChatInputBorder);
painter.drawRect(0, 0, width() - 1, height() - 1);
}
}
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef CHATWIDGETINPUT_H
#define CHATWIDGETINPUT_H
#include <QPaintEvent>
#include <QWidget>
namespace chatterino {
namespace widgets {
class ChatWidgetInput : public QWidget
{
Q_OBJECT
public:
ChatWidgetInput();
protected:
void paintEvent(QPaintEvent *);
};
}
}
#endif // CHATWIDGETINPUT_H
+153
View File
@@ -0,0 +1,153 @@
#include "widgets/chatwidgetview.h"
#include "channels.h"
#include "colorscheme.h"
#include "messages/message.h"
#include "messages/word.h"
#include "messages/wordpart.h"
#include "widgets/chatwidget.h"
#include <math.h>
#include <QPainter>
#include <QScroller>
#include <functional>
namespace chatterino {
namespace widgets {
ChatWidgetView::ChatWidgetView(ChatWidget *parent)
: QWidget()
, chatWidget(parent)
, scrollbar(this)
{
auto scroll = QScroller::scroller(this);
scroll->scrollTo(QPointF(0, 100));
}
bool
ChatWidgetView::layoutMessages()
{
auto c = this->chatWidget->getChannel();
if (c == NULL)
return false;
auto messages = c->getMessagesClone();
bool redraw = false;
for (std::shared_ptr<Message> &message : messages) {
redraw |= message.get()->layout(this->width(), true);
}
return redraw;
}
void
ChatWidgetView::resizeEvent(QResizeEvent *)
{
this->scrollbar.resize(this->scrollbar.width(), height());
this->scrollbar.move(width() - this->scrollbar.width(), 0);
layoutMessages();
}
void
ChatWidgetView::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
auto c = this->chatWidget->getChannel();
QColor color;
ColorScheme &scheme = ColorScheme::instance();
// code for tesing colors
/*
static ConcurrentMap<qreal, QImage *> imgCache;
std::function<QImage *(qreal)> getImg = [&scheme](qreal light) {
return imgCache.getOrAdd(light, [&scheme, &light] {
QImage *img = new QImage(150, 50, QImage::Format_RGB32);
QColor color;
for (int j = 0; j < 50; j++) {
for (qreal i = 0; i < 150; i++) {
color = QColor::fromHslF(i / 150.0, light, j / 50.0);
scheme.normalizeColor(color);
img->setPixelColor(i, j, color);
}
}
return img;
});
};
for (qreal k = 0; k < 4.8; k++) {
auto img = getImg(k / 5);
painter.drawImage(QRect(k * 150, 0, 150, 150), *img);
}
painter.fillRect(QRect(0, 9, 500, 2), QColor(0, 0, 0));*/
if (c == NULL)
return;
auto messages = c->getMessagesClone();
int start = this->scrollbar.getValue();
if (start >= messages.length()) {
return;
}
int y = -(messages[start].get()->getHeight() *
(fmod(this->scrollbar.getValue(), 1)));
for (int i = start; i < messages.size(); ++i) {
Message *message = messages[i].get();
for (WordPart const &wordPart : message->getWordParts()) {
painter.setPen(QColor(255, 0, 0));
painter.drawRect(wordPart.getX(), wordPart.getY() + y,
wordPart.getWidth(), wordPart.getHeight());
// image
if (wordPart.getWord().isImage()) {
LazyLoadedImage &lli = wordPart.getWord().getImage();
const QPixmap *image = lli.getPixmap();
if (image != NULL) {
painter.drawPixmap(
QRect(wordPart.getX(), wordPart.getY() + y,
wordPart.getWidth(), wordPart.getHeight()),
*image);
}
}
// text
else {
QColor color = wordPart.getWord().getColor();
painter.setPen(color);
painter.setFont(wordPart.getWord().getFont());
painter.drawText(
QRectF(wordPart.getX(), wordPart.getY() + y, 10000, 10000),
wordPart.getText(),
QTextOption(Qt::AlignLeft | Qt::AlignTop));
}
}
y += message->getHeight();
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef CHATVIEW_H
#define CHATVIEW_H
#include "channel.h"
#include "widgets/scrollbar.h"
#include <QPaintEvent>
#include <QWidget>
namespace chatterino {
namespace widgets {
class ChatWidget;
class ChatWidgetView : public QWidget
{
Q_OBJECT
public:
explicit ChatWidgetView(ChatWidget *parent);
bool layoutMessages();
protected:
void resizeEvent(QResizeEvent *);
void paintEvent(QPaintEvent *);
private:
ChatWidget *chatWidget;
ScrollBar scrollbar;
};
}
}
#endif // CHATVIEW_H
+76
View File
@@ -0,0 +1,76 @@
#include "widgets/mainwindow.h"
#include "colorscheme.h"
#include "widgets/chatwidget.h"
#include "widgets/notebook.h"
#include <QPalette>
namespace chatterino {
namespace widgets {
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, notebook(this)
{
setCentralWidget(&this->notebook);
this->notebook.addPage();
this->notebook.addPage();
this->notebook.addPage();
QPalette palette;
palette.setColor(QPalette::Background,
ColorScheme::instance().TabPanelBackground);
setPalette(palette);
resize(1280, 800);
}
MainWindow::~MainWindow()
{
}
void
MainWindow::layoutVisibleChatWidgets(Channel *channel)
{
auto *page = notebook.getSelectedPage();
if (page == NULL) {
return;
}
const std::vector<ChatWidget *> &widgets = page->getChatWidgets();
for (auto it = widgets.begin(); it != widgets.end(); ++it) {
ChatWidget *widget = *it;
if (channel == NULL || channel == widget->getChannel()) {
if (widget->getView().layoutMessages()) {
widget->repaint();
}
}
}
}
void
MainWindow::repaintVisibleChatWidgets(Channel *channel)
{
auto *page = notebook.getSelectedPage();
if (page == NULL) {
return;
}
const std::vector<ChatWidget *> &widgets = page->getChatWidgets();
for (auto it = widgets.begin(); it != widgets.end(); ++it) {
ChatWidget *widget = *it;
if (channel == NULL || channel == widget->getChannel()) {
widget->getView().layoutMessages();
widget->repaint();
}
}
}
}
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "widgets/notebook.h"
#include <QMainWindow>
namespace chatterino {
namespace widgets {
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Notebook notebook;
void layoutVisibleChatWidgets(Channel *channel = NULL);
void repaintVisibleChatWidgets(Channel *channel = NULL);
};
}
}
#endif // MAINWINDOW_H
+115
View File
@@ -0,0 +1,115 @@
#include "widgets/notebook.h"
#include "colorscheme.h"
#include "widgets/notebookbutton.h"
#include "widgets/notebookpage.h"
#include "widgets/notebooktab.h"
#include "widgets/settingsdialog.h"
#include <QFormLayout>
#include <QLayout>
#include <QList>
#include <QWidget>
namespace chatterino {
namespace widgets {
Notebook::Notebook(QWidget *parent)
: QWidget(parent)
, addButton(this)
, settingsButton(this)
, userButton(this)
{
connect(&this->settingsButton, SIGNAL(clicked()), this,
SLOT(settingsButtonClicked()));
this->settingsButton.resize(24, 24);
this->settingsButton.icon = NotebookButton::IconSettings;
this->userButton.resize(24, 24);
this->userButton.move(24, 0);
this->userButton.icon = NotebookButton::IconUser;
this->addButton.resize(24, 24);
}
void
Notebook::settingsButtonClicked()
{
SettingsDialog *a = new SettingsDialog();
a->show();
}
NotebookPage *
Notebook::addPage()
{
auto tab = new NotebookTab(this);
auto page = new NotebookPage(this, tab);
if (this->pages.count() == 0) {
select(page);
}
this->pages.append(page);
return page;
}
void
Notebook::select(NotebookPage *page)
{
if (page == this->selectedPage)
return;
if (page != nullptr) {
page->setHidden(false);
page->tab->setSelected(true);
}
if (this->selectedPage != nullptr) {
this->selectedPage->setHidden(true);
this->selectedPage->tab->setSelected(false);
}
this->selectedPage = page;
performLayout();
}
void
Notebook::performLayout()
{
int x = 48, y = 0;
int tabHeight = 16;
bool first = true;
for (auto &i : this->pages) {
tabHeight = i->tab->height();
if (!first &&
(i == this->pages.last() ? tabHeight : 0) + x + i->tab->width() >
width()) {
y += i->tab->height();
i->tab->move(0, y);
x = i->tab->width();
} else {
i->tab->move(x, y);
x += i->tab->width();
}
first = false;
}
this->addButton.move(x, y);
if (this->selectedPage != nullptr) {
this->selectedPage->move(0, y + tabHeight);
this->selectedPage->resize(width(), height() - y - tabHeight);
}
}
void
Notebook::resizeEvent(QResizeEvent *)
{
performLayout();
}
}
}
+55
View File
@@ -0,0 +1,55 @@
#ifndef NOTEBOOK_H
#define NOTEBOOK_H
#include "widgets/notebookbutton.h"
#include "widgets/notebookpage.h"
#include "widgets/notebooktab.h"
#include <QList>
#include <QWidget>
namespace chatterino {
namespace widgets {
class Notebook : public QWidget
{
Q_OBJECT
public:
Notebook(QWidget *parent);
NotebookPage *addPage();
enum HighlightType { none, highlighted, newMessage };
void select(NotebookPage *page);
NotebookPage *
getSelectedPage()
{
return selectedPage;
}
void performLayout();
protected:
void resizeEvent(QResizeEvent *);
void settingsButtonMouseReleased(QMouseEvent *event);
public slots:
void settingsButtonClicked();
private:
QList<NotebookPage *> pages;
NotebookButton addButton;
NotebookButton settingsButton;
NotebookButton userButton;
NotebookPage *selectedPage = nullptr;
};
}
}
#endif // NOTEBOOK_H
+128
View File
@@ -0,0 +1,128 @@
#include "widgets/notebookbutton.h"
#include "colorscheme.h"
#include <QMouseEvent>
#include <QPainter>
#include <QPainterPath>
namespace chatterino {
namespace widgets {
NotebookButton::NotebookButton(QWidget *parent)
: QWidget(parent)
{
}
void
NotebookButton::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QColor background;
QColor foreground;
auto colorScheme = ColorScheme::instance();
if (mouseDown) {
background = colorScheme.TabSelectedBackground;
foreground = colorScheme.TabSelectedText;
} else if (mouseOver) {
background = colorScheme.TabHoverBackground;
foreground = colorScheme.TabSelectedBackground;
} else {
background = colorScheme.TabPanelBackground;
foreground = colorScheme.TabSelectedBackground;
}
painter.setPen(Qt::NoPen);
painter.fillRect(this->rect(), background);
float h = this->height(), w = this->width();
if (icon == IconPlus) {
painter.fillRect(QRectF((h / 12) * 2 + 1, (h / 12) * 5 + 1,
w - ((h / 12) * 5), (h / 12) * 1),
foreground);
painter.fillRect(QRectF((h / 12) * 5 + 1, (h / 12) * 2 + 1,
(h / 12) * 1, w - ((h / 12) * 5)),
foreground);
} else if (icon == IconUser) {
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
auto a = w / 8;
QPainterPath path;
path.arcMoveTo(a, 4 * a, 6 * a, 6 * a, 0);
path.arcTo(a, 4 * a, 6 * a, 6 * a, 0, 180);
painter.fillPath(path, foreground);
painter.setBrush(background);
painter.drawEllipse(2 * a, 1 * a, 4 * a, 4 * a);
painter.setBrush(foreground);
painter.drawEllipse(2.5 * a, 1.5 * a, 3 * a + 1, 3 * a);
} else // IconSettings
{
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
auto a = w / 8;
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.fillPath(path, foreground);
painter.setBrush(background);
painter.drawEllipse(3 * a, 3 * a, 2 * a, 2 * a);
}
}
void
NotebookButton::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
mouseDown = true;
this->repaint();
}
}
void
NotebookButton::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
mouseDown = false;
this->repaint();
emit clicked();
}
}
void
NotebookButton::enterEvent(QEvent *)
{
mouseOver = true;
this->repaint();
}
void
NotebookButton::leaveEvent(QEvent *)
{
mouseOver = false;
this->repaint();
}
}
}
+37
View File
@@ -0,0 +1,37 @@
#ifndef NOTEBOOKBUTTON_H
#define NOTEBOOKBUTTON_H
#include <QWidget>
namespace chatterino {
namespace widgets {
class NotebookButton : public QWidget
{
Q_OBJECT
public:
static const int IconPlus = 0;
static const int IconUser = 1;
static const int IconSettings = 2;
int icon = 0;
NotebookButton(QWidget *parent);
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void enterEvent(QEvent *) Q_DECL_OVERRIDE;
void leaveEvent(QEvent *) Q_DECL_OVERRIDE;
signals:
void clicked();
private:
bool mouseOver = false;
bool mouseDown = false;
};
}
}
#endif // NOTEBOOKBUTTON_H
+240
View File
@@ -0,0 +1,240 @@
#include "widgets/notebookpage.h"
#include "colorscheme.h"
#include "widgets/chatwidget.h"
#include "widgets/notebooktab.h"
#include <QHBoxLayout>
#include <QMimeData>
#include <QPainter>
#include <QVBoxLayout>
#include <QWidget>
namespace chatterino {
namespace widgets {
bool NotebookPage::isDraggingSplit = false;
ChatWidget *NotebookPage::draggingSplit = NULL;
std::pair<int, int> NotebookPage::dropPosition = std::pair<int, int>(-1, -1);
NotebookPage::NotebookPage(QWidget *parent, NotebookTab *tab)
: QWidget(parent)
, parentbox(this)
, chatWidgets()
, preview(this)
{
this->tab = tab;
tab->page = this;
setHidden(true);
setAcceptDrops(true);
this->parentbox.addSpacing(2);
this->parentbox.addLayout(&this->hbox);
this->parentbox.setMargin(0);
this->hbox.setSpacing(1);
this->hbox.setMargin(0);
}
std::pair<int, int>
NotebookPage::removeFromLayout(ChatWidget *widget)
{
for (auto it = this->chatWidgets.begin(); it != this->chatWidgets.end();
++it) {
if (*it == widget) {
this->chatWidgets.erase(it);
break;
}
}
for (int i = 0; i < this->hbox.count(); ++i) {
auto vbox = static_cast<QVBoxLayout *>(this->hbox.itemAt(i));
for (int j = 0; j < vbox->count(); ++j) {
if (vbox->itemAt(j)->widget() != widget)
continue;
widget->setParent(NULL);
bool isLastItem = vbox->count() == 0;
if (isLastItem) {
this->hbox.removeItem(vbox);
delete vbox;
}
return std::pair<int, int>(i, isLastItem ? -1 : j);
}
}
return std::pair<int, int>(-1, -1);
}
void
NotebookPage::addToLayout(
ChatWidget *widget,
std::pair<int, int> position = std::pair<int, int>(-1, -1))
{
this->chatWidgets.push_back(widget);
// add vbox at the end
if (position.first < 0 || position.first >= this->hbox.count()) {
auto vbox = new QVBoxLayout();
vbox->addWidget(widget);
this->hbox.addLayout(vbox);
return;
}
// insert vbox
if (position.second == -1) {
auto vbox = new QVBoxLayout();
vbox->addWidget(widget);
this->hbox.insertLayout(position.first, vbox);
return;
}
// add to existing vbox
auto vbox = static_cast<QVBoxLayout *>(this->hbox.itemAt(position.first));
vbox->insertWidget(std::max(0, std::min(vbox->count(), position.second)),
widget);
}
void
NotebookPage::enterEvent(QEvent *)
{
if (this->hbox.count() == 0) {
setCursor(QCursor(Qt::PointingHandCursor));
} else {
setCursor(QCursor(Qt::ArrowCursor));
}
}
void
NotebookPage::leaveEvent(QEvent *)
{
}
void
NotebookPage::mouseReleaseEvent(QMouseEvent *event)
{
if (this->hbox.count() == 0 && event->button() == Qt::LeftButton) {
addToLayout(new ChatWidget(), std::pair<int, int>(-1, -1));
setCursor(QCursor(Qt::ArrowCursor));
}
}
void
NotebookPage::dragEnterEvent(QDragEnterEvent *event)
{
if (!event->mimeData()->hasFormat("chatterino/split"))
return;
if (isDraggingSplit) {
this->dropRegions.clear();
if (this->hbox.count() == 0) {
this->dropRegions.push_back(
DropRegion(rect(), std::pair<int, int>(-1, -1)));
} else {
for (int i = 0; i < this->hbox.count() + 1; ++i) {
this->dropRegions.push_back(DropRegion(
QRect(((i * 4 - 1) * width() / this->hbox.count()) / 4, 0,
width() / this->hbox.count() / 2, height()),
std::pair<int, int>(i, -1)));
}
for (int i = 0; i < this->hbox.count(); ++i) {
auto vbox = static_cast<QVBoxLayout *>(this->hbox.itemAt(i));
for (int j = 0; j < vbox->count() + 1; ++j) {
this->dropRegions.push_back(DropRegion(
QRect(i * width() / this->hbox.count(),
((j * 2 - 1) * height() / vbox->count()) / 2,
width() / this->hbox.count(),
height() / vbox->count()),
std::pair<int, int>(i, j)));
}
}
}
setPreviewRect(event->pos());
event->acceptProposedAction();
}
}
void
NotebookPage::dragMoveEvent(QDragMoveEvent *event)
{
setPreviewRect(event->pos());
}
void
NotebookPage::setPreviewRect(QPoint mousePos)
{
for (DropRegion region : this->dropRegions) {
if (region.rect.contains(mousePos)) {
this->preview.setBounds(region.rect);
// this->preview.move(region.rect.x(), region.rect.y());
// this->preview.resize(region.rect.width(),
// region.rect.height());
this->preview.show();
this->preview.raise();
dropPosition = region.position;
return;
} else {
this->preview.hide();
}
}
}
void
NotebookPage::dragLeaveEvent(QDragLeaveEvent *event)
{
this->preview.hide();
}
void
NotebookPage::dropEvent(QDropEvent *event)
{
if (isDraggingSplit) {
event->acceptProposedAction();
NotebookPage::draggingSplit->setParent(this);
addToLayout(NotebookPage::draggingSplit, dropPosition);
}
this->preview.hide();
}
void
NotebookPage::paintEvent(QPaintEvent *)
{
QPainter painter(this);
if (this->hbox.count() == 0) {
painter.fillRect(rect(), ColorScheme::instance().ChatBackground);
painter.fillRect(0, 0, width(), 2,
ColorScheme::instance().TabSelectedBackground);
painter.setPen(ColorScheme::instance().Text);
painter.drawText(rect(), "Add Chat", QTextOption(Qt::AlignCenter));
} else {
painter.fillRect(rect(), ColorScheme::instance().TabSelectedBackground);
painter.fillRect(0, 0, width(), 2,
ColorScheme::instance().TabSelectedBackground);
}
}
}
}
+77
View File
@@ -0,0 +1,77 @@
#ifndef NOTEBOOKPAGE_H
#define NOTEBOOKPAGE_H
#include "widgets/chatwidget.h"
#include "widgets/notebookpage.h"
#include "widgets/notebookpagedroppreview.h"
#include "widgets/notebooktab.h"
#include <QDragEnterEvent>
#include <QHBoxLayout>
#include <QRect>
#include <QVBoxLayout>
#include <QVector>
#include <QWidget>
namespace chatterino {
namespace widgets {
class NotebookPage : public QWidget
{
Q_OBJECT
public:
NotebookPage(QWidget *parent, NotebookTab *tab);
NotebookTab *tab;
std::pair<int, int> removeFromLayout(ChatWidget *widget);
void addToLayout(ChatWidget *widget, std::pair<int, int> position);
const std::vector<ChatWidget *> &
getChatWidgets() const
{
return chatWidgets;
}
static bool isDraggingSplit;
static ChatWidget *draggingSplit;
static std::pair<int, int> dropPosition;
protected:
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
void enterEvent(QEvent *) override;
void leaveEvent(QEvent *) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE;
void dragMoveEvent(QDragMoveEvent *event) Q_DECL_OVERRIDE;
void dragLeaveEvent(QDragLeaveEvent *event) Q_DECL_OVERRIDE;
void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
struct DropRegion {
QRect rect;
std::pair<int, int> position;
DropRegion(QRect rect, std::pair<int, int> position)
{
this->rect = rect;
this->position = position;
}
};
QVBoxLayout parentbox;
QHBoxLayout hbox;
std::vector<ChatWidget *> chatWidgets;
std::vector<DropRegion> dropRegions;
NotebookPageDropPreview preview;
private:
void setPreviewRect(QPoint mousePos);
};
}
}
#endif // NOTEBOOKPAGE_H
+42
View File
@@ -0,0 +1,42 @@
#include "widgets/notebookpagedroppreview.h"
#include "colorscheme.h"
#include <QPainter>
namespace chatterino {
namespace widgets {
NotebookPageDropPreview::NotebookPageDropPreview(QWidget *parent)
: QWidget(parent)
, positionAnimation(this, "geometry")
, desiredGeometry()
{
setHidden(true);
}
void
NotebookPageDropPreview::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.fillRect(8, 8, width() - 17, height() - 17,
ColorScheme::instance().DropPreviewBackground);
}
void
NotebookPageDropPreview::setBounds(const QRect &rect)
{
if (rect == this->desiredGeometry) {
return;
}
this->positionAnimation.stop();
this->positionAnimation.setDuration(50);
this->positionAnimation.setStartValue(geometry());
this->positionAnimation.setEndValue(rect);
this->positionAnimation.start();
this->desiredGeometry = rect;
}
}
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef NOTEBOOKPAGEDROPPREVIEW_H
#define NOTEBOOKPAGEDROPPREVIEW_H
#include <QPropertyAnimation>
#include <QWidget>
namespace chatterino {
namespace widgets {
class NotebookPageDropPreview : public QWidget
{
public:
NotebookPageDropPreview(QWidget *parent);
void setBounds(const QRect &rect);
protected:
void paintEvent(QPaintEvent *);
QPropertyAnimation positionAnimation;
QRect desiredGeometry;
};
}
}
#endif // NOTEBOOKPAGEDROPPREVIEW_H
+100
View File
@@ -0,0 +1,100 @@
#include "widgets/notebooktab.h"
#include "colorscheme.h"
#include "widgets/notebook.h"
#include <QPainter>
namespace chatterino {
namespace widgets {
NotebookTab::NotebookTab(Notebook *notebook)
: QWidget(notebook)
, notebook(notebook)
, text("<no title>")
, selected(false)
, mouseOver(false)
, mouseDown(false)
, highlightStyle(HighlightNone)
{
calcSize();
setAcceptDrops(true);
}
void
NotebookTab::calcSize()
{
resize(fontMetrics().width(this->text) + 8, 24);
}
void
NotebookTab::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QColor fg = QColor(0, 0, 0);
auto colorScheme = ColorScheme::instance();
if (this->selected) {
painter.fillRect(rect(), colorScheme.TabSelectedBackground);
fg = colorScheme.TabSelectedText;
} else if (this->mouseOver) {
painter.fillRect(rect(), colorScheme.TabHoverBackground);
fg = colorScheme.TabHoverText;
} else if (this->highlightStyle == HighlightHighlighted) {
painter.fillRect(rect(), colorScheme.TabHighlightedBackground);
fg = colorScheme.TabHighlightedText;
} else if (this->highlightStyle == HighlightNewMessage) {
painter.fillRect(rect(), colorScheme.TabNewMessageBackground);
fg = colorScheme.TabHighlightedText;
} else {
painter.fillRect(rect(), colorScheme.TabBackground);
fg = colorScheme.TabText;
}
painter.setPen(fg);
painter.drawText(4, (height() + fontMetrics().height()) / 2, this->text);
}
void
NotebookTab::mousePressEvent(QMouseEvent *)
{
this->mouseDown = true;
repaint();
this->notebook->select(page);
}
void
NotebookTab::mouseReleaseEvent(QMouseEvent *)
{
this->mouseDown = false;
repaint();
}
void
NotebookTab::enterEvent(QEvent *)
{
this->mouseOver = true;
repaint();
}
void
NotebookTab::leaveEvent(QEvent *)
{
this->mouseOver = false;
repaint();
}
void
NotebookTab::dragEnterEvent(QDragEnterEvent *event)
{
this->notebook->select(page);
}
}
}
+90
View File
@@ -0,0 +1,90 @@
#ifndef NOTEBOOKTAB_H
#define NOTEBOOKTAB_H
#include <QWidget>
namespace chatterino {
namespace widgets {
class Notebook;
class NotebookPage;
class NotebookTab : public QWidget
{
Q_OBJECT
public:
enum HighlightStyle {
HighlightNone,
HighlightHighlighted,
HighlightNewMessage
};
NotebookTab(Notebook *notebook);
void calcSize();
NotebookPage *page;
const QString &
getText() const
{
return this->text;
}
void
setText(const QString &text)
{
this->text = text;
}
bool
getSelected()
{
return this->selected;
}
void
setSelected(bool value)
{
this->selected = value;
repaint();
}
HighlightStyle
getHighlightStyle() const
{
return this->highlightStyle;
}
void
setHighlightStyle(HighlightStyle style)
{
this->highlightStyle = style;
repaint();
}
protected:
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE;
void enterEvent(QEvent *) Q_DECL_OVERRIDE;
void leaveEvent(QEvent *) Q_DECL_OVERRIDE;
void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE;
private:
Notebook *notebook;
QString text;
bool selected;
bool mouseOver;
bool mouseDown;
HighlightStyle highlightStyle;
};
}
}
#endif // NOTEBOOKTAB_H
+119
View File
@@ -0,0 +1,119 @@
#include "widgets/scrollbar.h"
#include "colorscheme.h"
#include <QPainter>
#define MIN_THUMB_HEIGHT 10
namespace chatterino {
namespace widgets {
ScrollBar::ScrollBar(QWidget *widget)
: QWidget(widget)
, mutex()
, highlights(NULL)
, thumbRect()
, maximum()
, minimum()
, largeChange()
, smallChange()
, value()
{
resize(16, 100);
}
ScrollBar::~ScrollBar()
{
auto highlight = this->highlights;
while (highlight != NULL) {
auto tmp = highlight->next;
delete highlight;
highlight = tmp;
}
}
void
ScrollBar::removeHighlightsWhere(std::function<bool(ScrollBarHighlight &)> func)
{
this->mutex.lock();
ScrollBarHighlight *last = NULL;
ScrollBarHighlight *current = this->highlights;
while (current != NULL) {
if (func(*current)) {
if (last == NULL) {
this->highlights = current->next;
} else {
last->next = current->next;
}
auto oldCurrent = current;
current = current->next;
last = current;
delete oldCurrent;
}
}
this->mutex.unlock();
}
void
ScrollBar::addHighlight(ScrollBarHighlight *highlight)
{
this->mutex.lock();
if (this->highlights == NULL) {
this->highlights = highlight;
} else {
highlight->next = this->highlights->next;
this->highlights->next = highlight;
}
this->mutex.unlock();
}
void
ScrollBar::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.fillRect(rect(), ColorScheme::instance().ScrollbarBG);
painter.fillRect(QRect(0, 0, width(), this->buttonHeight),
QColor(255, 0, 0));
painter.fillRect(
QRect(0, height() - this->buttonHeight, width(), this->buttonHeight),
QColor(255, 0, 0));
ScrollBarHighlight *highlight = this->highlights;
this->mutex.lock();
// do {
// painter.fillRect();
// } while ((highlight = highlight->next()) != NULL);
this->mutex.unlock();
}
void
ScrollBar::updateScroll()
{
this->trackHeight = height() - this->buttonHeight - this->buttonHeight -
MIN_THUMB_HEIGHT - 1;
this->thumbRect =
QRect(0,
(int)(this->value / this->maximum * this->trackHeight) + 1 +
this->buttonHeight,
width(),
(int)(this->largeChange / this->maximum * this->trackHeight) +
MIN_THUMB_HEIGHT);
repaint();
}
}
}
+115
View File
@@ -0,0 +1,115 @@
#ifndef SCROLLBAR_H
#define SCROLLBAR_H
#include "widgets/scrollbarhighlight.h"
#include <QMutex>
#include <QWidget>
#include <functional>
namespace chatterino {
namespace widgets {
class ScrollBar : public QWidget
{
Q_OBJECT
public:
ScrollBar(QWidget *parent = 0);
~ScrollBar();
void removeHighlightsWhere(std::function<bool(ScrollBarHighlight &)> func);
void addHighlight(ScrollBarHighlight *highlight);
void
setMaximum(qreal value)
{
this->maximum = value;
this->updateScroll();
}
void
setMinimum(qreal value)
{
this->minimum = value;
this->updateScroll();
}
void
setLargeChange(qreal value)
{
this->largeChange = value;
this->updateScroll();
}
void
setSmallChange(qreal value)
{
this->smallChange = value;
this->updateScroll();
}
void
setValue(qreal value)
{
this->value = value;
this->updateScroll();
}
qreal
getMaximum() const
{
return this->maximum;
}
qreal
getMinimum() const
{
return this->minimum;
}
qreal
getLargeChange() const
{
return this->largeChange;
}
qreal
getSmallChange() const
{
return this->smallChange;
}
qreal
getValue() const
{
return this->value;
}
private:
QMutex mutex;
ScrollBarHighlight *highlights;
void paintEvent(QPaintEvent *);
int buttonHeight;
int trackHeight;
QRect thumbRect;
qreal maximum;
qreal minimum;
qreal largeChange;
qreal smallChange;
qreal value;
void updateScroll();
};
}
}
#endif // SCROLLBAR_H
+18
View File
@@ -0,0 +1,18 @@
#include "widgets/scrollbarhighlight.h"
#include "colorscheme.h"
namespace chatterino {
namespace widgets {
ScrollBarHighlight::ScrollBarHighlight(float position, int colorIndex,
Style style, QString tag)
: position(position)
, colorIndex(std::max(
0, std::min(ColorScheme::instance().HighlightColorCount, colorIndex)))
, style(style)
, tag(tag)
, next(NULL)
{
}
}
}
+52
View File
@@ -0,0 +1,52 @@
#ifndef SCROLLBARHIGHLIGHT_H
#define SCROLLBARHIGHLIGHT_H
#include "QString"
namespace chatterino {
namespace widgets {
class ScrollBarHighlight
{
public:
enum Style { Default, Left, Right, SingleLine };
ScrollBarHighlight(float getPosition, int getColorIndex,
Style getStyle = Default, QString tag = "");
Style
getStyle()
{
return style;
}
float
getPosition()
{
return position;
}
int
getColorIndex()
{
return colorIndex;
}
QString
getTag()
{
return tag;
}
ScrollBarHighlight *next;
private:
Style style;
float position;
int colorIndex;
QString tag;
};
}
}
#endif // SCROLLBARHIGHLIGHT_H
+179
View File
@@ -0,0 +1,179 @@
#include "widgets/settingsdialog.h"
#include "widgets/settingsdialogtab.h"
#include <QComboBox>
#include <QFile>
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QPalette>
#include <QResource>
namespace chatterino {
namespace widgets {
SettingsDialog::SettingsDialog()
{
QFile file(":/qss/settings.qss");
file.open(QFile::ReadOnly);
QString styleSheet = QLatin1String(file.readAll());
setStyleSheet(styleSheet);
QPalette palette;
palette.setColor(QPalette::Background, QColor("#444"));
setPalette(palette);
pageStack.setObjectName("pages");
setLayout(&vbox);
vbox.addLayout(&hbox);
vbox.addWidget(&buttonBox);
auto tabWidget = new QWidget();
tabWidget->setObjectName("tabWidget");
tabWidget->setLayout(&tabs);
tabWidget->setFixedWidth(200);
hbox.addWidget(tabWidget);
hbox.addLayout(&pageStack);
buttonBox.addButton(&okButton, QDialogButtonBox::ButtonRole::AcceptRole);
buttonBox.addButton(&cancelButton,
QDialogButtonBox::ButtonRole::RejectRole);
okButton.setText("OK");
cancelButton.setText("Cancel");
resize(600, 500);
addTabs();
}
void
SettingsDialog::addTabs()
{
QVBoxLayout *vbox;
// Appearance
vbox = new QVBoxLayout();
{
auto group = new QGroupBox("Application");
auto form = new QFormLayout();
auto combo = new QComboBox();
auto slider = new QSlider(Qt::Horizontal);
auto font = new QPushButton("select");
form->addRow("Theme:", combo);
form->addRow("Theme color:", slider);
form->addRow("Font:", font);
group->setLayout(form);
vbox->addWidget(group);
}
{
auto group = new QGroupBox("Messages");
auto v = new QVBoxLayout();
v->addWidget(createCheckbox("Show timestamp", ""));
v->addWidget(createCheckbox("Show seconds in timestamp", ""));
v->addWidget(createCheckbox(
"Allow sending duplicate messages (add a space at the end)", ""));
v->addWidget(createCheckbox("Seperate messages", ""));
v->addWidget(createCheckbox("Show message length", ""));
group->setLayout(v);
vbox->addWidget(group);
}
vbox->addStretch(1);
addTab(vbox, "Appearance", ":/images/AppearanceEditorPart_16x.png");
// Behaviour
vbox = new QVBoxLayout();
vbox->addWidget(createCheckbox("Hide input box if empty", ""));
vbox->addWidget(
createCheckbox("Mention users with a @ (except in commands)", ""));
vbox->addWidget(createCheckbox("Window always on top", ""));
vbox->addWidget(createCheckbox("Show last read message indicator", ""));
{
auto v = new QVBoxLayout();
v->addWidget(new QLabel("Mouse scroll speed"));
auto scroll = new QSlider(Qt::Horizontal);
v->addWidget(scroll);
v->addStretch(1);
}
vbox->addStretch(1);
addTab(vbox, "Behaviour", ":/images/AppearanceEditorPart_16x.png");
// Commands
vbox = new QVBoxLayout();
vbox->addWidget(new QLabel());
vbox->addStretch(1);
addTab(vbox, "Commands", ":/images/CustomActionEditor_16x.png");
// Add stretch
tabs.addStretch(1);
}
QCheckBox *
SettingsDialog::createCheckbox(QString title, QString settingsId)
{
return new QCheckBox(title);
}
void
SettingsDialog::addTab(QLayout *layout, QString title, QString imageRes)
{
auto widget = new QWidget();
widget->setLayout(layout);
auto tab = new SettingsDialogTab(this, title, imageRes);
tab->setWidget(widget);
tabs.addWidget(tab, 0, Qt::AlignTop);
pageStack.addWidget(widget);
if (tabs.count() == 1) {
select(tab);
}
}
void
SettingsDialog::select(SettingsDialogTab *tab)
{
pageStack.setCurrentWidget(tab->getWidget());
if (selectedTab != NULL) {
selectedTab->setSelected(false);
selectedTab->setStyleSheet("");
}
tab->setSelected(true);
tab->setStyleSheet("background: #F00;"
"background: qlineargradient( x1:0 y1:0, x2:1 y2:0, "
"stop:0 #333, stop:1 #555);"
"border-right: none;");
selectedTab = tab;
}
}
}
+47
View File
@@ -0,0 +1,47 @@
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include "widgets/settingsdialogtab.h"
#include <QButtonGroup>
#include <QCheckBox>
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QListView>
#include <QMainWindow>
#include <QPushButton>
#include <QStackedLayout>
#include <QVBoxLayout>
#include <QWidget>
namespace chatterino {
namespace widgets {
class SettingsDialog : public QWidget
{
public:
SettingsDialog();
void select(SettingsDialogTab *tab);
private:
QVBoxLayout tabs;
QVBoxLayout vbox;
QHBoxLayout hbox;
QStackedLayout pageStack;
QDialogButtonBox buttonBox;
QPushButton okButton;
QPushButton cancelButton;
void addTab(QLayout *layout, QString title, QString imageRes);
void addTabs();
SettingsDialogTab *selectedTab = NULL;
QCheckBox *createCheckbox(QString title, QString settingsId);
};
}
}
#endif // SETTINGSDIALOG_H
+51
View File
@@ -0,0 +1,51 @@
#include "widgets/settingsdialogtab.h"
#include "widgets/settingsdialog.h"
#include <QPainter>
#include <QStyleOption>
namespace chatterino {
namespace widgets {
SettingsDialogTab::SettingsDialogTab(SettingsDialog *dialog, QString label,
QString imageRes)
: image(QImage(imageRes))
{
this->dialog = dialog;
this->label = label;
setFixedHeight(32);
setCursor(QCursor(Qt::PointingHandCursor));
}
void
SettingsDialogTab::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QStyleOption opt;
opt.init(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
int a = (height() - image.width()) / 2;
painter.drawImage(a, a, image);
a = a + a + image.width();
painter.drawText(QRect(a, 0, width() - a, height()), label,
QTextOption(Qt::AlignLeft | Qt::AlignVCenter));
}
void
SettingsDialogTab::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton)
return;
dialog->select(this);
}
}
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef SETTINGSNOTEBOOKTAB_H
#define SETTINGSNOTEBOOKTAB_H
#include <QPaintEvent>
#include <QWidget>
namespace chatterino {
namespace widgets {
class SettingsDialog;
class SettingsDialogTab : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool getSelected READ getSelected WRITE setSelected NOTIFY
selectedChanged)
public:
SettingsDialogTab(SettingsDialog *dialog, QString label, QString imageRes);
void
setSelected(bool selected)
{
if (this->selected == selected)
return;
this->selected = selected;
emit selectedChanged(selected);
}
bool
getSelected() const
{
return this->selected;
}
QWidget *
getWidget()
{
return this->widget;
}
void
setWidget(QWidget *widget)
{
this->widget = widget;
}
signals:
void selectedChanged(bool);
private:
void paintEvent(QPaintEvent *);
void mouseReleaseEvent(QMouseEvent *event);
QWidget *widget;
QString label;
QImage image;
SettingsDialog *dialog = NULL;
bool selected = false;
};
}
}
#endif // SETTINGSNOTEBOOKTAB_H
+23
View File
@@ -0,0 +1,23 @@
#ifndef SIGNALLABEL_H
#define SIGNALLABEL_H
#include <QFlags>
#include <QLabel>
#include <QWidget>
class SignalLabel : public QLabel
{
Q_OBJECT
public:
explicit SignalLabel(QWidget *parent = 0, Qt::WindowFlags f = 0)
: QLabel(parent, f) {}
virtual ~SignalLabel() = default;
signals:
void mouseDoubleClick(QMouseEvent *ev);
protected:
virtual void mouseDoubleClickEvent(QMouseEvent *ev) override {
emit this->mouseDoubleClick(ev);
}
};
#endif // SIGNALLABEL_H
+46
View File
@@ -0,0 +1,46 @@
#include "widgets/textinputdialog.h"
#include <QSizePolicy>
namespace chatterino {
namespace widgets {
TextInputDialog::TextInputDialog(QWidget *parent)
: QDialog(parent)
, vbox(this)
, lineEdit()
, buttonBox()
, okButton("OK")
, cancelButton("Cancel")
{
this->vbox.addWidget(&this->lineEdit);
this->vbox.addLayout(&this->buttonBox);
this->buttonBox.addStretch(1);
this->buttonBox.addWidget(&this->okButton);
this->buttonBox.addWidget(&this->cancelButton);
QObject::connect(&this->okButton, SIGNAL(clicked()), this,
SLOT(okButtonClicked()));
QObject::connect(&this->cancelButton, SIGNAL(clicked()), this,
SLOT(cancelButtonClicked()));
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setWindowFlags((windowFlags() & ~(Qt::WindowContextHelpButtonHint)) |
Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
}
void
TextInputDialog::okButtonClicked()
{
accept();
close();
}
void
TextInputDialog::cancelButtonClicked()
{
reject();
close();
}
}
}
+47
View File
@@ -0,0 +1,47 @@
#ifndef TEXTINPUTDIALOG_H
#define TEXTINPUTDIALOG_H
#include <QDialog>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
#include <QVBoxLayout>
namespace chatterino {
namespace widgets {
class TextInputDialog : public QDialog
{
Q_OBJECT
public:
TextInputDialog(QWidget *parent = NULL);
QString
getText() const
{
return lineEdit.text();
}
void
setText(const QString &text)
{
lineEdit.setText(text);
}
private:
QVBoxLayout vbox;
QLineEdit lineEdit;
QHBoxLayout buttonBox;
QPushButton okButton;
QPushButton cancelButton;
private slots:
void okButtonClicked();
void cancelButtonClicked();
};
}
}
#endif // TEXTINPUTDIALOG_H