You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Editor/Clipboard.cpp

136 lines
3.9 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "EditorDefs.h"
#include "Clipboard.h"
#include "Util/Image.h"
#include <QClipboard>
#include <QMessageBox>
#include <QVariant>
XmlNodeRef CClipboard::m_node;
QString CClipboard::m_title;
QVariant CClipboard::s_pendingPut;
//////////////////////////////////////////////////////////////////////////
// Clipboard implementation.
//////////////////////////////////////////////////////////////////////////
CClipboard::CClipboard(QWidget* parent)
: m_parent(parent != nullptr ? parent : QApplication::activeWindow())
{
m_putDebounce.setSingleShot(true);
m_putDebounce.setInterval(0);
// Wait one frame before setting clipboard contents, in case we're updated frequently
QObject::connect(&m_putDebounce, &QTimer::timeout, [this](){SendPendingPut();});
}
void CClipboard::Put(XmlNodeRef& node, const QString& title)
{
m_title = title;
if (m_title.isEmpty())
{
m_title = node->getTag();
}
m_node = node;
PutString(m_node->getXML().c_str(), title);
}
//////////////////////////////////////////////////////////////////////////
XmlNodeRef CClipboard::Get() const
{
QString str = GetString();
return XmlHelpers::LoadXmlFromBuffer(str.toUtf8().data(), str.toUtf8().length(), true);
}
//////////////////////////////////////////////////////////////////////////
void CClipboard::PutString(const QString& text, [[maybe_unused]] const QString& title /* = "" */)
{
s_pendingPut = text;
m_putDebounce.start();
}
//////////////////////////////////////////////////////////////////////////
QString CClipboard::GetString() const
{
if (s_pendingPut.type() == QVariant::String)
{
return s_pendingPut.toString();
}
return QApplication::clipboard()->text();
}
//////////////////////////////////////////////////////////////////////////
bool CClipboard::IsEmpty() const
{
return GetString().isEmpty();
}
//////////////////////////////////////////////////////////////////////////
void CClipboard::PutImage(const CImageEx& img)
{
QImage image(img.GetWidth(), img.GetHeight(), QImage::Format_RGBA8888);
s_pendingPut = image;
m_putDebounce.start();
}
//////////////////////////////////////////////////////////////////////////
bool CClipboard::GetImage(CImageEx& img)
{
QImage image;
if (s_pendingPut.type() == QVariant::Image)
{
image = s_pendingPut.value<QImage>();
}
else
{
image = QApplication::clipboard()->image();
}
img.Allocate(image.width(), image.height());
unsigned char* pSrc = (unsigned char*)image.scanLine(0);
unsigned char* pDst = (unsigned char*)img.GetData();
int stSrc = (image.depth() == 24) ? 3 : 4;
for (int y = 0; y < image.height(); y++)
{
for (int x = 0; x < image.width(); x++)
{
pDst[x * 4 + (image.height() - y - 1) * image.width() * 4] = pSrc[x * stSrc + y * image.bytesPerLine()];
pDst[x * 4 + (image.height() - y - 1) * image.width() * 4 + 1] = pSrc[x * stSrc + y * image.bytesPerLine() + 1];
pDst[x * 4 + (image.height() - y - 1) * image.width() * 4 + 2] = pSrc[x * stSrc + y * image.bytesPerLine() + 2];
pDst[x * 4 + (image.height() - y - 1) * image.width() * 4 + 3] = 0;
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////
void CClipboard::SendPendingPut()
{
if (s_pendingPut.type() == QVariant::String)
{
QString text = s_pendingPut.toString();
QApplication::clipboard()->setText(text);
}
else if (s_pendingPut.type() == QVariant::Image)
{
QImage image = s_pendingPut.value<QImage>();
QApplication::clipboard()->setImage(image);
}
s_pendingPut = {};
}