summaryrefslogtreecommitdiff
path: root/src/gui_qt.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui_qt.cc')
-rw-r--r--src/gui_qt.cc184
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);
+}