diff options
Diffstat (limited to 'src/gui_qt.cc')
| -rw-r--r-- | src/gui_qt.cc | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/gui_qt.cc b/src/gui_qt.cc index 7aa52d3..cc2ad0d 100644 --- a/src/gui_qt.cc +++ b/src/gui_qt.cc @@ -5,6 +5,7 @@ #include <QAction> #include <QApplication> #include <QClipboard> +#include <QCloseEvent> #include <QDialogButtonBox> #include <QGridLayout> #include <QHeaderView> @@ -44,6 +45,7 @@ #include "gui_main.hh" #include "gui_menu.hh" #include "gui_statusbar.hh" +#include "gui_textwnd.hh" #include "looper.hh" #include "observers.hh" @@ -1098,6 +1100,181 @@ private: bool applied_; }; +class OptionalCloseWidget : public QWidget { +public: + class Delegate { + public: + virtual ~Delegate() {} + + virtual bool about_to_close() = 0; + + protected: + Delegate() {} + }; + + OptionalCloseWidget(QWidget* parent, Delegate* delegate) + : QWidget(parent), delegate_(delegate) { + } + +protected: + void closeEvent(QCloseEvent* event) override { + if (!delegate_->about_to_close()) { + event->ignore(); + return; + } + this->QWidget::closeEvent(event); + } + +private: + Delegate* const delegate_; +}; + +class QtGuiTextWindow : public virtual GuiTextWindow, public QtGuiWindow, + public virtual OptionalCloseWidget::Delegate, + public virtual HtmlAttributedText::Listener { +public: + QtGuiTextWindow(std::string const& title, uint32_t width, uint32_t height, + AttributedText const* text) + : title_(title), width_(width), height_(height), + text_(static_cast<HtmlAttributedText const*>(text)), + widget_(nullptr), view_(nullptr) { + } + + ~QtGuiTextWindow() override { + } + + void set_text(AttributedText const* text) override { + if (!text) { + assert(false); + if (text_own_) text_own_->reset(); + return; + } + disconnect_buffer(); + text_ = static_cast<HtmlAttributedText const*>(text); + connect_buffer(); + text_own_.reset(); + } + + void set_text(std::unique_ptr<AttributedText>&& text) override { + if (!text) { + assert(false); + if (text_own_) text_own_->reset(); + return; + } + disconnect_buffer(); + text_ = static_cast<HtmlAttributedText const*>(text.get()); + connect_buffer(); + text_own_.swap(text); + } + + AttributedText const* text() const override { + return text_; + } + + void add_listener(GuiTextWindow::Listener* listener) override { + observers_.insert(listener); + } + + void remove_listener(GuiTextWindow::Listener* listener) override { + observers_.erase(listener); + } + + void set_title(std::string const& title) override { + title_ = title; + QtGuiWindow::set_title(title); + } + + QWidget* widget() const override { + return widget_.get(); + } + + void* impl() const override { + return QtGuiWindow::impl(); + } + + bool showWidget() override { + show(); + return true; + } + + void show(GuiWindow* UNUSED(parent)) override { + if (widget_) { + focus(); + return; + } + show(); + } + + void focus() override { + if (!widget_) { + assert(false); + show(); + return; + } + widget_->raise(); + widget_->activateWindow(); + } + +private: + void show() { + widget_.reset(new OptionalCloseWidget(nullptr, this)); + widget_->setWindowTitle(QString::fromStdString(title_)); + layout_.reset(new SizeHintLayout(widget_.get(), QSize(width_, height_))); + view_ = new QTextEdit(); + view_->setReadOnly(true); + connect_buffer(); + if (text_) view_->setHtml(QString::fromStdString(text_->html())); + widget_->layout()->addWidget(view_); + widget_->show(); + } + + bool about_to_close() override { + disconnect_buffer(); + auto view = view_; + view_ = nullptr; + auto widget = widget_.release(); + auto it = observers_.notify(); + while (it.has_next()) { + if (!it.next()->about_to_close(this)) { + widget_.reset(widget); + view_ = view; + connect_buffer(); + return false; + } + } + return true; + } + + void changed(HtmlAttributedText* text) override { + assert(text == text_); + if (view_) { + view_->setHtml(QString::fromStdString(text->html())); + view_->moveCursor(QTextCursor::End); + view_->ensureCursorVisible(); + } + } + + void connect_buffer() { + if (!text_ || !view_) return; + const_cast<HtmlAttributedText*>(text_)->add_listener(this); + } + + void disconnect_buffer() { + if (!text_ || !view_) return; + const_cast<HtmlAttributedText*>(text_)->remove_listener(this); + } + + std::string title_; + uint32_t width_; + uint32_t height_; + HtmlAttributedText const* text_; + std::unique_ptr<AttributedText> text_own_; + Observers<GuiTextWindow::Listener*> observers_; + std::unique_ptr<SizeHintLayout> layout_; + std::unique_ptr<QWidget> widget_; + QTextEdit* view_; +}; + bool QtGuiMain::run(int argc, char** argv) { QApplication app(argc, argv); app.setStyleSheet("QStatusBar::item { border: 0px }"); @@ -1322,3 +1499,10 @@ Looper* GuiMain::createLooper() { AttributedText* AttributedText::create() { return HtmlAttributedText::create(); } + +// static +GuiTextWindow* GuiTextWindow::create(std::string const& title, + uint32_t width, uint32_t height, + AttributedText const* text) { + return new QtGuiTextWindow(title, width, height, text); +} |
