mirror of
				https://github.com/JakubMelka/PDF4QT.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			218 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//    Copyright (C) 2022 Jakub Melka
 | 
						|
//
 | 
						|
//    This file is part of PDF4QT.
 | 
						|
//
 | 
						|
//    PDF4QT is free software: you can redistribute it and/or modify
 | 
						|
//    it under the terms of the GNU Lesser General Public License as published by
 | 
						|
//    the Free Software Foundation, either version 3 of the License, or
 | 
						|
//    with the written consent of the copyright owner, any later version.
 | 
						|
//
 | 
						|
//    PDF4QT 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 Lesser General Public License for more details.
 | 
						|
//
 | 
						|
//    You should have received a copy of the GNU Lesser General Public License
 | 
						|
//    along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
#ifndef PDFTEXTEDITPSEUDOWIDGET_H
 | 
						|
#define PDFTEXTEDITPSEUDOWIDGET_H
 | 
						|
 | 
						|
#include "pdfglobal.h"
 | 
						|
#include "pdfform.h"
 | 
						|
 | 
						|
#include <QRectF>
 | 
						|
#include <QColor>
 | 
						|
 | 
						|
class QWidget;
 | 
						|
class QKeyEvent;
 | 
						|
 | 
						|
namespace pdf
 | 
						|
{
 | 
						|
 | 
						|
/// "Pseudo" widget, which is emulating text editor, which can be single line, or multiline.
 | 
						|
/// Passwords can also be edited and editor can be read only.
 | 
						|
class PDFTextEditPseudowidget
 | 
						|
{
 | 
						|
public:
 | 
						|
    explicit PDFTextEditPseudowidget(PDFFormField::FieldFlags flags);
 | 
						|
 | 
						|
    void shortcutOverrideEvent(QWidget* widget, QKeyEvent* event);
 | 
						|
    void keyPressEvent(QWidget* widget, QKeyEvent* event);
 | 
						|
 | 
						|
    inline bool isReadonly() const { return m_flags.testFlag(PDFFormField::ReadOnly); }
 | 
						|
    inline bool isMultiline() const { return m_flags.testFlag(PDFFormField::Multiline); }
 | 
						|
    inline bool isPassword() const { return m_flags.testFlag(PDFFormField::Password); }
 | 
						|
    inline bool isFileSelect() const { return m_flags.testFlag(PDFFormField::FileSelect); }
 | 
						|
    inline bool isComb() const { return m_flags.testFlag(PDFFormField::Comb); }
 | 
						|
 | 
						|
    inline bool isEmpty() const { return m_editText.isEmpty(); }
 | 
						|
    inline bool isTextSelected() const { return !isEmpty() && getSelectionLength() > 0; }
 | 
						|
    inline bool isWholeTextSelected() const { return !isEmpty() && getSelectionLength() == m_editText.length(); }
 | 
						|
 | 
						|
    inline int getTextLength() const { return m_editText.length(); }
 | 
						|
    inline int getSelectionLength() const { return m_selectionEnd - m_selectionStart; }
 | 
						|
 | 
						|
    inline int getPositionCursor() const { return m_positionCursor; }
 | 
						|
    inline int getPositionStart() const { return 0; }
 | 
						|
    inline int getPositionEnd() const { return getTextLength(); }
 | 
						|
 | 
						|
    inline void clearSelection() { m_selectionStart = m_selectionEnd = 0; }
 | 
						|
 | 
						|
    inline const QString& getText() const { return m_editText; }
 | 
						|
    inline QString getSelectedText() const { return m_editText.mid(m_selectionStart, getSelectionLength()); }
 | 
						|
 | 
						|
    /// Sets (updates) text selection
 | 
						|
    /// \param startPosition From where we are selecting text
 | 
						|
    /// \param selectionLength Selection length (positive - to the right, negative - to the left)
 | 
						|
    void setSelection(int startPosition, int selectionLength);
 | 
						|
 | 
						|
    /// Moves cursor position. It behaves as usual in text boxes,
 | 
						|
    /// when user moves the cursor. If \p select is true, then
 | 
						|
    /// selection is updated.
 | 
						|
    /// \param position New position of the cursor
 | 
						|
    /// \param select Select text when moving the cursor?
 | 
						|
    void setCursorPosition(int position, bool select);
 | 
						|
 | 
						|
    /// Sets text content of the widget. This functions sets the text,
 | 
						|
    /// even if widget is readonly.
 | 
						|
    /// \param text Text to be set
 | 
						|
    void setText(const QString& text);
 | 
						|
 | 
						|
    /// Sets widget appearance, such as font, font size, color, text alignment,
 | 
						|
    /// and rectangle, in which widget resides on page (in page coordinates)
 | 
						|
    /// \param appearance Appearance
 | 
						|
    /// \param textAlignment Text alignment
 | 
						|
    /// \param rect Widget rectangle in page coordinates
 | 
						|
    /// \param maxTextLength Maximal text length
 | 
						|
    void setAppearance(const PDFAnnotationDefaultAppearance& appearance,
 | 
						|
                       Qt::Alignment textAlignment,
 | 
						|
                       QRectF rect,
 | 
						|
                       int maxTextLength);
 | 
						|
 | 
						|
    /// Sets widget appearance, such as font, font size, color, text alignment,
 | 
						|
    /// and rectangle, in which widget resides on page (in page coordinates)
 | 
						|
    /// \param font Font
 | 
						|
    /// \param textAlignment Text alignment
 | 
						|
    /// \param rect Widget rectangle in page coordinates
 | 
						|
    /// \param maxTextLength Maximal text length
 | 
						|
    /// \param textColor Color
 | 
						|
    void setAppearance(const QFont& font,
 | 
						|
                       Qt::Alignment textAlignment,
 | 
						|
                       QRectF rect,
 | 
						|
                       int maxTextLength,
 | 
						|
                       QColor textColor);
 | 
						|
 | 
						|
    void performCut();
 | 
						|
    void performCopy();
 | 
						|
    void performPaste();
 | 
						|
    void performClear();
 | 
						|
    void performSelectAll();
 | 
						|
    void performBackspace();
 | 
						|
    void performDelete();
 | 
						|
    void performRemoveSelectedText();
 | 
						|
    void performInsertText(const QString& text);
 | 
						|
 | 
						|
    /// Draw text edit using given parameters
 | 
						|
    /// \param parameters Parameters
 | 
						|
    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); }
 | 
						|
 | 
						|
    const QRectF& getWidgetRect() const { return m_widgetRect; }
 | 
						|
    QFont getFont() const { return m_textLayout.font(); }
 | 
						|
    QColor getFontColor() const { return m_textColor; }
 | 
						|
 | 
						|
