164 lines
6.1 KiB
C++
164 lines
6.1 KiB
C++
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
/***************************************************************************
|
|
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
#include <QApplication>
|
|
#include <QEvent>
|
|
#include <QKeyEvent>
|
|
#include <QGraphicsProxyWidget>
|
|
|
|
#include "LineEdit.h"
|
|
#include <Gui/MainWindow.h>
|
|
#include "ZoomableView.h"
|
|
|
|
|
|
using namespace SpreadsheetGui;
|
|
|
|
LineEdit::LineEdit(QWidget* parent)
|
|
: Gui::ExpressionLineEdit(parent, false, '=', true)
|
|
, lastKeyPressed(0)
|
|
{
|
|
setFocusPolicy(Qt::FocusPolicy::ClickFocus);
|
|
}
|
|
|
|
void LineEdit::setDocumentObject(const App::DocumentObject* currentDocObj, bool checkInList)
|
|
{
|
|
ExpressionLineEdit::setDocumentObject(currentDocObj, checkInList);
|
|
|
|
/* The code below is supposed to fix the input of an expression and to make the popup
|
|
* functional. The input seems to be broken because of installed event filters. My solution is
|
|
* to re-add the widget into the scene. Only a parentless widget can be added to the scene.
|
|
* Making a widget parentless makes it lose its windowFlags, even if it is added to the scene.
|
|
* So, the algorithm is to obtain globalPos, then to make the widget parentless,
|
|
* to add it to the scene, setting the globalPos after. */
|
|
|
|
QPointer<Gui::MDIView> active_view = Gui::MainWindow::getInstance()->activeWindow();
|
|
if (!active_view) {
|
|
Base::Console().developerWarning("LineEdit::setDocumentObject",
|
|
"The active view is not a spreadsheet");
|
|
return;
|
|
}
|
|
QPointer<ZoomableView> zv = active_view->findChild<ZoomableView*>();
|
|
if (!zv) {
|
|
Base::Console().developerWarning("LineEdit::setDocumentObject", "ZoomableView not found");
|
|
return;
|
|
}
|
|
|
|
auto getPos = [this]() {
|
|
return this->mapToGlobal(QPoint {0, 0});
|
|
};
|
|
const QPoint old_pos = getPos();
|
|
|
|
auto xpopup = new XListView(this);
|
|
getCompleter()->setPopup(xpopup);
|
|
setParent(nullptr);
|
|
QGraphicsProxyWidget* proxy_lineedit = zv->scene()->addWidget(this);
|
|
|
|
const QPoint new_pos = getPos();
|
|
const QPoint shift = old_pos - new_pos;
|
|
const qreal scale_factor = static_cast<qreal>(zv->zoomLevel()) / 100.0;
|
|
const qreal shift_x = static_cast<qreal>(shift.x()) / scale_factor,
|
|
shift_y = static_cast<qreal>(shift.y()) / scale_factor;
|
|
|
|
QTransform trans = proxy_lineedit->transform();
|
|
proxy_lineedit->setTransform(trans.translate(shift_x, shift_y));
|
|
|
|
|
|
auto getPopupPos = [proxy_lineedit, zv]() {
|
|
const QPointF scene_pos =
|
|
proxy_lineedit->mapToScene(proxy_lineedit->boundingRect().bottomLeft());
|
|
const QPoint view_pos = zv->mapFromScene(scene_pos);
|
|
const QPoint global_pos = zv->viewport()->mapToGlobal(view_pos);
|
|
|
|
return global_pos;
|
|
};
|
|
|
|
auto getPopupWidth = [this, zv]() {
|
|
const int zoom_level = zv->zoomLevel(), editors_width = this->width();
|
|
|
|
return qMax(editors_width * zoom_level / 100, editors_width);
|
|
};
|
|
|
|
auto updatePopupGeom = [getPopupPos, getPopupWidth, xpopup]() {
|
|
const QPoint new_pos = getPopupPos();
|
|
xpopup->setGeometry(new_pos.x(), new_pos.y(), getPopupWidth(), xpopup->height());
|
|
};
|
|
|
|
QObject::connect(xpopup, &XListView::geometryChanged, this, updatePopupGeom);
|
|
}
|
|
|
|
void LineEdit::focusOutEvent(QFocusEvent* event)
|
|
{
|
|
if (lastKeyPressed) {
|
|
Q_EMIT finishedWithKey(lastKeyPressed, lastModifiers);
|
|
}
|
|
|
|
Gui::ExpressionLineEdit::focusOutEvent(event);
|
|
}
|
|
|
|
void LineEdit::keyPressEvent(QKeyEvent* event)
|
|
{
|
|
if (event->key() == Qt::Key::Key_Tab && completerActive()) {
|
|
hideCompleter();
|
|
Gui::ExpressionLineEdit::keyPressEvent(event);
|
|
return;
|
|
}
|
|
|
|
lastKeyPressed = event->key();
|
|
lastModifiers = event->modifiers();
|
|
|
|
if ((lastKeyPressed == Qt::Key::Key_Down || lastKeyPressed == Qt::Key::Key_Up)
|
|
&& completerActive()) {
|
|
auto kevent = new QKeyEvent(QEvent::KeyPress, lastKeyPressed, Qt::NoModifier);
|
|
QCoreApplication::postEvent(getCompleter()->popup(), kevent);
|
|
}
|
|
|
|
Gui::ExpressionLineEdit::keyPressEvent(event);
|
|
}
|
|
|
|
XListView::XListView(LineEdit* parent)
|
|
: QListView(parent)
|
|
{
|
|
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
setAttribute(Qt::WidgetAttribute::WA_ShowWithoutActivating);
|
|
}
|
|
|
|
void XListView::resizeEvent(QResizeEvent* event)
|
|
{
|
|
Q_EMIT geometryChanged();
|
|
QListView::resizeEvent(event);
|
|
}
|
|
|
|
void XListView::updateGeometries()
|
|
{
|
|
QListView::updateGeometries();
|
|
Q_EMIT geometryChanged();
|
|
}
|
|
|
|
#include "moc_LineEdit.cpp"
|