/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * */ #include #include #include #include #include #include #include #include #include #include namespace { void lcl_peekFormats(const css::uno::Sequence& rFormats, bool& bHasHtml, bool& bHasImage) { for (int i = 0; i < rFormats.getLength(); ++i) { const css::datatransfer::DataFlavor& rFlavor = rFormats[i]; if (rFlavor.MimeType == "text/html") bHasHtml = true; else if (rFlavor.MimeType.startsWith("image")) bHasImage = true; } } } std::vector Qt5Transferable::getTransferDataFlavorsAsVector() { std::vector aVector; const QClipboard* clipboard = QApplication::clipboard(); const QMimeData* mimeData = clipboard->mimeData(); css::datatransfer::DataFlavor aFlavor; if (mimeData->hasHtml()) { aFlavor.MimeType = "text/html"; aFlavor.DataType = cppu::UnoType>::get(); aVector.push_back(aFlavor); } if (mimeData->hasText()) { aFlavor.MimeType = "text/plain;charset=utf-16"; aFlavor.DataType = cppu::UnoType::get(); aVector.push_back(aFlavor); } if (mimeData->hasImage()) { aFlavor.MimeType = "image/png"; aFlavor.DataType = cppu::UnoType>::get(); aVector.push_back(aFlavor); } return aVector; } css::uno::Sequence SAL_CALL Qt5Transferable::getTransferDataFlavors() { return comphelper::containerToSequence(getTransferDataFlavorsAsVector()); } sal_Bool SAL_CALL Qt5Transferable::isDataFlavorSupported(const css::datatransfer::DataFlavor& /*rFlavor*/) { const std::vector aAll = getTransferDataFlavorsAsVector(); return !aAll.empty(); //FIXME } /* * XTransferable */ css::uno::Any SAL_CALL Qt5Transferable::getTransferData(const css::datatransfer::DataFlavor& rFlavor) { css::uno::Any aRet; const QClipboard* clipboard = QApplication::clipboard(); const QMimeData* mimeData = clipboard->mimeData(); if (rFlavor.MimeType == "text/plain;charset=utf-16") { QString clipboardContent = mimeData->text(); OUString sContent = toOUString(clipboardContent); aRet <<= sContent.replaceAll("\r\n", "\n"); } else if (rFlavor.MimeType == "text/html") { QString clipboardContent = mimeData->html(); std::string aStr = clipboardContent.toStdString(); Sequence aSeq(reinterpret_cast(aStr.c_str()), aStr.length()); aRet <<= aSeq; } else if (rFlavor.MimeType.startsWith("image") && mimeData->hasImage()) { QImage image = qvariant_cast(mimeData->imageData()); QByteArray ba; QBuffer buffer(&ba); sal_Int32 nIndex = rFlavor.MimeType.indexOf('/'); OUString sFormat(nIndex != -1 ? rFlavor.MimeType.copy(nIndex + 1) : "png"); buffer.open(QIODevice::WriteOnly); image.save(&buffer, sFormat.toUtf8().getStr()); Sequence aSeq(reinterpret_cast(ba.data()), ba.size()); aRet <<= aSeq; } return aRet; } VclQt5Clipboard::VclQt5Clipboard() : cppu::WeakComponentImplHelper( m_aMutex) { } void VclQt5Clipboard::flushClipboard() { SolarMutexGuard aGuard; return; } VclQt5Clipboard::~VclQt5Clipboard() {} OUString VclQt5Clipboard::getImplementationName() { return OUString("com.sun.star.datatransfer.VclQt5Clipboard"); } Sequence VclQt5Clipboard::getSupportedServiceNames() { Sequence aRet{ "com.sun.star.datatransfer.clipboard.SystemClipboard" }; return aRet; } sal_Bool VclQt5Clipboard::supportsService(const OUString& ServiceName) { return cppu::supportsService(this, ServiceName); } Reference VclQt5Clipboard::getContents() { if (!m_aContents.is()) m_aContents = new Qt5Transferable; return m_aContents; } void VclQt5Clipboard::setContents( const Reference& xTrans, const Reference& xClipboardOwner) { osl::ClearableMutexGuard aGuard(m_aMutex); Reference xOldOwner(m_aOwner); Reference xOldContents(m_aContents); m_aContents = xTrans; m_aOwner = xClipboardOwner; std::vector> aListeners(m_aListeners); datatransfer::clipboard::ClipboardEvent aEv; if (m_aContents.is()) { css::uno::Sequence aFormats = xTrans->getTransferDataFlavors(); bool bHasHtml = false, bHasImage = false; lcl_peekFormats(aFormats, bHasHtml, bHasImage); css::datatransfer::DataFlavor aFlavor; QClipboard* clipboard = QApplication::clipboard(); if (bHasImage) { //FIXME: other image formats? aFlavor.MimeType = "image/png"; aFlavor.DataType = cppu::UnoType::get(); } else if (bHasHtml) { aFlavor.MimeType = "text/html"; aFlavor.DataType = cppu::UnoType::get(); } else { aFlavor.MimeType = "text/plain;charset=utf-16"; aFlavor.DataType = cppu::UnoType::get(); } Any aValue; try { aValue = xTrans->getTransferData(aFlavor); } catch (...) { } if (aValue.getValueTypeClass() == TypeClass_STRING) { OUString aString; aValue >>= aString; clipboard->setText(toQString(aString)); } else if (aValue.getValueType() == cppu::UnoType>::get()) { Sequence aData; aValue >>= aData; if (bHasHtml) { OUString aHtmlAsString(reinterpret_cast(aData.getConstArray()), aData.getLength(), RTL_TEXTENCODING_UTF8); QMimeData* mimeData = new QMimeData; mimeData->setHtml(toQString(aHtmlAsString)); clipboard->setMimeData(mimeData); } else if (bHasImage) { QImage image; image.loadFromData(reinterpret_cast(aData.getConstArray()), aData.getLength()); clipboard->setImage(image); } } } aEv.Contents = getContents(); aGuard.clear(); if (xOldOwner.is() && xOldOwner != xClipboardOwner) xOldOwner->lostOwnership(this, xOldContents); for (auto const& listener : aListeners) { listener->changedContents(aEv); } } OUString VclQt5Clipboard::getName() { return OUString("CLIPBOARD"); } sal_Int8 VclQt5Clipboard::getRenderingCapabilities() { return 0; } void VclQt5Clipboard::addClipboardListener( const Reference& listener) { osl::ClearableMutexGuard aGuard(m_aMutex); m_aListeners.push_back(listener); } void VclQt5Clipboard::removeClipboardListener( const Reference& listener) { osl::ClearableMutexGuard aGuard(m_aMutex); m_aListeners.erase(std::remove(m_aListeners.begin(), m_aListeners.end(), listener), m_aListeners.end()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */