Finishing editation of text field - also 'Comb' functionality

This commit is contained in:
Jakub Melka
2020-05-10 16:41:06 +02:00
parent 691eaff6db
commit 713a7079f8
9 changed files with 405 additions and 59 deletions

View File

@ -1122,6 +1122,7 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
parameters.annotation = annotation.annotation.data(); parameters.annotation = annotation.annotation.data();
parameters.formManager = m_formManager; parameters.formManager = m_formManager;
parameters.key = std::make_pair(annotation.appearance, annotation.annotation->getAppearanceState()); parameters.key = std::make_pair(annotation.appearance, annotation.annotation->getAppearanceState());
parameters.invertColors = m_features.testFlag(PDFRenderer::InvertColors);
annotation.annotation->draw(parameters); annotation.annotation->draw(parameters);
if (parameters.boundingRectangle.isValid()) if (parameters.boundingRectangle.isValid())
@ -1394,15 +1395,19 @@ void PDFWidgetAnnotationManager::keyReleaseEvent(QWidget* widget, QKeyEvent* eve
void PDFWidgetAnnotationManager::mousePressEvent(QWidget* widget, QMouseEvent* event) void PDFWidgetAnnotationManager::mousePressEvent(QWidget* widget, QMouseEvent* event)
{ {
Q_UNUSED(widget); Q_UNUSED(widget);
Q_UNUSED(event);
updateFromMouseEvent(event); updateFromMouseEvent(event);
} }
void PDFWidgetAnnotationManager::mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
}
void PDFWidgetAnnotationManager::mouseReleaseEvent(QWidget* widget, QMouseEvent* event) void PDFWidgetAnnotationManager::mouseReleaseEvent(QWidget* widget, QMouseEvent* event)
{ {
Q_UNUSED(widget); Q_UNUSED(widget);
Q_UNUSED(event);
updateFromMouseEvent(event); updateFromMouseEvent(event);
} }
@ -1410,7 +1415,6 @@ void PDFWidgetAnnotationManager::mouseReleaseEvent(QWidget* widget, QMouseEvent*
void PDFWidgetAnnotationManager::mouseMoveEvent(QWidget* widget, QMouseEvent* event) void PDFWidgetAnnotationManager::mouseMoveEvent(QWidget* widget, QMouseEvent* event)
{ {
Q_UNUSED(widget); Q_UNUSED(widget);
Q_UNUSED(event);
updateFromMouseEvent(event); updateFromMouseEvent(event);
} }

View File

@ -458,6 +458,9 @@ struct AnnotationDrawParameters
/// Appeareance mode (normal/rollover/down, and appearance state) /// Appeareance mode (normal/rollover/down, and appearance state)
PDFAppeareanceStreams::Key key; PDFAppeareanceStreams::Key key;
/// Invert colors?
bool invertColors = false;
}; };
/// Base class for all annotation types. Represents PDF annotation object. /// Base class for all annotation types. Represents PDF annotation object.
@ -1424,6 +1427,7 @@ public:
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override; virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override; virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override;
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override; virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override;
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event) override;
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event) override; virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event) override;
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) override; virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) override;
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override; virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override;

View File

@ -95,6 +95,11 @@ public:
/// \param event Event /// \param event Event
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) = 0; virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) = 0;
/// Handles mouse double click event from widget
/// \param widget Widget
/// \param event Event
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event) = 0;
/// Handles mouse release event from widget /// Handles mouse release event from widget
/// \param widget Widget /// \param widget Widget
/// \param event Event /// \param event Event

View File

