Advance Wayland and KDE package bring-up

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-14 10:51:06 +01:00
parent 51f3c21121
commit cf12defd28
15214 changed files with 20594243 additions and 269 deletions
@@ -0,0 +1,495 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2004 Antonio Larrosa <larrosa@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kpixmapregionselectorwidget.h"
#include <QAction>
#include <QApplication>
#include <QColor>
#include <QCursor>
#include <QHBoxLayout>
#include <QImage>
#include <QLabel>
#include <QMenu>
#include <QMouseEvent>
#include <QPainter>
#include <QRubberBand>
#include <QVBoxLayout>
class KPixmapRegionSelectorWidgetPrivate
{
public:
KPixmapRegionSelectorWidgetPrivate(KPixmapRegionSelectorWidget *qq)
: q(qq)
{
}
KPixmapRegionSelectorWidget *const q;
/**
* Recalculates the pixmap that is shown based on the current selected area,
* the original image, etc.
*/
void updatePixmap();
QRect calcSelectionRectangle(const QPoint &startPoint, const QPoint &endPoint);
enum CursorState { None = 0, Resizing, Moving };
CursorState m_state;
QPixmap m_unzoomedPixmap;
QPixmap m_originalPixmap;
QPixmap m_linedPixmap;
QRect m_selectedRegion;
QLabel *m_label;
QPoint m_tempFirstClick;
double m_forcedAspectRatio;
int m_maxWidth, m_maxHeight;
double m_zoomFactor;
QRubberBand *m_rubberBand;
};
KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget(QWidget *parent)
: QWidget(parent)
, d(new KPixmapRegionSelectorWidgetPrivate(this))
{
QHBoxLayout *hboxLayout = new QHBoxLayout(this);
hboxLayout->addStretch();
QVBoxLayout *vboxLayout = new QVBoxLayout();
hboxLayout->addItem(vboxLayout);
vboxLayout->addStretch();
d->m_label = new QLabel(this);
d->m_label->setAttribute(Qt::WA_NoSystemBackground, true); // setBackgroundMode( Qt::NoBackground );
d->m_label->installEventFilter(this);
vboxLayout->addWidget(d->m_label);
vboxLayout->addStretch();
hboxLayout->addStretch();
d->m_forcedAspectRatio = 0;
d->m_zoomFactor = 1.0;
d->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, d->m_label);
d->m_rubberBand->hide();
}
KPixmapRegionSelectorWidget::~KPixmapRegionSelectorWidget() = default;
QPixmap KPixmapRegionSelectorWidget::pixmap() const
{
return d->m_unzoomedPixmap;
}
void KPixmapRegionSelectorWidget::setPixmap(const QPixmap &pixmap)
{
Q_ASSERT(!pixmap.isNull()); // This class isn't designed to deal with null pixmaps.
d->m_originalPixmap = pixmap;
d->m_unzoomedPixmap = pixmap;
d->m_label->setPixmap(pixmap);
resetSelection();
}
void KPixmapRegionSelectorWidget::resetSelection()
{
d->m_selectedRegion = d->m_originalPixmap.rect();
d->m_rubberBand->hide();
d->updatePixmap();
}
QRect KPixmapRegionSelectorWidget::selectedRegion() const
{
return d->m_selectedRegion;
}
void KPixmapRegionSelectorWidget::setSelectedRegion(const QRect &rect)
{
if (!rect.isValid()) {
resetSelection();
} else {
d->m_selectedRegion = rect;
d->updatePixmap();
}
}
void KPixmapRegionSelectorWidgetPrivate::updatePixmap()
{
Q_ASSERT(!m_originalPixmap.isNull());
if (m_originalPixmap.isNull()) {
m_label->setPixmap(m_originalPixmap);
return;
}
if (m_selectedRegion.width() > m_originalPixmap.width()) {
m_selectedRegion.setWidth(m_originalPixmap.width());
}
if (m_selectedRegion.height() > m_originalPixmap.height()) {
m_selectedRegion.setHeight(m_originalPixmap.height());
}
QPainter painter;
if (m_linedPixmap.isNull()) {
m_linedPixmap = m_originalPixmap;
QPainter p(&m_linedPixmap);
p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
p.fillRect(m_linedPixmap.rect(), QColor(0, 0, 0, 100));
}
QPixmap pixmap = m_linedPixmap;
painter.begin(&pixmap);
painter.drawPixmap(m_selectedRegion.topLeft(), m_originalPixmap, m_selectedRegion);
painter.end();
m_label->setPixmap(pixmap);
qApp->sendPostedEvents(nullptr, QEvent::LayoutRequest);
if (m_selectedRegion == m_originalPixmap.rect()) { // d->m_label->rect()) //### CHECK!
m_rubberBand->hide();
} else {
m_rubberBand->setGeometry(QRect(m_selectedRegion.topLeft(), m_selectedRegion.size()));
/* m_rubberBand->setGeometry(QRect(m_label -> mapToGlobal(m_selectedRegion.topLeft()),
m_selectedRegion.size()));
*/
if (m_state != None) {
m_rubberBand->show();
}
}
}
QMenu *KPixmapRegionSelectorWidget::createPopupMenu()
{
QMenu *popup = new QMenu(this);
popup->setObjectName(QStringLiteral("PixmapRegionSelectorPopup"));
popup->addSection(tr("Image Operations", "@title:menu"));
popup->addAction(QIcon::fromTheme(QStringLiteral("object-rotate-right")),
tr("&Rotate Clockwise", "@action:inmenu"),
this,
&KPixmapRegionSelectorWidget::rotateClockwise);
popup->addAction(QIcon::fromTheme(QStringLiteral("object-rotate-left")),
tr("Rotate &Counterclockwise", "@action:inmenu"),
this,
&KPixmapRegionSelectorWidget::rotateCounterclockwise);
/*
I wonder if it would be appropriate to have here an "Open with..." option to
edit the image (antlarr)
*/
return popup;
}
void KPixmapRegionSelectorWidget::rotate(RotateDirection direction)
{
int w = d->m_originalPixmap.width();
int h = d->m_originalPixmap.height();
QImage img = d->m_unzoomedPixmap.toImage();
if (direction == Rotate90) {
img = img.transformed(QTransform().rotate(90.0));
} else if (direction == Rotate180) {
img = img.transformed(QTransform().rotate(180.0));
} else {
img = img.transformed(QTransform().rotate(270.0));
}
d->m_unzoomedPixmap = QPixmap::fromImage(img);
img = d->m_originalPixmap.toImage();
if (direction == Rotate90) {
img = img.transformed(QTransform().rotate(90.0));
} else if (direction == Rotate180) {
img = img.transformed(QTransform().rotate(180.0));
} else {
img = img.transformed(QTransform().rotate(270.0));
}
d->m_originalPixmap = QPixmap::fromImage(img);
d->m_linedPixmap = QPixmap();
if (d->m_forcedAspectRatio > 0 && d->m_forcedAspectRatio != 1) {
resetSelection();
} else {
switch (direction) {
case (Rotate90): {
int x = h - d->m_selectedRegion.y() - d->m_selectedRegion.height();
int y = d->m_selectedRegion.x();
d->m_selectedRegion.setRect(x, y, d->m_selectedRegion.height(), d->m_selectedRegion.width());
d->updatePixmap();
// qApp->sendPostedEvents(0,QEvent::LayoutRequest);
// updatePixmap();
} break;
case (Rotate270): {
int x = d->m_selectedRegion.y();
int y = w - d->m_selectedRegion.x() - d->m_selectedRegion.width();
d->m_selectedRegion.setRect(x, y, d->m_selectedRegion.height(), d->m_selectedRegion.width());
d->updatePixmap();
// qApp->sendPostedEvents(0,QEvent::LayoutRequest);
// updatePixmap();
} break;
default:
resetSelection();
}
}
Q_EMIT pixmapRotated();
}
void KPixmapRegionSelectorWidget::rotateClockwise()
{
rotate(Rotate90);
}
void KPixmapRegionSelectorWidget::rotateCounterclockwise()
{
rotate(Rotate270);
}
bool KPixmapRegionSelectorWidget::eventFilter(QObject *obj, QEvent *ev)
{
if (ev->type() == QEvent::MouseButtonPress) {
QMouseEvent *mev = (QMouseEvent *)(ev);
// qCDebug(KWidgetsAddonsLog) << QString("click at %1,%2").arg( mev->x() ).arg( mev->y() );
if (mev->button() == Qt::RightButton) {
QMenu *popup = createPopupMenu();
popup->exec(mev->globalPosition().toPoint());
delete popup;
return true;
}
QCursor cursor;
if (d->m_selectedRegion.contains(mev->pos()) && d->m_selectedRegion != d->m_originalPixmap.rect()) {
d->m_state = KPixmapRegionSelectorWidgetPrivate::Moving;
cursor.setShape(Qt::SizeAllCursor);
d->m_rubberBand->show();
} else {
d->m_state = KPixmapRegionSelectorWidgetPrivate::Resizing;
cursor.setShape(Qt::CrossCursor);
}
QApplication::setOverrideCursor(cursor);
d->m_tempFirstClick = mev->pos();
return true;
}
if (ev->type() == QEvent::MouseMove) {
QMouseEvent *mev = (QMouseEvent *)(ev);
// qCDebug(KWidgetsAddonsLog) << QString("move to %1,%2").arg( mev->x() ).arg( mev->y() );
if (d->m_state == KPixmapRegionSelectorWidgetPrivate::Resizing) {
setSelectedRegion(d->calcSelectionRectangle(d->m_tempFirstClick, mev->pos()));
} else if (d->m_state == KPixmapRegionSelectorWidgetPrivate::Moving) {
int mevx = mev->position().x();
int mevy = mev->position().y();
bool mouseOutside = false;
if (mevx < 0) {
d->m_selectedRegion.translate(-d->m_selectedRegion.x(), 0);
mouseOutside = true;
} else if (mevx > d->m_originalPixmap.width()) {
d->m_selectedRegion.translate(d->m_originalPixmap.width() - d->m_selectedRegion.width() - d->m_selectedRegion.x(), 0);
mouseOutside = true;
}
if (mevy < 0) {
d->m_selectedRegion.translate(0, -d->m_selectedRegion.y());
mouseOutside = true;
} else if (mevy > d->m_originalPixmap.height()) {
d->m_selectedRegion.translate(0, d->m_originalPixmap.height() - d->m_selectedRegion.height() - d->m_selectedRegion.y());
mouseOutside = true;
}
if (mouseOutside) {
d->updatePixmap();
return true;
};
d->m_selectedRegion.translate(mev->position().x() - d->m_tempFirstClick.x(), //
mev->position().y() - d->m_tempFirstClick.y());
// Check that the region has not fallen outside the image
if (d->m_selectedRegion.x() < 0) {
d->m_selectedRegion.translate(-d->m_selectedRegion.x(), 0);
} else if (d->m_selectedRegion.right() > d->m_originalPixmap.width()) {
d->m_selectedRegion.translate(-(d->m_selectedRegion.right() - d->m_originalPixmap.width()), 0);
}
if (d->m_selectedRegion.y() < 0) {
d->m_selectedRegion.translate(0, -d->m_selectedRegion.y());
} else if (d->m_selectedRegion.bottom() > d->m_originalPixmap.height()) {
d->m_selectedRegion.translate(0, -(d->m_selectedRegion.bottom() - d->m_originalPixmap.height()));
}
d->m_tempFirstClick = mev->pos();
d->updatePixmap();
}
return true;
}
if (ev->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mev = (QMouseEvent *)(ev);
if (d->m_state == KPixmapRegionSelectorWidgetPrivate::Resizing && mev->pos() == d->m_tempFirstClick) {
resetSelection();
}
d->m_state = KPixmapRegionSelectorWidgetPrivate::None;
QApplication::restoreOverrideCursor();
d->m_rubberBand->hide();
return true;
}
QWidget::eventFilter(obj, ev);
return false;
}
QRect KPixmapRegionSelectorWidgetPrivate::calcSelectionRectangle(const QPoint &startPoint, const QPoint &_endPoint)
{
QPoint endPoint = _endPoint;
if (endPoint.x() < 0) {
endPoint.setX(0);
} else if (endPoint.x() > m_originalPixmap.width()) {
endPoint.setX(m_originalPixmap.width());
}
if (endPoint.y() < 0) {
endPoint.setY(0);
} else if (endPoint.y() > m_originalPixmap.height()) {
endPoint.setY(m_originalPixmap.height());
}
int w = abs(startPoint.x() - endPoint.x());
int h = abs(startPoint.y() - endPoint.y());
if (m_forcedAspectRatio > 0) {
double aspectRatio = w / double(h);
if (aspectRatio > m_forcedAspectRatio) {
h = (int)(w / m_forcedAspectRatio);
} else {
w = (int)(h * m_forcedAspectRatio);
}
}
int x;
int y;
if (startPoint.x() < endPoint.x()) {
x = startPoint.x();
} else {
x = startPoint.x() - w;
}
if (startPoint.y() < endPoint.y()) {
y = startPoint.y();
} else {
y = startPoint.y() - h;
}
if (x < 0) {
w += x;
x = 0;
h = (int)(w / m_forcedAspectRatio);
if (startPoint.y() > endPoint.y()) {
y = startPoint.y() - h;
}
} else if (x + w > m_originalPixmap.width()) {
w = m_originalPixmap.width() - x;
h = (int)(w / m_forcedAspectRatio);
if (startPoint.y() > endPoint.y()) {
y = startPoint.y() - h;
}
}
if (y < 0) {
h += y;
y = 0;
w = (int)(h * m_forcedAspectRatio);
if (startPoint.x() > endPoint.x()) {
x = startPoint.x() - w;
}
} else if (y + h > m_originalPixmap.height()) {
h = m_originalPixmap.height() - y;
w = (int)(h * m_forcedAspectRatio);
if (startPoint.x() > endPoint.x()) {
x = startPoint.x() - w;
}
}
return QRect(x, y, w, h);
}
QRect KPixmapRegionSelectorWidget::unzoomedSelectedRegion() const
{
return QRect((int)(d->m_selectedRegion.x() / d->m_zoomFactor),
(int)(d->m_selectedRegion.y() / d->m_zoomFactor),
(int)(d->m_selectedRegion.width() / d->m_zoomFactor),
(int)(d->m_selectedRegion.height() / d->m_zoomFactor));
}
QImage KPixmapRegionSelectorWidget::selectedImage() const
{
QImage origImage = d->m_unzoomedPixmap.toImage();
return origImage.copy(unzoomedSelectedRegion());
}
void KPixmapRegionSelectorWidget::setSelectionAspectRatio(int width, int height)
{
d->m_forcedAspectRatio = width / double(height);
}
void KPixmapRegionSelectorWidget::setFreeSelectionAspectRatio()
{
d->m_forcedAspectRatio = 0;
}
void KPixmapRegionSelectorWidget::setMaximumWidgetSize(int width, int height)
{
d->m_maxWidth = width;
d->m_maxHeight = height;
if (d->m_selectedRegion == d->m_originalPixmap.rect()) {
d->m_selectedRegion = QRect();
}
d->m_originalPixmap = d->m_unzoomedPixmap;
// qCDebug(KWidgetsAddonsLog) << QString(" original Pixmap :") << d->m_originalPixmap.rect();
// qCDebug(KWidgetsAddonsLog) << QString(" unzoomed Pixmap : %1 x %2 ").arg(d->m_unzoomedPixmap.width()).arg(d->m_unzoomedPixmap.height());
if (!d->m_originalPixmap.isNull() && (d->m_originalPixmap.width() > d->m_maxWidth || d->m_originalPixmap.height() > d->m_maxHeight)) {
/* We have to resize the pixmap to get it complete on the screen */
QImage image = d->m_originalPixmap.toImage();
d->m_originalPixmap = QPixmap::fromImage(image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation));
double oldZoomFactor = d->m_zoomFactor;
d->m_zoomFactor = d->m_originalPixmap.width() / (double)d->m_unzoomedPixmap.width();
if (d->m_selectedRegion.isValid()) {
d->m_selectedRegion = QRect((int)(d->m_selectedRegion.x() * d->m_zoomFactor / oldZoomFactor),
(int)(d->m_selectedRegion.y() * d->m_zoomFactor / oldZoomFactor),
(int)(d->m_selectedRegion.width() * d->m_zoomFactor / oldZoomFactor),
(int)(d->m_selectedRegion.height() * d->m_zoomFactor / oldZoomFactor));
}
}
if (!d->m_selectedRegion.isValid()) {
d->m_selectedRegion = d->m_originalPixmap.rect();
}
d->m_linedPixmap = QPixmap();
d->updatePixmap();
resize(d->m_label->width(), d->m_label->height());
}
#include "moc_kpixmapregionselectorwidget.cpp"