Merge branch 'master' into apa-notification-on-live
This commit is contained in:
@@ -363,6 +363,12 @@ void Split::handleModifiers(Qt::KeyboardModifiers modifiers)
|
||||
}
|
||||
}
|
||||
|
||||
void Split::setIsTopRightSplit(bool value)
|
||||
{
|
||||
this->isTopRightSplit_ = value;
|
||||
this->header_->setAddButtonVisible(value);
|
||||
}
|
||||
|
||||
/// Slots
|
||||
void Split::addSibling()
|
||||
{
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
void layoutMessages();
|
||||
void updateGifEmotes();
|
||||
void updateLastReadMessage();
|
||||
void setIsTopRightSplit(bool value);
|
||||
|
||||
void drag();
|
||||
|
||||
@@ -106,10 +107,11 @@ private:
|
||||
|
||||
NullablePtr<SelectChannelDialog> selectChannelDialog_;
|
||||
|
||||
bool moderationMode_ = false;
|
||||
bool moderationMode_{};
|
||||
bool isTopRightSplit_{};
|
||||
|
||||
bool isMouseOver_ = false;
|
||||
bool isDragging_ = false;
|
||||
bool isMouseOver_{};
|
||||
bool isDragging_{};
|
||||
|
||||
pajlada::Signals::Connection channelIDChangedConnection_;
|
||||
pajlada::Signals::Connection usermodeChangedConnection_;
|
||||
|
||||
@@ -310,8 +310,33 @@ void SplitContainer::focusSplitRecursive(Node *node, Direction direction)
|
||||
}
|
||||
}
|
||||
|
||||
Split *SplitContainer::getTopRightSplit(Node &node)
|
||||
{
|
||||
switch (node.getType()) {
|
||||
case Node::_Split:
|
||||
return node.getSplit();
|
||||
case Node::VerticalContainer:
|
||||
if (!node.getChildren().empty())
|
||||
return getTopRightSplit(*node.getChildren().front());
|
||||
break;
|
||||
case Node::HorizontalContainer:
|
||||
if (!node.getChildren().empty())
|
||||
return getTopRightSplit(*node.getChildren().back());
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SplitContainer::layout()
|
||||
{
|
||||
// update top right split
|
||||
auto topRight = this->getTopRightSplit(this->baseNode_);
|
||||
if (this->topRight_) this->topRight_->setIsTopRightSplit(false);
|
||||
this->topRight_ = topRight;
|
||||
if (topRight) this->topRight_->setIsTopRightSplit(true);
|
||||
|
||||
// layout
|
||||
this->baseNode_.geometry_ = this->rect().adjusted(-1, -1, 0, 0);
|
||||
|
||||
std::vector<DropRect> _dropRects;
|
||||
@@ -431,9 +456,10 @@ void SplitContainer::paintEvent(QPaintEvent *)
|
||||
|
||||
if (notebook != nullptr) {
|
||||
if (notebook->getPageCount() > 1) {
|
||||
text += "\n\nTip: After adding a split you can hold <Alt> to "
|
||||
"move it or split it "
|
||||
"further.";
|
||||
text +=
|
||||
"\n\nTip: After adding a split you can hold <Ctrl+Alt> to "
|
||||
"move it or split it "
|
||||
"further.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ private:
|
||||
void addSplit(Split *split);
|
||||
|
||||
void decodeNodeRecusively(QJsonObject &obj, Node *node);
|
||||
Split *getTopRightSplit(Node &node);
|
||||
|
||||
struct DropRegion {
|
||||
QRect rect;
|
||||
@@ -239,6 +240,7 @@ private:
|
||||
|
||||
Node baseNode_;
|
||||
Split *selected_;
|
||||
Split *topRight_{};
|
||||
|
||||
NotebookTab *tab_;
|
||||
std::vector<Split *> splits_;
|
||||
|
||||
@@ -93,11 +93,11 @@ namespace {
|
||||
title += " (live)";
|
||||
|
||||
// description
|
||||
if (settings.showUptime) title += " - " + s.uptime;
|
||||
if (settings.showViewerCount)
|
||||
title += " - " + QString::number(s.viewerCount);
|
||||
if (settings.showTitle) title += " - " + s.title;
|
||||
if (settings.showGame) title += " - " + s.game;
|
||||
if (settings.showUptime) title += " - " + s.uptime;
|
||||
if (settings.showTitle) title += " - " + s.title;
|
||||
|
||||
return title;
|
||||
}
|
||||
@@ -138,33 +138,42 @@ SplitHeader::SplitHeader(Split *_split)
|
||||
|
||||
void SplitHeader::initializeLayout()
|
||||
{
|
||||
auto layout = makeLayout<QHBoxLayout>(
|
||||
{// title
|
||||
this->titleLabel = makeWidget<Label>([](auto w) {
|
||||
w->setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||
QSizePolicy::Preferred);
|
||||
w->setCentered(true);
|
||||
w->setHasOffset(false);
|
||||
}),
|
||||
// mode
|
||||
this->modeButton_ = makeWidget<EffectLabel>([&](auto w) {
|
||||
w->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
w->hide();
|
||||
this->initializeModeSignals(*w);
|
||||
w->setMenu(this->createChatModeMenu());
|
||||
}),
|
||||
// moderator
|
||||
this->moderationButton_ = makeWidget<Button>([&](auto w) {
|
||||
QObject::connect(w, &Button::clicked, this, [this, w]() mutable {
|
||||
this->split_->setModerationMode(
|
||||
!this->split_->getModerationMode());
|
||||
auto layout = makeLayout<QHBoxLayout>({
|
||||
// title
|
||||
this->titleLabel_ = makeWidget<Label>([](auto w) {
|
||||
w->setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||
QSizePolicy::Preferred);
|
||||
w->setCentered(true);
|
||||
w->setHasOffset(false);
|
||||
}),
|
||||
// mode
|
||||
this->modeButton_ = makeWidget<EffectLabel>([&](auto w) {
|
||||
w->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
w->hide();
|
||||
this->initializeModeSignals(*w);
|
||||
w->setMenu(this->createChatModeMenu());
|
||||
}),
|
||||
// moderator
|
||||
this->moderationButton_ = makeWidget<Button>([&](auto w) {
|
||||
QObject::connect(w, &Button::clicked, this, [this, w]() mutable {
|
||||
this->split_->setModerationMode(
|
||||
!this->split_->getModerationMode());
|
||||
|
||||
w->setDim(!this->split_->getModerationMode());
|
||||
});
|
||||
}),
|
||||
// dropdown
|
||||
this->dropdownButton_ = makeWidget<Button>(
|
||||
[&](auto w) { w->setMenu(this->createMainMenu()); })});
|
||||
w->setDim(!this->split_->getModerationMode());
|
||||
});
|
||||
}),
|
||||
// dropdown
|
||||
this->dropdownButton_ = makeWidget<Button>(
|
||||
[&](auto w) { w->setMenu(this->createMainMenu()); }),
|
||||
// add split
|
||||
this->addButton_ = makeWidget<Button>([&](auto w) {
|
||||
w->setPixmap(getApp()->resources->buttons.addSplitDark);
|
||||
w->setEnableMargin(false);
|
||||
|
||||
QObject::connect(w, &Button::clicked, this,
|
||||
[this]() { this->split_->addSibling(); });
|
||||
}),
|
||||
});
|
||||
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
@@ -174,18 +183,16 @@ void SplitHeader::initializeLayout()
|
||||
std::unique_ptr<QMenu> SplitHeader::createMainMenu()
|
||||
{
|
||||
auto menu = std::make_unique<QMenu>();
|
||||
menu->addAction("New split", this->split_, &Split::addSibling,
|
||||
QKeySequence("Ctrl+T"));
|
||||
menu->addAction("Close split", this->split_, &Split::deleteFromContainer,
|
||||
menu->addAction("Close channel", this->split_, &Split::deleteFromContainer,
|
||||
QKeySequence("Ctrl+W"));
|
||||
menu->addAction("Change channel", this->split_, &Split::changeChannel,
|
||||
QKeySequence("Ctrl+R"));
|
||||
menu->addSeparator();
|
||||
menu->addAction("Popup", this->split_, &Split::popup);
|
||||
menu->addAction("Viewer list", this->split_, &Split::showViewerList);
|
||||
menu->addAction("Search", this->split_, &Split::showSearch,
|
||||
QKeySequence("Ctrl+F"));
|
||||
menu->addSeparator();
|
||||
menu->addAction("Popup", this->split_, &Split::popup);
|
||||
#ifdef USEWEBENGINE
|
||||
this->dropdownMenu.addAction("Start watching", this, [this] {
|
||||
ChannelPtr _channel = this->split->getChannel();
|
||||
@@ -224,7 +231,7 @@ std::unique_ptr<QMenu> SplitHeader::createMainMenu()
|
||||
menu->addSeparator();
|
||||
menu->addAction("Reload channel emotes", this, SLOT(reloadChannelEmotes()));
|
||||
menu->addAction("Reconnect", this, SLOT(reconnect()));
|
||||
// menu->addAction("Clear messages", this->split_, &Split::doClearChat);
|
||||
menu->addAction("Clear messages", this->split_, &Split::clear);
|
||||
// menu->addSeparator();
|
||||
// menu->addAction("Show changelog", this, SLOT(menuShowChangelog()));
|
||||
|
||||
@@ -351,6 +358,12 @@ void SplitHeader::scaleChangedEvent(float scale)
|
||||
this->setFixedHeight(w);
|
||||
this->dropdownButton_->setFixedWidth(w);
|
||||
this->moderationButton_->setFixedWidth(w);
|
||||
this->addButton_->setFixedWidth(w * 5 / 8);
|
||||
}
|
||||
|
||||
void SplitHeader::setAddButtonVisible(bool value)
|
||||
{
|
||||
this->addButton_->setVisible(value);
|
||||
}
|
||||
|
||||
void SplitHeader::updateChannelText()
|
||||
@@ -375,7 +388,7 @@ void SplitHeader::updateChannelText()
|
||||
}
|
||||
}
|
||||
|
||||
this->titleLabel->setText(title.isEmpty() ? "<empty>" : title);
|
||||
this->titleLabel_->setText(title.isEmpty() ? "<empty>" : title);
|
||||
}
|
||||
|
||||
void SplitHeader::updateModerationModeIcon()
|
||||
@@ -475,6 +488,8 @@ void SplitHeader::enterEvent(QEvent *event)
|
||||
tooltip->moveTo(this, this->mapToGlobal(this->rect().bottomLeft()),
|
||||
false);
|
||||
tooltip->setText(this->tooltipText_);
|
||||
tooltip->setWordWrap(false);
|
||||
tooltip->adjustSize();
|
||||
tooltip->show();
|
||||
tooltip->raise();
|
||||
}
|
||||
@@ -499,7 +514,7 @@ void SplitHeader::themeChangedEvent()
|
||||
} else {
|
||||
palette.setColor(QPalette::Foreground, this->theme->splits.header.text);
|
||||
}
|
||||
this->titleLabel->setPalette(palette);
|
||||
this->titleLabel_->setPalette(palette);
|
||||
|
||||
// --
|
||||
if (this->theme->isLightTheme()) {
|
||||
|
||||
@@ -24,6 +24,8 @@ class SplitHeader final : public BaseWidget, pajlada::Signals::SignalHolder
|
||||
public:
|
||||
explicit SplitHeader(Split *_chatWidget);
|
||||
|
||||
void setAddButtonVisible(bool value);
|
||||
|
||||
void updateChannelText();
|
||||
void updateModerationModeIcon();
|
||||
void updateRoomModes();
|
||||
@@ -53,9 +55,10 @@ private:
|
||||
|
||||
// ui
|
||||
Button *dropdownButton_{};
|
||||
Label *titleLabel{};
|
||||
Label *titleLabel_{};
|
||||
EffectLabel *modeButton_{};
|
||||
Button *moderationButton_{};
|
||||
Button *addButton_{};
|
||||
|
||||
// states
|
||||
QPoint dragStart_{};
|
||||
|
||||
@@ -84,21 +84,8 @@ void SplitInput::initLayout()
|
||||
}));
|
||||
|
||||
// open emote popup
|
||||
QObject::connect(this->ui_.emoteButton, &EffectLabel::clicked, [this] {
|
||||
if (!this->emotePopup_) {
|
||||
this->emotePopup_ = std::make_unique<EmotePopup>();
|
||||
this->emotePopup_->linkClicked.connect([this](const Link &link) {
|
||||
if (link.type == Link::InsertText) {
|
||||
this->insertText(link.value + " ");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this->emotePopup_->resize(int(300 * this->emotePopup_->getScale()),
|
||||
int(500 * this->emotePopup_->getScale()));
|
||||
this->emotePopup_->loadChannel(this->split_->getChannel());
|
||||
this->emotePopup_->show();
|
||||
});
|
||||
QObject::connect(this->ui_.emoteButton, &EffectLabel::clicked,
|
||||
[=] { this->openEmotePopup(); });
|
||||
|
||||
// clear channelview selection when selecting in the input
|
||||
QObject::connect(this->ui_.textEdit, &QTextEdit::copyAvailable,
|
||||
@@ -159,6 +146,23 @@ void SplitInput::updateEmoteButton()
|
||||
this->ui_.emoteButton->setFixedHeight(int(18 * scale));
|
||||
}
|
||||
|
||||
void SplitInput::openEmotePopup()
|
||||
{
|
||||
if (!this->emotePopup_) {
|
||||
this->emotePopup_ = std::make_unique<EmotePopup>();
|
||||
this->emotePopup_->linkClicked.connect([this](const Link &link) {
|
||||
if (link.type == Link::InsertText) {
|
||||
this->insertText(link.value + " ");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this->emotePopup_->resize(int(300 * this->emotePopup_->getScale()),
|
||||
int(500 * this->emotePopup_->getScale()));
|
||||
this->emotePopup_->loadChannel(this->split_->getChannel());
|
||||
this->emotePopup_->show();
|
||||
}
|
||||
|
||||
void SplitInput::installKeyPressedEvent()
|
||||
{
|
||||
auto app = getApp();
|
||||
@@ -177,7 +181,8 @@ void SplitInput::installKeyPressedEvent()
|
||||
|
||||
c->sendMessage(sendMessage);
|
||||
// don't add duplicate messages and empty message to message history
|
||||
if ((this->prevMsg_.isEmpty() || !this->prevMsg_.endsWith(message)) &&
|
||||
if ((this->prevMsg_.isEmpty() ||
|
||||
!this->prevMsg_.endsWith(message)) &&
|
||||
!message.trimmed().isEmpty())
|
||||
this->prevMsg_.append(message);
|
||||
|
||||
@@ -186,7 +191,7 @@ void SplitInput::installKeyPressedEvent()
|
||||
this->currMsg_ = QString();
|
||||
this->ui_.textEdit->setText(QString());
|
||||
this->prevIndex_ = 0;
|
||||
} else if (this->ui_.textEdit->toPlainText() ==
|
||||
} else if (message ==
|
||||
this->prevMsg_.at(this->prevMsg_.size() - 1)) {
|
||||
this->prevMsg_.removeLast();
|
||||
}
|
||||
@@ -227,6 +232,13 @@ void SplitInput::installKeyPressedEvent()
|
||||
page->selectNextSplit(SplitContainer::Below);
|
||||
}
|
||||
} else {
|
||||
// If user did not write anything before then just do nothing.
|
||||
if (this->prevMsg_.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
bool cursorToEnd = true;
|
||||
QString message = ui_.textEdit->toPlainText();
|
||||
|
||||
if (this->prevIndex_ != (this->prevMsg_.size() - 1) &&
|
||||
this->prevIndex_ != this->prevMsg_.size()) {
|
||||
this->prevIndex_++;
|
||||
@@ -234,12 +246,27 @@ void SplitInput::installKeyPressedEvent()
|
||||
this->prevMsg_.at(this->prevIndex_));
|
||||
} else {
|
||||
this->prevIndex_ = this->prevMsg_.size();
|
||||
this->ui_.textEdit->setText(this->currMsg_);
|
||||
if (message == this->prevMsg_.at(this->prevIndex_ - 1)) {
|
||||
// If user has just come from a message history
|
||||
// Then simply get currMsg_.
|
||||
this->ui_.textEdit->setText(this->currMsg_);
|
||||
} else if (message != this->currMsg_) {
|
||||
// If user are already in current message
|
||||
// And type something new
|
||||
// Then replace currMsg_ with new one.
|
||||
this->currMsg_ = message;
|
||||
}
|
||||
// If user is already in current message
|
||||
// Then don't touch cursos.
|
||||
cursorToEnd =
|
||||
(message == this->prevMsg_.at(this->prevIndex_ - 1));
|
||||
}
|
||||
|
||||
QTextCursor cursor = this->ui_.textEdit->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
this->ui_.textEdit->setTextCursor(cursor);
|
||||
if (cursorToEnd) {
|
||||
QTextCursor cursor = this->ui_.textEdit->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
this->ui_.textEdit->setTextCursor(cursor);
|
||||
}
|
||||
}
|
||||
} else if (event->key() == Qt::Key_Left) {
|
||||
if (event->modifiers() == Qt::AltModifier) {
|
||||
@@ -284,6 +311,9 @@ void SplitInput::installKeyPressedEvent()
|
||||
this->split_->copyToClipboard();
|
||||
event->accept();
|
||||
}
|
||||
} else if (event->key() == Qt::Key_E &&
|
||||
event->modifiers() == Qt::ControlModifier) {
|
||||
this->openEmotePopup();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ private:
|
||||
void initLayout();
|
||||
void installKeyPressedEvent();
|
||||
void updateEmoteButton();
|
||||
void openEmotePopup();
|
||||
|
||||
Split *const split_;
|
||||
std::shared_ptr<EmotePopup> emotePopup_;
|
||||
|
||||
Reference in New Issue
Block a user