Copying text to clipboard

This commit is contained in:
Jakub Melka 2020-01-26 17:48:38 +01:00
parent 12b2f44619
commit 0bc64494fd
4 changed files with 103 additions and 0 deletions

View File

@ -483,6 +483,33 @@ PDFTextSelection PDFTextLayout::createTextSelection(PDFInteger pageIndex, const
return selection;
}
QString PDFTextLayout::getTextFromSelection(PDFTextSelection::iterator itBegin, PDFTextSelection::iterator itEnd, PDFInteger pageIndex) const
{
QStringList text;
if (itBegin != itEnd)
{
PDFTextFlows flows = PDFTextFlow::createTextFlows(*this, PDFTextFlow::RemoveSoftHyphen, pageIndex);
Q_ASSERT(flows.size() < 2);
if (!flows.empty())
{
const PDFTextFlow& textFlow = flows.front();
for (auto it = itBegin; it != itEnd; ++it)
{
text << textFlow.getText(it->start, it->end);
}
}
}
return text.join("\n");
}
QString PDFTextLayout::getTextFromSelection(const PDFTextSelection& selection, PDFInteger pageIndex) const
{
return getTextFromSelection(selection.begin(pageIndex), selection.end(pageIndex), pageIndex);
}
QDataStream& operator>>(QDataStream& stream, PDFTextLayout& layout)
{
stream >> layout.m_characters;
@ -1083,6 +1110,17 @@ PDFTextSelection::iterator PDFTextSelection::end(PDFInteger pageIndex) const
return std::upper_bound(m_items.cbegin(), m_items.end(), item);
}
PDFTextSelection::iterator PDFTextSelection::nextPageRange(iterator currentPageRange) const
{
auto it = currentPageRange;
while (it != m_items.cend() && it->start.pageIndex == currentPageRange->start.pageIndex)
{
++it;
}
return it;
}
PDFFindResults PDFTextFlow::find(const QString& text, Qt::CaseSensitivity caseSensitivity) const
{
PDFFindResults results;
@ -1133,6 +1171,21 @@ PDFFindResults PDFTextFlow::find(const QRegularExpression& expression) const
return results;
}
QString PDFTextFlow::getText(const PDFCharacterPointer& begin, const PDFCharacterPointer& end) const
{
auto it = std::find(m_characterPointers.cbegin(), m_characterPointers.cend(), begin);
auto itEnd = std::find(m_characterPointers.cbegin(), m_characterPointers.cend(), end);
const std::size_t startIndex = std::distance(m_characterPointers.cbegin(), it);
const std::size_t endIndex = std::distance(m_characterPointers.cbegin(), itEnd);
if (startIndex <= endIndex)
{
return m_text.mid(int(startIndex), int(endIndex - startIndex + 1));
}
return QString();
}
void PDFTextFlow::merge(const PDFTextFlow& next)
{
m_text += next.m_text;

View File

@ -238,9 +238,15 @@ public:
/// Returns iterator to end of page range
iterator end(PDFInteger pageIndex) const;
/// Returns iterator to next page range
iterator nextPageRange(iterator currentPageRange) const;
/// Returns true, if text selection is empty
bool isEmpty() const { return m_items.empty(); }
iterator begin() const { return m_items.cbegin(); }
iterator end() const { return m_items.cend(); }
private:
PDFTextSelectionColoredItems m_items;
};
@ -288,6 +294,11 @@ public:
/// \param expression Regular expression to be matched
PDFFindResults find(const QRegularExpression& expression) const;
/// Returns text form character pointers
/// \param begin Begin character
/// \param end End character
QString getText(const PDFCharacterPointer& begin, const PDFCharacterPointer& end) const;
/// Merge data from \p next flow (i.e. connect two consecutive flows)
void merge(const PDFTextFlow& next);
@ -347,6 +358,17 @@ public:
/// \param point2 Second point
PDFTextSelection createTextSelection(PDFInteger pageIndex, const QPointF& point1, const QPointF& point2);
/// Returns string from text selection
/// \param itBegin Iterator (begin range)
/// \param itEnd Iterator (end range)
/// \param pageIndex Index of the page
QString getTextFromSelection(PDFTextSelection::iterator itBegin, PDFTextSelection::iterator itEnd, PDFInteger pageIndex) const;
/// Returns string from text selection
/// \param selection Text selection
/// \param pageIndex Index of the page
QString getTextFromSelection(const PDFTextSelection& selection, PDFInteger pageIndex) const;
friend QDataStream& operator<<(QDataStream& stream, const PDFTextLayout& layout);
friend QDataStream& operator>>(QDataStream& stream, PDFTextLayout& layout);

View File

@ -28,6 +28,8 @@
#include <QKeyEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QClipboard>
#include <QApplication>
namespace pdf
{
@ -602,7 +604,32 @@ void PDFSelectTextTool::updateCursor()
void PDFSelectTextTool::onActionCopyText()
{
if (isActive())
{
// Jakub Melka: we must obey document permissions
if (getDocument()->getStorage().getSecurityHandler()->isAllowed(PDFSecurityHandler::Permission::CopyContent))
{
QStringList result;
auto it = m_textSelection.begin();
auto itEnd = m_textSelection.nextPageRange(it);
while (it != m_textSelection.end())
{
const PDFInteger pageIndex = it->start.pageIndex;
PDFTextLayout textLayout = getProxy()->getTextLayoutCompiler()->getTextLayoutLazy(pageIndex);
result << textLayout.getTextFromSelection(it, itEnd, pageIndex);
it = itEnd;
itEnd = m_textSelection.nextPageRange(it);
}
QString text = result.join("\n\n");
if (!text.isEmpty())
{
QApplication::clipboard()->setText(text, QClipboard::Clipboard);
}
}
}
}
void PDFSelectTextTool::onActionSelectAll()

View File

@ -102,6 +102,7 @@ protected:
virtual void setActiveImpl(bool active);
virtual void updateActions();
const PDFDocument* getDocument() const { return m_document; }
PDFDrawWidgetProxy* getProxy() const { return m_proxy; }
inline void setCursor(QCursor cursor) { m_cursor = qMove(cursor); }