viewer: use popup for text editor
This commit is contained in:
@@ -248,10 +248,15 @@ bool ViewerDisplayWidget::eventFilter(QObject *o, QEvent *e)
|
||||
|
||||
switch (e->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
if (OnMousePress(static_cast<QMouseEvent*>(e))) {
|
||||
return true;
|
||||
{
|
||||
QMouseEvent *mouse = static_cast<QMouseEvent*>(e);
|
||||
if (!(mouse->flags() & Qt::MouseEventCreatedDoubleClick)) {
|
||||
if (OnMousePress(mouse)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
EmitColorAtCursor(static_cast<QMouseEvent*>(e));
|
||||
if (OnMouseMove(static_cast<QMouseEvent*>(e))) {
|
||||
@@ -656,61 +661,94 @@ void ViewerDisplayWidget::OpenTextGizmo(TextGizmo *text, QMouseEvent *event)
|
||||
{
|
||||
QTransform gizmo_transform = GenerateDisplayTransform();
|
||||
|
||||
ViewerTextEditor *text_edit = new ViewerTextEditor(gizmo_transform.m11(), this);
|
||||
|
||||
text_edit->setWindowFlags(text_edit->windowFlags() | Qt::Tool | Qt::FramelessWindowHint);
|
||||
text_edit->setAttribute(Qt::WA_NoSystemBackground);
|
||||
text_edit->setAttribute(Qt::WA_TranslucentBackground);
|
||||
// Create popup container for text and toolbar
|
||||
auto popup = new QWidget(this);
|
||||
popup->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
|
||||
popup->setAttribute(Qt::WA_DeleteOnClose);
|
||||
popup->setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
// Create text editor
|
||||
ViewerTextEditor *text_edit = new ViewerTextEditor(gizmo_transform.m11(), popup);
|
||||
Html::HtmlToDoc(text_edit->document(), text->GetHtml());
|
||||
text_edit->setProperty("gizmo", reinterpret_cast<quintptr>(text));
|
||||
connect(text_edit, &ViewerTextEditor::textChanged, this, &ViewerDisplayWidget::TextEditChanged);
|
||||
|
||||
QRect transformed_geom = gizmo_transform.map(text->GetRect()).boundingRect().toRect();
|
||||
// Get on screen text rect (this will be the text editor's global geometry)
|
||||
QRect global_text_area = gizmo_transform.map(text->GetRect()).boundingRect().toRect();
|
||||
global_text_area = QRect(mapToGlobal(global_text_area.topLeft()), mapToGlobal(global_text_area.bottomRight()));
|
||||
|
||||
text_edit->setGeometry(QRect(mapToGlobal(transformed_geom.topLeft()), mapToGlobal(transformed_geom.bottomRight())));
|
||||
QRect global_popup_area = global_text_area;
|
||||
|
||||
ViewerTextEditorToolBar *toolbar = new ViewerTextEditorToolBar(this);
|
||||
// Create toolbar
|
||||
ViewerTextEditorToolBar *toolbar = new ViewerTextEditorToolBar(popup);
|
||||
text_edit->ConnectToolBar(toolbar);
|
||||
|
||||
QPoint pos = mapToGlobal(QPoint(transformed_geom.x(), transformed_geom.y() - toolbar->height()));
|
||||
// Work out which corner of the text editor to anchor the toolbar to based on screen limitations
|
||||
bool top = true;
|
||||
bool left = true;
|
||||
for (QScreen *screen : qApp->screens()) {
|
||||
if (screen->geometry().contains(pos)) {
|
||||
if (pos.x() + toolbar->width() > screen->geometry().right()) {
|
||||
pos.setX(screen->geometry().right() - toolbar->width());
|
||||
// Look for screen that contains text area
|
||||
if (screen->geometry().contains(global_text_area)) {
|
||||
if (global_text_area.left() + toolbar->width() > screen->geometry().right()) {
|
||||
left = false;
|
||||
}
|
||||
if (global_text_area.top() - toolbar->height() < screen->geometry().top()) {
|
||||
top = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
toolbar->move(pos);
|
||||
toolbar->show();
|
||||
|
||||
text_edit->show();
|
||||
|
||||
connect(text_edit, &ViewerTextEditor::textChanged, this, &ViewerDisplayWidget::TextEditChanged);
|
||||
QPoint toolbar_pos;
|
||||
|
||||
text_edit->ConnectToolBar(toolbar);
|
||||
if (top) {
|
||||
global_popup_area.adjust(0, -toolbar->height(), 0, 0);
|
||||
toolbar_pos.setY(0);
|
||||
} else {
|
||||
global_popup_area.adjust(0, 0, 0, toolbar->height());
|
||||
toolbar_pos.setY(global_text_area.height());
|
||||
}
|
||||
|
||||
QPoint text_edit_pos;
|
||||
if (toolbar->width() > global_popup_area.width()) {
|
||||
int diff = toolbar->width() - global_popup_area.width();
|
||||
if (left) {
|
||||
global_popup_area.adjust(0, 0, diff, 0);
|
||||
} else {
|
||||
global_popup_area.adjust(-diff, 0, 0, 0);
|
||||
}
|
||||
toolbar_pos.setX(0);
|
||||
} else {
|
||||
if (left) {
|
||||
toolbar_pos.setX(0);
|
||||
} else {
|
||||
toolbar_pos.setX(global_popup_area.width() - toolbar->width());
|
||||
}
|
||||
}
|
||||
|
||||
toolbar->move(toolbar_pos);
|
||||
|
||||
popup->setGeometry(global_popup_area);
|
||||
|
||||
text_edit->setGeometry(QRect(text_edit->mapFromGlobal(global_text_area.topLeft()), text_edit->mapFromGlobal(global_text_area.bottomRight())));
|
||||
|
||||
popup->show();
|
||||
|
||||
// Store click pos from event so we can use it later to set the initial text cursor position
|
||||
QPoint click_pos;
|
||||
if (event) {
|
||||
text_edit_pos = text_edit->mapFrom(this, event->pos());
|
||||
click_pos = event->globalPos();
|
||||
}
|
||||
|
||||
// Ensure text edit is actually focused rather than the toolbar
|
||||
connect(toolbar, &ViewerTextEditorToolBar::FirstPaint, this, [this, text_edit, text_edit_pos]{
|
||||
connect(toolbar, &ViewerTextEditorToolBar::FirstPaint, this, [text_edit, click_pos]{
|
||||
// Grab focus back from the toolbar
|
||||
this->raise();
|
||||
this->activateWindow();
|
||||
text_edit->setFocus();
|
||||
|
||||
// Start text cursor where the user clicked
|
||||
if (!text_edit_pos.isNull()) {
|
||||
text_edit->setTextCursor(text_edit->cursorForPosition(text_edit_pos));
|
||||
if (!click_pos.isNull()) {
|
||||
text_edit->setTextCursor(text_edit->cursorForPosition(text_edit->mapFromGlobal(click_pos)));
|
||||
}
|
||||
|
||||
// HACK: On macOS, for some reason the QDockWidget receives focus before the
|
||||
// ViewerTextEditor, causing the editor to close prematurely. However this only
|
||||
// happens the first time the editor receives focus and not subsequent times, so
|
||||
// if we get it to only listen after the first one, this solves the problem.
|
||||
text_edit->SetListenToFocusEvents(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,6 @@ ViewerTextEditor::ViewerTextEditor(double scale, QWidget *parent) :
|
||||
dpi_force_.setDotsPerMeterY(dpm);
|
||||
document()->documentLayout()->setPaintDevice(&dpi_force_);
|
||||
|
||||
connect(qApp, &QApplication::focusChanged, this, &ViewerTextEditor::FocusChanged);
|
||||
connect(this, &QTextEdit::currentCharFormatChanged, this, &ViewerTextEditor::FormatChanged);
|
||||
connect(document(), &QTextDocument::contentsChanged, this, &ViewerTextEditor::DocumentChanged, Qt::QueuedConnection);
|
||||
|
||||
@@ -70,8 +69,6 @@ ViewerTextEditor::ViewerTextEditor(double scale, QWidget *parent) :
|
||||
|
||||
void ViewerTextEditor::ConnectToolBar(ViewerTextEditorToolBar *toolbar)
|
||||
{
|
||||
connect(this, &ViewerTextEditor::destroyed, toolbar, &ViewerTextEditorToolBar::deleteLater);
|
||||
|
||||
connect(toolbar, &ViewerTextEditorToolBar::FamilyChanged, this, &ViewerTextEditor::SetFamily);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::SizeChanged, this, &ViewerTextEditor::setFontPointSize);
|
||||
connect(toolbar, &ViewerTextEditorToolBar::StyleChanged, this, &ViewerTextEditor::SetStyle);
|
||||
@@ -94,15 +91,6 @@ void ViewerTextEditor::ConnectToolBar(ViewerTextEditorToolBar *toolbar)
|
||||
toolbars_.append(toolbar);
|
||||
}
|
||||
|
||||
void ViewerTextEditor::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
super::keyPressEvent(event);
|
||||
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerTextEditor::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QPainter p(this->viewport());
|
||||
@@ -178,34 +166,6 @@ void ViewerTextEditor::UpdateToolBar(ViewerTextEditorToolBar *toolbar, const QTe
|
||||
toolbar->SetLineHeight(b.lineHeight() == 0.0 ? 100 : b.lineHeight());
|
||||
}
|
||||
|
||||
void ViewerTextEditor::FocusChanged(QWidget *old, QWidget *now)
|
||||
{
|
||||
if (!listen_to_focus_events_) {
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget *test = now;
|
||||
|
||||
if (!test) {
|
||||
// Ignore null focuses because that could be one of the toolbar widgets simply losing focus
|
||||
// and that would be undesirable to close the text editor from
|
||||
return;
|
||||
}
|
||||
|
||||
while (test) {
|
||||
if (test == this
|
||||
|| dynamic_cast<ViewerTextEditorToolBar*>(test)
|
||||
|| dynamic_cast<SliderLadder*>(test)) {
|
||||
return;
|
||||
}
|
||||
|
||||
test = test->parentWidget();
|
||||
}
|
||||
|
||||
// If we didn't return in the loop, the user must have focused on something else
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void ViewerTextEditor::FormatChanged(const QTextCharFormat &f)
|
||||
{
|
||||
if (!block_update_toolbar_signal_) {
|
||||
@@ -325,8 +285,9 @@ void ViewerTextEditor::DocumentChanged()
|
||||
}
|
||||
|
||||
ViewerTextEditorToolBar::ViewerTextEditorToolBar(QWidget *parent) :
|
||||
QWidget(parent, Qt::Tool | Qt::FramelessWindowHint),
|
||||
painted_(false)
|
||||
QWidget(parent),
|
||||
painted_(false),
|
||||
drag_enabled_(false)
|
||||
{
|
||||
QVBoxLayout *outer_layout = new QVBoxLayout(this);
|
||||
outer_layout->setSpacing(0);
|
||||
@@ -511,7 +472,7 @@ void ViewerTextEditorToolBar::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mousePressEvent(event);
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
if (event->button() == Qt::LeftButton && drag_enabled_) {
|
||||
drag_anchor_ = event->pos();
|
||||
}
|
||||
}
|
||||
@@ -520,7 +481,7 @@ void ViewerTextEditorToolBar::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mouseMoveEvent(event);
|
||||
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
if ((event->buttons() & Qt::LeftButton) && drag_enabled_) {
|
||||
this->move(mapToParent(QPoint(event->pos() - drag_anchor_)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,8 @@ private:
|
||||
|
||||
bool painted_;
|
||||
|
||||
bool drag_enabled_;
|
||||
|
||||
private slots:
|
||||
void UpdateFontStyleList(const QString &family);
|
||||
|
||||
@@ -144,8 +146,6 @@ public:
|
||||
void SetListenToFocusEvents(bool e) { listen_to_focus_events_ = e; }
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
@@ -166,8 +166,6 @@ private:
|
||||
bool listen_to_focus_events_;
|
||||
|
||||
private slots:
|
||||
void FocusChanged(QWidget *old, QWidget *now);
|
||||
|
||||
void FormatChanged(const QTextCharFormat &f);
|
||||
|
||||
void SetFamily(const QString &s);
|
||||
|
||||
Reference in New Issue
Block a user