From 50a2454cc640d8be9816712074973de585f14b0e Mon Sep 17 00:00:00 2001 From: fourtf Date: Fri, 25 May 2018 14:57:17 +0200 Subject: [PATCH] added alt+arrowkeys back --- src/widgets/helper/resizingtextedit.cpp | 11 ++- src/widgets/helper/resizingtextedit.hpp | 3 + src/widgets/helper/splitinput.cpp | 49 ++++------- src/widgets/helper/splitinput.hpp | 6 -- src/widgets/split.cpp | 2 + src/widgets/split.hpp | 1 + src/widgets/splitcontainer.cpp | 112 +++++++++++++++++++++++- src/widgets/splitcontainer.hpp | 26 +++--- 8 files changed, 154 insertions(+), 56 deletions(-) diff --git a/src/widgets/helper/resizingtextedit.cpp b/src/widgets/helper/resizingtextedit.cpp index 4b88ec294..752b1f236 100644 --- a/src/widgets/helper/resizingtextedit.cpp +++ b/src/widgets/helper/resizingtextedit.cpp @@ -137,10 +137,19 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event) } } +void ResizingTextEdit::focusInEvent(QFocusEvent *event) +{ + QTextEdit::focusInEvent(event); + + if (event->gotFocus()) { + this->focused.invoke(); + } +} + void ResizingTextEdit::setCompleter(QCompleter *c) { if (this->completer) { - QObject::disconnect(this->completer, 0, this, 0); + QObject::disconnect(this->completer, nullptr, this, nullptr); } this->completer = c; diff --git a/src/widgets/helper/resizingtextedit.hpp b/src/widgets/helper/resizingtextedit.hpp index d68ea0ebd..736619772 100644 --- a/src/widgets/helper/resizingtextedit.hpp +++ b/src/widgets/helper/resizingtextedit.hpp @@ -15,6 +15,7 @@ public: bool hasHeightForWidth() const override; pajlada::Signals::Signal keyPressed; + pajlada::Signals::NoArgSignal focused; void setCompleter(QCompleter *c); QCompleter *getCompleter() const; @@ -23,6 +24,8 @@ protected: int heightForWidth(int) const override; void keyPressEvent(QKeyEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + private: QCompleter *completer = nullptr; bool completionInProgress = false; diff --git a/src/widgets/helper/splitinput.cpp b/src/widgets/helper/splitinput.cpp index b06444733..803c36086 100644 --- a/src/widgets/helper/splitinput.cpp +++ b/src/widgets/helper/splitinput.cpp @@ -165,16 +165,11 @@ void SplitInput::installKeyPressedEvent() return; } if (event->modifiers() == Qt::AltModifier) { - // SplitContainer *page = - // static_cast(this->chatWidget->parentWidget()); + SplitContainer *page = this->split->getContainer(); - // page->requestFocus(); - // int reqX = page->currentX; - // int reqY = page->lastRequestedY[reqX] - 1; - - // qDebug() << "Alt+Down to" << reqX << "/" << reqY; - - // page->requestFocus(reqX, reqY); + if (page != nullptr) { + page->selectNextSplit(SplitContainer::Above); + } } else { if (this->prevMsg.size() && this->prevIndex) { if (this->prevIndex == (this->prevMsg.size())) { @@ -194,15 +189,11 @@ void SplitInput::installKeyPressedEvent() return; } if (event->modifiers() == Qt::AltModifier) { - // SplitContainer *page = - // static_cast(this->chatWidget->parentWidget()); + SplitContainer *page = this->split->getContainer(); - // int reqX = page->currentX; - // int reqY = page->lastRequestedY[reqX] + 1; - - // qDebug() << "Alt+Down to" << reqX << "/" << reqY; - - // page->requestFocus(reqX, reqY); + if (page != nullptr) { + page->selectNextSplit(SplitContainer::Below); + } } else { if (this->prevIndex != (this->prevMsg.size() - 1) && this->prevIndex != this->prevMsg.size()) { @@ -219,27 +210,19 @@ void SplitInput::installKeyPressedEvent() } } else if (event->key() == Qt::Key_Left) { if (event->modifiers() == Qt::AltModifier) { - // SplitContainer *page = - // static_cast(this->chatWidget->parentWidget()); + SplitContainer *page = this->split->getContainer(); - // int reqX = page->currentX - 1; - // int reqY = page->lastRequestedY[reqX]; - - // qDebug() << "Alt+Left to" << reqX << "/" << reqY; - - // page->requestFocus(reqX, reqY); + if (page != nullptr) { + page->selectNextSplit(SplitContainer::Left); + } } } else if (event->key() == Qt::Key_Right) { if (event->modifiers() == Qt::AltModifier) { - // SplitContainer *page = - // static_cast(this->chatWidget->parentWidget()); + SplitContainer *page = this->split->getContainer(); - // int reqX = page->currentX + 1; - // int reqY = page->lastRequestedY[reqX]; - - // qDebug() << "Alt+Right to" << reqX << "/" << reqY; - - // page->requestFocus(reqX, reqY); + if (page != nullptr) { + page->selectNextSplit(SplitContainer::Right); + } } } else if (event->key() == Qt::Key_Tab) { if (event->modifiers() == Qt::ControlModifier) { diff --git a/src/widgets/helper/splitinput.hpp b/src/widgets/helper/splitinput.hpp index b73a64216..9f7d7fdbb 100644 --- a/src/widgets/helper/splitinput.hpp +++ b/src/widgets/helper/splitinput.hpp @@ -52,12 +52,6 @@ private: } ui; std::vector managedConnections; - // QHBoxLayout hbox; - // QVBoxLayout vbox; - // QHBoxLayout editContainer; - // ResizingTextEdit textInput; - // QLabel textLengthLabel; - // RippleEffectLabel emotesLabel; QStringList prevMsg; QString currMsg; int prevIndex = 0; diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index c3f9f1e9e..dda289b3b 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -136,6 +136,8 @@ Split::Split(QWidget *parent) this->overlay->hide(); } }); + + this->input.ui.textEdit->focused.connect([this] { this->focused.invoke(); }); } Split::~Split() diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index 41257550d..35b974850 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -46,6 +46,7 @@ public: ~Split() override; pajlada::Signals::NoArgSignal channelChanged; + pajlada::Signals::NoArgSignal focused; ChannelView &getChannelView(); SplitContainer *getContainer(); diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index 1ea304197..ad909dfaf 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -3,6 +3,7 @@ #include "common.hpp" #include "singletons/thememanager.hpp" #include "singletons/windowmanager.hpp" +#include "util/assertinguithread.hpp" #include "util/helpers.hpp" #include "util/layoutcreator.hpp" #include "widgets/helper/notebooktab.hpp" @@ -83,6 +84,8 @@ void SplitContainer::setTab(NotebookTab *_tab) void SplitContainer::appendNewSplit(bool openChannelNameDialog) { + util::assertInGuiThread(); + Split *split = new Split(this); this->appendSplit(split); @@ -115,6 +118,8 @@ void SplitContainer::insertSplit(Split *split, Direction direction, Split *relat void SplitContainer::insertSplit(Split *split, Direction direction, Node *relativeTo) { + util::assertInGuiThread(); + split->setContainer(this); if (relativeTo == nullptr) { @@ -136,6 +141,8 @@ void SplitContainer::insertSplit(Split *split, Direction direction, Node *relati void SplitContainer::addSplit(Split *split) { + util::assertInGuiThread(); + split->setParent(this); split->show(); split->giveFocus(Qt::MouseFocusReason); @@ -148,12 +155,33 @@ void SplitContainer::addSplit(Split *split) this->tab->setHighlightState(state); } }); + split->focused.connect([this, split] { this->setSelected(split); }); this->layout(); } +void SplitContainer::setSelected(Split *split) +{ + this->selected = split; + + if (Node *node = this->baseNode.findNodeContainingSplit(split)) { + this->setPreferedTargetRecursive(node); + } +} + +void SplitContainer::setPreferedTargetRecursive(Node *node) +{ + if (node->parent != nullptr) { + node->parent->preferedFocusTarget = node; + + this->setPreferedTargetRecursive(node->parent); + } +} + SplitContainer::Position SplitContainer::releaseSplit(Split *split) { + util::assertInGuiThread(); + Node *node = this->baseNode.findNodeContainingSplit(split); assert(node != nullptr); @@ -161,7 +189,9 @@ SplitContainer::Position SplitContainer::releaseSplit(Split *split) split->setParent(nullptr); Position position = node->releaseSplit(); this->layout(); - if (splits.size() != 0) { + if (splits.size() == 0) { + this->setSelected(nullptr); + } else { this->splits.front()->giveFocus(Qt::MouseFocusReason); } @@ -174,12 +204,77 @@ SplitContainer::Position SplitContainer::releaseSplit(Split *split) SplitContainer::Position SplitContainer::deleteSplit(Split *split) { + util::assertInGuiThread(); assert(split != nullptr); split->deleteLater(); return releaseSplit(split); } +void SplitContainer::selectNextSplit(Direction direction) +{ + util::assertInGuiThread(); + + if (Node *node = this->baseNode.findNodeContainingSplit(this->selected)) { + this->selectSplitRecursive(node, direction); + } +} + +void SplitContainer::selectSplitRecursive(Node *node, Direction direction) +{ + if (node->parent != nullptr) { + if (node->parent->type == Node::toContainerType(direction)) { + auto &siblings = node->parent->children; + + auto it = std::find_if(siblings.begin(), siblings.end(), + [node](const auto &other) { return other.get() == node; }); + assert(it != siblings.end()); + + if (direction == Direction::Left || direction == Direction::Above) { + if (it == siblings.begin()) { + this->selectSplitRecursive(node->parent, direction); + } else { + this->focusSplitRecursive(siblings[it - siblings.begin() - 1].get(), direction); + } + } else { + if (it->get() == siblings.back().get()) { + this->selectSplitRecursive(node->parent, direction); + } else { + this->focusSplitRecursive(siblings[it - siblings.begin() + 1].get(), direction); + } + } + } else { + this->selectSplitRecursive(node->parent, direction); + } + } +} + +void SplitContainer::focusSplitRecursive(Node *node, Direction direction) +{ + switch (node->type) { + case Node::_Split: { + node->split->giveFocus(Qt::OtherFocusReason); + } break; + + case Node::HorizontalContainer: + case Node::VerticalContainer: { + auto &children = node->children; + + auto it = std::find_if(children.begin(), children.end(), [node](const auto &other) { + return node->preferedFocusTarget == other.get(); + }); + + if (it != children.end()) { + this->focusSplitRecursive(it->get(), direction); + } else { + this->focusSplitRecursive(node->children.front().get(), direction); + } + } break; + + default:; + } +} + void SplitContainer::layout() { this->baseNode.geometry = this->rect(); @@ -383,6 +478,21 @@ void SplitContainer::refreshTabTitle() this->tab->setTitle(newTitle); } +int SplitContainer::getSplitCount() +{ + return 0; +} + +const std::vector SplitContainer::getSplits() const +{ + return this->splits; +} + +SplitContainer::Node *SplitContainer::getBaseNode() +{ + return &this->baseNode; +} + void SplitContainer::decodeFromJson(QJsonObject &obj) { assert(this->baseNode.type == Node::EmptyRoot); diff --git a/src/widgets/splitcontainer.hpp b/src/widgets/splitcontainer.hpp index ec04ddc74..00459430d 100644 --- a/src/widgets/splitcontainer.hpp +++ b/src/widgets/splitcontainer.hpp @@ -94,6 +94,7 @@ public: private: Type type; Split *split; + Node *preferedFocusTarget; Node *parent; QRectF geometry; qreal flexH = 1; @@ -175,25 +176,15 @@ public: Position releaseSplit(Split *split); Position deleteSplit(Split *split); + void selectNextSplit(Direction direction); + void decodeFromJson(QJsonObject &obj); - int getSplitCount() - { - return 0; - } - - const std::vector getSplits() const - { - return this->splits; - } - + int getSplitCount(); + const std::vector getSplits() const; void refreshTabTitle(); - NotebookTab *getTab() const; - Node *getBaseNode() - { - return &this->baseNode; - } + Node *getBaseNode(); void setTab(NotebookTab *tab); @@ -235,6 +226,11 @@ private: void layout(); Node baseNode; + Split *selected; + void setSelected(Split *selected); + void selectSplitRecursive(Node *node, Direction direction); + void focusSplitRecursive(Node *node, Direction direction); + void setPreferedTargetRecursive(Node *node); NotebookTab *tab; std::vector splits;