@ -384,6 +384,17 @@ void PDFDrawWidgetBase<BaseWidget>::mousePressEvent(QMouseEvent* event)
event->accept(); event->accept();
} }
template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::mouseDoubleClickEvent(QMouseEvent* event)
{
event->ignore();
if (processEvent<QMouseEvent, &IDrawWidgetInputInterface::mouseDoubleClickEvent>(event))
{
return;
}
}
template<typename BaseWidget> template<typename BaseWidget>
void PDFDrawWidgetBase<BaseWidget>::mouseReleaseEvent(QMouseEvent* event) void PDFDrawWidgetBase<BaseWidget>::mouseReleaseEvent(QMouseEvent* event)
{ {

View File

@ -142,6 +142,7 @@ protected:
virtual void keyPressEvent(QKeyEvent* event) override; virtual void keyPressEvent(QKeyEvent* event) override;
virtual void keyReleaseEvent(QKeyEvent* event) override; virtual void keyReleaseEvent(QKeyEvent* event) override;
virtual void mousePressEvent(QMouseEvent* event) override; virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent* event) override; virtual void mouseReleaseEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override; virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void wheelEvent(QWheelEvent* event) override; virtual void wheelEvent(QWheelEvent* event) override;

View File

@ -866,7 +866,7 @@ void PDFFormManager::mousePressEvent(QWidget* widget, QMouseEvent* event)
setFocusToEditor(info.editor); setFocusToEditor(info.editor);
} }
info.editor->mousePressEvent(widget, event); info.editor->mousePressEvent(widget, event, info.mousePosition);
grabMouse(info, event); grabMouse(info, event);
} }
else if (!isMouseGrabbed()) else if (!isMouseGrabbed())
@ -876,6 +876,30 @@ void PDFFormManager::mousePressEvent(QWidget* widget, QMouseEvent* event)
} }
} }
void PDFFormManager::mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event)
{
if (!hasForm())
{
return;
}
MouseEventInfo info = getMouseEventInfo(widget, event->pos());
if (info.isValid())
{
Q_ASSERT(info.editor);
info.editor->mouseDoubleClickEvent(widget, event, info.mousePosition);
// If mouse is grabbed, then event is accepted always (because
// we get Press event, when we grabbed the mouse, then we will
// wait for corresponding release event while all mouse move events
// will be accepted, even if editor doesn't accept them.
if (isMouseGrabbed())
{
event->accept();
}
}
}
void PDFFormManager::mouseReleaseEvent(QWidget* widget, QMouseEvent* event) void PDFFormManager::mouseReleaseEvent(QWidget* widget, QMouseEvent* event)
{ {
if (!hasForm()) if (!hasForm())
@ -887,7 +911,7 @@ void PDFFormManager::mouseReleaseEvent(QWidget* widget, QMouseEvent* event)
if (info.isValid()) if (info.isValid())
{ {
Q_ASSERT(info.editor); Q_ASSERT(info.editor);
info.editor->mouseReleaseEvent(widget, event); info.editor->mouseReleaseEvent(widget, event, info.mousePosition);
ungrabMouse(info, event); ungrabMouse(info, event);
} }
} }
@ -903,7 +927,7 @@ void PDFFormManager::mouseMoveEvent(QWidget* widget, QMouseEvent* event)
if (info.isValid()) if (info.isValid())
{ {
Q_ASSERT(info.editor); Q_ASSERT(info.editor);
info.editor->mouseMoveEvent(widget, event); info.editor->mouseMoveEvent(widget, event, info.mousePosition);
// If mouse is grabbed, then event is accepted always (because // If mouse is grabbed, then event is accepted always (because
// we get Press event, when we grabbed the mouse, then we will // we get Press event, when we grabbed the mouse, then we will
@ -1172,22 +1196,32 @@ void PDFFormFieldWidgetEditor::keyReleaseEvent(QWidget* widget, QKeyEvent* event
Q_UNUSED(event); Q_UNUSED(event);
} }
void PDFFormFieldWidgetEditor::mousePressEvent(QWidget* widget, QMouseEvent* event) void PDFFormFieldWidgetEditor::mousePressEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition)
{ {
Q_UNUSED(widget); Q_UNUSED(widget);
Q_UNUSED(event); Q_UNUSED(event);
Q_UNUSED(mousePagePosition);
} }
void PDFFormFieldWidgetEditor::mouseReleaseEvent(QWidget* widget, QMouseEvent* event) void PDFFormFieldWidgetEditor::mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition)
{ {
Q_UNUSED(widget); Q_UNUSED(widget);
Q_UNUSED(event); Q_UNUSED(event);
Q_UNUSED(mousePagePosition);
} }
void PDFFormFieldWidgetEditor::mouseMoveEvent(QWidget* widget, QMouseEvent* event) void PDFFormFieldWidgetEditor::mouseReleaseEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition)
{ {
Q_UNUSED(widget); Q_UNUSED(widget);
Q_UNUSED(event); Q_UNUSED(event);
Q_UNUSED(mousePagePosition);
}
void PDFFormFieldWidgetEditor::mouseMoveEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition)
{
Q_UNUSED(widget);
Q_UNUSED(event);
Q_UNUSED(mousePagePosition);
} }
void PDFFormFieldWidgetEditor::setFocus(bool hasFocus) void PDFFormFieldWidgetEditor::setFocus(bool hasFocus)
@ -1281,6 +1315,28 @@ PDFFormFieldAbstractButtonEditor::PDFFormFieldAbstractButtonEditor(PDFFormManage
} }
void PDFFormFieldAbstractButtonEditor::shortcutOverrideEvent(QWidget* widget, QKeyEvent* event)
{
Q_UNUSED(widget);
switch (event->key())
{
case Qt::Key_Enter:
case Qt::Key_Return:
case Qt::Key_Left:
case Qt::Key_Right:
case Qt::Key_Up:
case Qt::Key_Down:
{
event->accept();
break;
}
default:
break;
}
}
void PDFFormFieldAbstractButtonEditor::keyPressEvent(QWidget* widget, QKeyEvent* event) void PDFFormFieldAbstractButtonEditor::keyPressEvent(QWidget* widget, QKeyEvent* event)
{ {
switch (event->key()) switch (event->key())
@ -1326,9 +1382,10 @@ void PDFFormFieldAbstractButtonEditor::keyReleaseEvent(QWidget* widget, QKeyEven
} }
} }
void PDFFormFieldAbstractButtonEditor::mousePressEvent(QWidget* widget, QMouseEvent* event) void PDFFormFieldAbstractButtonEditor::mousePressEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition)
{ {
Q_UNUSED(widget); Q_UNUSED(widget);
Q_UNUSED(mousePagePosition);
if (event->button() == Qt::LeftButton) if (event->button() == Qt::LeftButton)
{ {
@ -1464,6 +1521,46 @@ void PDFFormFieldTextBoxEditor::keyPressEvent(QWidget* widget, QKeyEvent* event)
} }
} }
void PDFFormFieldTextBoxEditor::mousePressEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition)
{
if (event->button() == Qt::LeftButton)
{
const int cursorPosition = m_textEdit.getCursorPositionFromWidgetPosition(mousePagePosition, m_hasFocus);
m_textEdit.setCursorPosition(cursorPosition, event->modifiers() & Qt::ShiftModifier);
event->accept();
widget->update();
}
}
void PDFFormFieldTextBoxEditor::mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition)
{
if (event->button() == Qt::LeftButton)
{
const int cursorPosition = m_textEdit.getCursorPositionFromWidgetPosition(mousePagePosition, m_hasFocus);
m_textEdit.setCursorPosition(cursorPosition, false);
m_textEdit.setCursorPosition(m_textEdit.getCursorWordBackward(), false);
m_textEdit.setCursorPosition(m_textEdit.getCursorWordForward(), true);
event->accept();
widget->update();
}
}
void PDFFormFieldTextBoxEditor::mouseMoveEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition)
{
// We must test, if left mouse button is pressed while
// we are moving the mouse - if yes, then select the text.
if (event->buttons() & Qt::LeftButton)
{
const int cursorPosition = m_textEdit.getCursorPositionFromWidgetPosition(mousePagePosition, m_hasFocus);
m_textEdit.setCursorPosition(cursorPosition, true);
event->accept();
widget->update();
}
}
void PDFFormFieldTextBoxEditor::draw(AnnotationDrawParameters& parameters) const void PDFFormFieldTextBoxEditor::draw(AnnotationDrawParameters& parameters) const
{ {
m_textEdit.draw(parameters, true); m_textEdit.draw(parameters, true);
@ -1515,6 +1612,19 @@ void PDFTextEditPseudowidget::shortcutOverrideEvent(QWidget* widget, QKeyEvent*
default: default:
break; break;
} }
if (!event->text().isEmpty())
{
event->accept();
for (const QChar& character : event->text())
{
if (!character.isPrint())
{
event->ignore();
break;
}
}
}
} }
void PDFTextEditPseudowidget::keyPressEvent(QWidget* widget, QKeyEvent* event) void PDFTextEditPseudowidget::keyPressEvent(QWidget* widget, QKeyEvent* event)
@ -1836,6 +1946,7 @@ void PDFTextEditPseudowidget::setAppearance(const PDFAnnotationDefaultAppearance
QFont font(appearance.getFontName()); QFont font(appearance.getFontName());
font.setHintingPreference(QFont::PreferNoHinting); font.setHintingPreference(QFont::PreferNoHinting);
font.setPixelSize(qCeil(fontSize)); font.setPixelSize(qCeil(fontSize));
font.setStyleStrategy(QFont::ForceOutline);
m_textLayout.setFont(font); m_textLayout.setFont(font);
QTextOption option = m_textLayout.textOption(); QTextOption option = m_textLayout.textOption();
@ -1956,56 +2067,232 @@ void PDFTextEditPseudowidget::performInsertText(const QString& text)
updateTextLayout(); updateTextLayout();
} }
QMatrix PDFTextEditPseudowidget::createTextBoxTransformMatrix(bool edit) const
{
QMatrix matrix;
matrix.translate(m_widgetRect.left(), m_widgetRect.bottom());
matrix.scale(1.0, -1.0);
if (edit && !isComb() && m_textLayout.isValidCursorPosition(m_positionCursor))
{
// Jakub Melka: we must scroll the control, so cursor is always
// visible in the widget area. If we are not editing, this not the
// case, because we always show the text from the beginning.
const QTextLine line = m_textLayout.lineForTextPosition(m_positionCursor);
if (line.isValid())
{
const qreal xCursorPosition = line.cursorToX(m_positionCursor);
if (xCursorPosition >= m_widgetRect.width())
{
const qreal delta = xCursorPosition - m_widgetRect.width();
matrix.translate(-delta, 0.0);
}
// Check, if we aren't outside of y position
const qreal lineSpacing = line.leadingIncluded() ? line.height() : line.leading() + line.height();
const qreal lineBottom = lineSpacing * (line.lineNumber() + 1);
if (lineBottom >= m_widgetRect.height())
{
const qreal delta = lineBottom - m_widgetRect.height();
matrix.translate(0.0, -delta);
}
}
}
return matrix;
}
std::vector<int> PDFTextEditPseudowidget::getCursorPositions() const
{
std::vector<int> result;
result.reserve(m_editText.length());
result.push_back(0);
int currentPos = 0;
while (currentPos < m_editText.length())
{
currentPos = m_textLayout.nextCursorPosition(currentPos, QTextLayout::SkipCharacters);
result.push_back(currentPos);
}
return result;
}
void PDFTextEditPseudowidget::draw(AnnotationDrawParameters& parameters, bool edit) const void PDFTextEditPseudowidget::draw(AnnotationDrawParameters& parameters, bool edit) const
{ {
pdf::PDFPainterStateGuard guard(parameters.painter); pdf::PDFPainterStateGuard guard(parameters.painter);
parameters.boundingRectangle = parameters.annotation->getRectangle(); parameters.boundingRectangle = parameters.annotation->getRectangle();
QPainter* painter = parameters.painter; QPalette palette = QApplication::palette();
painter->translate(parameters.boundingRectangle.bottomLeft());
painter->scale(1.0, -1.0);
QVector<QTextLayout::FormatRange> selections; auto getAdjustedColor = [&parameters](QColor color)
QTextLayout::FormatRange defaultFormat;
defaultFormat.start = getPositionStart();
defaultFormat.length = getTextLength();
defaultFormat.format.clearBackground();
defaultFormat.format.setForeground(QBrush(m_textColor, Qt::SolidPattern));
// If we are editing, draw selections
if (edit && isTextSelected())
{ {
QTextLayout::FormatRange before = defaultFormat; if (parameters.invertColors)
QTextLayout::FormatRange after = defaultFormat; {
return invertColor(color);
}
before.start = getPositionStart(); return color;
before.length = m_selectionStart; };
after.start = m_selectionEnd;
after.length = getTextLength() - m_selectionEnd;
QPalette palette = QApplication::palette(); QPainter* painter = parameters.painter;
QTextLayout::FormatRange selectedFormat = defaultFormat; painter->setClipRect(parameters.boundingRectangle, Qt::IntersectClip);
selectedFormat.start = m_selectionStart; painter->setWorldMatrix(createTextBoxTransformMatrix(edit), true);
selectedFormat.length = getSelectionLength(); painter->setPen(getAdjustedColor(Qt::black));
selectedFormat.format.setForeground(palette.brush(QPalette::HighlightedText));
selectedFormat.format.setBackground(palette.brush(QPalette::Highlight));
selections = { before, selectedFormat, after}; if (isComb())
{
const qreal combCount = qMax(m_maxTextLength, 1);
qreal combWidth = m_widgetRect.width() / combCount;
QRectF combRect(0.0, 0.0, combWidth, m_widgetRect.height());
painter->setFont(m_textLayout.font());
QColor textColor = getAdjustedColor(palette.color(QPalette::Text));
QColor highlightTextColor = getAdjustedColor(palette.color(QPalette::HighlightedText));
QColor highlightColor = getAdjustedColor(palette.color(QPalette::Highlight));
std::vector<int> positions = getCursorPositions();
for (size_t i = 1; i < positions.size(); ++i)
{
if (positions[i - 1] >= m_selectionStart && positions[i] - 1 < m_selectionEnd)
{
// We are in text selection
painter->fillRect(combRect, highlightColor);
painter->setPen(highlightTextColor);
}
else
{
// We are not in text selection
painter->setPen(textColor);
}
int length = positions[i] - positions[i - 1];
QString text = m_displayText.mid(positions[i - 1], length);
painter->drawText(combRect, Qt::AlignCenter, text);
// Draw the cursor?
if (edit && m_positionCursor >= positions[i - 1] && m_positionCursor < positions[i])
{
QRectF cursorRect(combRect.left(), combRect.bottom() - 1, combRect.width(), 1);
painter->fillRect(cursorRect, textColor);
}
combRect.translate(combWidth, 0.0);
}
// Draw the cursor onto next unfilled cell?
if (edit && m_positionCursor == getPositionEnd())
{
QRectF cursorRect(combRect.left(), combRect.bottom() - 1, combRect.width(), 1);
painter->fillRect(cursorRect, textColor);
}
} }
else else
{ {
selections.push_back(defaultFormat); QVector<QTextLayout::FormatRange> selections;
QTextLayout::FormatRange defaultFormat;
defaultFormat.start = getPositionStart();
defaultFormat.length = getTextLength();
defaultFormat.format.clearBackground();
defaultFormat.format.setForeground(QBrush(getAdjustedColor(m_textColor), Qt::SolidPattern));
// If we are editing, draw selections
if (edit && isTextSelected())
{
QTextLayout::FormatRange before = defaultFormat;
QTextLayout::FormatRange after = defaultFormat;
before.start = getPositionStart();
before.length = m_selectionStart;
after.start = m_selectionEnd;
after.length = getTextLength() - m_selectionEnd;
QTextLayout::FormatRange selectedFormat = defaultFormat;
selectedFormat.start = m_selectionStart;
selectedFormat.length = getSelectionLength();
selectedFormat.format.setForeground(QBrush(getAdjustedColor(palette.color(QPalette::HighlightedText)), Qt::SolidPattern));
selectedFormat.format.setBackground(QBrush(getAdjustedColor(palette.color(QPalette::Highlight)), Qt::SolidPattern));
selections = { before, selectedFormat, after};
}
else
{
selections.push_back(defaultFormat);
}
// Draw text
m_textLayout.draw(painter, QPointF(0.0, 0.0), selections, QRectF());
// If we are editing, also draw text
if (edit)
{
m_textLayout.drawCursor(painter, QPointF(0.0, 0.0), m_positionCursor);
}
} }
}
// Draw text int PDFTextEditPseudowidget::getCursorPositionFromWidgetPosition(const QPointF& point, bool edit) const
m_textLayout.draw(painter, QPointF(0.0, 0.0), selections, QRectF(0, 0, parameters.boundingRectangle.width(), parameters.boundingRectangle.height())); {
QMatrix textBoxSpaceToPageSpace = createTextBoxTransformMatrix(edit);
QMatrix pageSpaceToTextBoxSpace = textBoxSpaceToPageSpace.inverted();
// If we are editing, also draw text QPointF textBoxPoint = pageSpaceToTextBoxSpace.map(point);
if (edit)
if (isComb())
{ {
m_textLayout.drawCursor(painter, QPointF(0.0, 0.0), m_positionCursor); // If it is comb, then characters are spaced equidistantly
const qreal x = qBound(0.0, textBoxPoint.x(), m_widgetRect.width());
const size_t position = qFloor(x * qreal(m_maxTextLength) / qreal(m_widgetRect.width()));
std::vector<int> positions = getCursorPositions();
if (position < positions.size())
{
return positions[position];
}
return positions.back();
} }
else if (m_textLayout.lineCount() > 0)
{
QTextLine line;
qreal yPos = 0.0;
// Find line under cursor
for (int i = 0; i < m_textLayout.lineCount(); ++i)
{
QTextLine currentLine = m_textLayout.lineAt(i);
const qreal lineSpacing = currentLine.leadingIncluded() ? currentLine.height() : currentLine.leading() + currentLine.height();
const qreal yNextPos = yPos + lineSpacing;
if (textBoxPoint.y() >= yPos && textBoxPoint.y() < yNextPos)
{
line = currentLine;
break;
}
yPos = yNextPos;
}
// If no line is found, select last line
if (!line.isValid())
{
if (textBoxPoint.y() < 0.0)
{
line = m_textLayout.lineAt(0);
}
else
{
line = m_textLayout.lineAt(m_textLayout.lineCount() - 1);
}
}
return line.xToCursor(textBoxPoint.x(), QTextLine::CursorBetweenCharacters);
}
return 0;
} }
void PDFTextEditPseudowidget::updateTextLayout() void PDFTextEditPseudowidget::updateTextLayout()
@ -2049,7 +2336,7 @@ void PDFTextEditPseudowidget::updateTextLayout()
int length = 0; int length = 0;
int currentPos = 0; int currentPos = 0;
while (currentPos <= m_editText.length()) while (currentPos < m_editText.length())
{ {
currentPos = m_textLayout.nextCursorPosition(currentPos, QTextLayout::SkipCharacters); currentPos = m_textLayout.nextCursorPosition(currentPos, QTextLayout::SkipCharacters);
++length; ++length;

View File

@ -517,6 +517,25 @@ public:
/// \param parameters Parameters /// \param parameters Parameters
void draw(AnnotationDrawParameters& parameters, bool edit) const; void draw(AnnotationDrawParameters& parameters, bool edit) const;
/// Returns valid cursor position retrieved from position in the widget.
/// \param point Point in page coordinate space
/// \param edit Are we using edit transformations?
/// \returns Cursor position
int getCursorPositionFromWidgetPosition(const QPointF& point, bool edit) const;
inline int getCursorForward(QTextLayout::CursorMode mode) const { return getNextPrevCursorPosition(getSingleStepForward(), mode); }
inline int getCursorBackward(QTextLayout::CursorMode mode) const { return getNextPrevCursorPosition(getSingleStepBackward(), mode); }
inline int getCursorCharacterForward() const { return getCursorForward(QTextLayout::SkipCharacters); }
inline int getCursorCharacterBackward() const { return getCursorBackward(QTextLayout::SkipCharacters); }
inline int getCursorWordForward() const { return getCursorForward(QTextLayout::SkipWords); }
inline int getCursorWordBackward() const { return getCursorBackward(QTextLayout::SkipWords); }
inline int getCursorDocumentStart() const { return (getSingleStepForward() > 0) ? getPositionStart() : getPositionEnd(); }
inline int getCursorDocumentEnd() const { return (getSingleStepForward() > 0) ? getPositionEnd() : getPositionStart(); }
inline int getCursorLineStart() const { return (getSingleStepForward() > 0) ? getCurrentLineTextStart() : getCurrentLineTextEnd(); }
inline int getCursorLineEnd() const { return (getSingleStepForward() > 0) ? getCurrentLineTextEnd() : getCurrentLineTextStart(); }
inline int getCursorNextLine() const { return getCurrentLineTextEnd(); }
inline int getCursorPreviousLine() const { return getNextPrevCursorPosition(getCurrentLineTextStart(), -1, QTextLayout::SkipCharacters); }
private: private:
/// This function does following things: /// This function does following things:
/// 1) Clamps edit text to fit maximum length /// 1) Clamps edit text to fit maximum length
@ -551,18 +570,16 @@ private:
/// Returns current line text end position /// Returns current line text end position
int getCurrentLineTextEnd() const; int getCurrentLineTextEnd() const;
inline int getCursorForward(QTextLayout::CursorMode mode) const { return getNextPrevCursorPosition(getSingleStepForward(), mode); } /// Creates text box transform matrix, which transforms from
inline int getCursorBackward(QTextLayout::CursorMode mode) const { return getNextPrevCursorPosition(getSingleStepBackward(), mode); } /// widget space to page space.
inline int getCursorCharacterForward() const { return getCursorForward(QTextLayout::SkipCharacters); } /// \param edit Create matrix for text editing?
inline int getCursorCharacterBackward() const { return getCursorBackward(QTextLayout::SkipCharacters); } QMatrix createTextBoxTransformMatrix(bool edit) const;
inline int getCursorWordForward() const { return getCursorForward(QTextLayout::SkipWords); }
inline int getCursorWordBackward() const { return getCursorBackward(QTextLayout::SkipWords); } /// Returns vector of cursor positions (which may be not equal
inline int getCursorDocumentStart() const { return (getSingleStepForward() > 0) ? getPositionStart() : getPositionEnd(); } /// to edit string length, because edit string can contain surrogates,
inline int getCursorDocumentEnd() const { return (getSingleStepForward() > 0) ? getPositionEnd() : getPositionStart(); } /// or graphemes, which are single glyphs, but represented by more
inline int getCursorLineStart() const { return (getSingleStepForward() > 0) ? getCurrentLineTextStart() : getCurrentLineTextEnd(); } /// 16-bit unicode codes).
inline int getCursorLineEnd() const { return (getSingleStepForward() > 0) ? getCurrentLineTextEnd() : getCurrentLineTextStart(); } std::vector<int> getCursorPositions() const;
inline int getCursorNextLine() const { return getCurrentLineTextEnd(); }
inline int getCursorPreviousLine() const { return getNextPrevCursorPosition(getCurrentLineTextStart(), -1, QTextLayout::SkipCharacters); }
int getCursorLineUp() const; int getCursorLineUp() const;
int getCursorLineDown() const; int getCursorLineDown() const;
@ -607,9 +624,10 @@ public:
virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event); virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event);
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event); virtual void keyPressEvent(QWidget* widget, QKeyEvent* event);
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event); virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event);
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event); virtual void mousePressEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event); virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event); virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual bool isEditorDrawEnabled() const { return false; } virtual bool isEditorDrawEnabled() const { return false; }
@ -647,9 +665,10 @@ public:
explicit PDFFormFieldAbstractButtonEditor(PDFFormManager* formManager, PDFFormWidget formWidget, QObject* parent); explicit PDFFormFieldAbstractButtonEditor(PDFFormManager* formManager, PDFFormWidget formWidget, QObject* parent);
virtual ~PDFFormFieldAbstractButtonEditor() = default; virtual ~PDFFormFieldAbstractButtonEditor() = default;
virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event) override;
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override; virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override; virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override;
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override; virtual void mousePressEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition) override;
protected: protected:
virtual void click() = 0; virtual void click() = 0;
@ -701,6 +720,9 @@ public:
virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event); virtual void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event);
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override; virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event, const QPointF& mousePagePosition);
virtual bool isEditorDrawEnabled() const override { return m_hasFocus; } virtual bool isEditorDrawEnabled() const override { return m_hasFocus; }
virtual void draw(AnnotationDrawParameters& parameters) const override; virtual void draw(AnnotationDrawParameters& parameters) const override;
@ -870,6 +892,7 @@ public:
virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override; virtual void keyPressEvent(QWidget* widget, QKeyEvent* event) override;
virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override; virtual void keyReleaseEvent(QWidget* widget, QKeyEvent* event) override;
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override; virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override;
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event) override;
virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event) override; virtual void mouseReleaseEvent(QWidget* widget, QMouseEvent* event) override;
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) override; virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) override;
virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override; virtual void wheelEvent(QWidget* widget, QWheelEvent* event) override;

View File

@ -833,6 +833,12 @@ void PDFToolManager::mousePressEvent(QWidget* widget, QMouseEvent* event)
} }
} }
void PDFToolManager::mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event)
{
Q_UNUSED(widget);
Q_UNUSED(event);
}
void PDFToolManager::mouseReleaseEvent(QWidget* widget, QMouseEvent* event) void PDFToolManager::mouseReleaseEvent(QWidget* widget, QMouseEvent* event)
{ {
event->ignore(); event->ignore();

View File

@ -464,6 +464,11 @@ public:
/// \param event Event /// \param event Event
virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override; virtual void mousePressEvent(QWidget* widget, QMouseEvent* event) override;
/// Handles mouse double click event from widget, over which tool operates
/// \param widget Widget, over which tool operates
/// \param event Event
virtual void mouseDoubleClickEvent(QWidget* widget, QMouseEvent* event) override;
/// Handles mouse release event from widget, over which tool operates /// Handles mouse release event from widget, over which tool operates
/// \param widget Widget, over which tool operates /// \param widget Widget, over which tool operates
/// \param event Event /// \param event Event