private:
 | 
						|
    /// This function does following things:
 | 
						|
    ///     1) Clamps edit text to fit maximum length
 | 
						|
    ///     2) Creates display string from edit string
 | 
						|
    ///     3) Updates text layout
 | 
						|
    void updateTextLayout();
 | 
						|
 | 
						|
    /// Returns single step forward, which is determined
 | 
						|
    /// by cursor move style and layout direction.
 | 
						|
    int getSingleStepForward() const;
 | 
						|
 | 
						|
    /// Returns single step backward, which is determined
 | 
						|
    /// by cursor move style and layout direction.
 | 
						|
    int getSingleStepBackward() const { return -getSingleStepForward(); }
 | 
						|
 | 
						|
    /// Returns next/previous position, by number of steps,
 | 
						|
    /// using given cursor mode (skipping characters or whole words).
 | 
						|
    /// \param steps Number of steps to proceed (can be negative number)
 | 
						|
    /// \param mode Skip mode - letters or words?
 | 
						|
    int getNextPrevCursorPosition(int steps, QTextLayout::CursorMode mode) const { return getNextPrevCursorPosition(m_positionCursor, steps, mode); }
 | 
						|
 | 
						|
    /// Returns next/previous position from reference cursor position, by number of steps,
 | 
						|
    /// using given cursor mode (skipping characters or whole words).
 | 
						|
    /// \param referencePosition Reference cursor position
 | 
						|
    /// \param steps Number of steps to proceed (can be negative number)
 | 
						|
    /// \param mode Skip mode - letters or words?
 | 
						|
    int getNextPrevCursorPosition(int referencePosition, int steps, QTextLayout::CursorMode mode) const;
 | 
						|
 | 
						|
    /// Returns current line text start position
 | 
						|
    int getCurrentLineTextStart() const;
 | 
						|
 | 
						|
    /// Returns current line text end position
 | 
						|
    int getCurrentLineTextEnd() const;
 | 
						|
 | 
						|
    /// Creates text box transform matrix, which transforms from
 | 
						|
    /// widget space to page space.
 | 
						|
    /// \param edit Create matrix for text editing?
 | 
						|
    QMatrix createTextBoxTransformMatrix(bool edit) const;
 | 
						|
 | 
						|
    /// Returns vector of cursor positions (which may be not equal
 | 
						|
    /// to edit string length, because edit string can contain surrogates,
 | 
						|
    /// or graphemes, which are single glyphs, but represented by more
 | 
						|
    /// 16-bit unicode codes).
 | 
						|
    std::vector<int> getCursorPositions() const;
 | 
						|
 | 
						|
    int getCursorLineUp() const;
 | 
						|
    int getCursorLineDown() const;
 | 
						|
 | 
						|
    PDFFormField::FieldFlags m_flags;
 | 
						|
 | 
						|
    /// Text edited by the user
 | 
						|
    QString m_editText;
 | 
						|
 | 
						|
    /// Text, which is displayed. It can differ from text
 | 
						|
    /// edited by user, in case password is being entered.
 | 
						|
    QString m_displayText;
 | 
						|
 | 
						|
    /// Text layout
 | 
						|
    QTextLayout m_textLayout;
 | 
						|
 | 
						|
    /// Character for displaying passwords
 | 
						|
    QChar m_passwordReplacementCharacter;
 | 
						|
 | 
						|
    int m_selectionStart;
 | 
						|
    int m_selectionEnd;
 | 
						|
    int m_positionCursor;
 | 
						|
    int m_maxTextLength;
 | 
						|
 | 
						|
    QRectF m_widgetRect;
 | 
						|
    QColor m_textColor;
 | 
						|
};
 | 
						|
 | 
						|
}   // namespace pdf
 | 
						|
 | 
						|
#endif // PDFTEXTEDITPSEUDOWIDGET_H
 |