QtSupport: Resurrect the "screenshot cropper" tool

After many Years, it is time to refresh "images_areaofinterest.xml".
That is best done with the "screenshot cropper" tool.

Change-Id: Icd07e1c1697e236855d3a03ae8977044d21d78f7
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
Alessandro Portale
2022-01-17 12:29:44 +01:00
parent 795d7364df
commit 77749e6e28
10 changed files with 100 additions and 66 deletions

View File

@@ -58,9 +58,8 @@ static inline QString fileNameForPath(const QString &path)
static QRect cropRectForAreaOfInterest(const QSize &imageSize, const QSize &cropSize, const QRect &areaOfInterest)
{
QRect result;
const qreal cropSizeToAreaSizeFactor = qMin(cropSize.width() / qreal(areaOfInterest.width()),
cropSize.height() / qreal(areaOfInterest.height()));
if (cropSizeToAreaSizeFactor >= 1) {
if (areaOfInterest.width() <= cropSize.width()
&& areaOfInterest.height() <= cropSize.height()) {
const QPoint areaOfInterestCenter = areaOfInterest.center();
const int cropX = qBound(0,
areaOfInterestCenter.x() - cropSize.width() / 2,
@@ -72,19 +71,28 @@ static QRect cropRectForAreaOfInterest(const QSize &imageSize, const QSize &crop
const int cropHeight = qMin(imageSize.height(), cropSize.height());
result = QRect(cropX, cropY, cropWidth, cropHeight);
} else {
QSize resultSize = cropSize.expandedTo(areaOfInterest.size());
QSize resultSize = cropSize.scaled(areaOfInterest.width(), areaOfInterest.height(),
Qt::KeepAspectRatioByExpanding);
result = QRect(QPoint(), resultSize);
result.moveCenter(areaOfInterest.center());
}
return result;
}
QImage ScreenshotCropper::croppedImage(const QImage &sourceImage, const QString &filePath, const QSize &cropSize)
} // namespace Internal
namespace ScreenshotCropper {
QImage croppedImage(const QImage &sourceImage, const QString &filePath, const QSize &cropSize,
const QRect &areaOfInterest)
{
const QRect areaOfInterest = welcomeScreenAreas()->areas.value(fileNameForPath(filePath));
const QRect area = areaOfInterest.isValid() ? areaOfInterest :
Internal::welcomeScreenAreas()->areas.value(Internal::fileNameForPath(filePath));
QImage result;
if (areaOfInterest.isValid()) {
const QRect cropRect = cropRectForAreaOfInterest(sourceImage.size(), cropSize, areaOfInterest);
if (area.isValid()) {
const QRect cropRect = Internal::cropRectForAreaOfInterest(sourceImage.size(),
cropSize, areaOfInterest);
const QSize cropRectSize = cropRect.size();
result = sourceImage.copy(cropRect);
if (cropRectSize.width() <= cropSize.width() && cropRectSize.height() <= cropSize.height())
@@ -115,7 +123,7 @@ static const QString xmlAttributeY = QLatin1String("y");
static const QString xmlAttributeWidth = QLatin1String("width");
static const QString xmlAttributeHeight = QLatin1String("height");
QMap<QString, QRect> ScreenshotCropper::loadAreasOfInterest(const QString &areasXmlFile)
QMap<QString, QRect> loadAreasOfInterest(const QString &areasXmlFile)
{
QMap<QString, QRect> areasOfInterest;
QFile xmlFile(areasXmlFile);
@@ -146,7 +154,7 @@ QMap<QString, QRect> ScreenshotCropper::loadAreasOfInterest(const QString &areas
return areasOfInterest;
}
bool ScreenshotCropper::saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas)
bool saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas)
{
QFile file(areasXmlFile);
if (!file.open(QIODevice::WriteOnly))
@@ -169,5 +177,5 @@ bool ScreenshotCropper::saveAreasOfInterest(const QString &areasXmlFile, QMap<QS
return true;
}
} // namespace Internal
} // ScreenshotCropper
} // namespace QtSupport

View File

@@ -25,20 +25,24 @@
#pragma once
#include "qtsupport_global.h"
#include <QMap>
#include <QRect>
#include <QImage>
QT_BEGIN_NAMESPACE
class QImage;
class QSize;
QT_END_NAMESPACE
namespace QtSupport {
namespace Internal {
namespace ScreenshotCropper {
class ScreenshotCropper
{
public:
static QImage croppedImage(const QImage &sourceImage, const QString &filePath, const QSize &cropSize);
static QMap<QString, QRect> loadAreasOfInterest(const QString &areasXmlFile);
static bool saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas);
};
QTSUPPORT_EXPORT QImage croppedImage(const QImage &sourceImage, const QString &filePath,
const QSize &cropSize, const QRect &areaOfInterest = {});
QTSUPPORT_EXPORT QMap<QString, QRect> loadAreasOfInterest(const QString &areasXmlFile);
QTSUPPORT_EXPORT bool saveAreasOfInterest(const QString &areasXmlFile,
QMap<QString, QRect> &areas);
} // namespace Internal
} // ScreenshotCropper
} // namespace QtSupport

View File

@@ -42,7 +42,7 @@ add_subdirectory(qtc-askpass)
add_subdirectory(qtcreatorcrashhandler)
# add_subdirectory(qtcreatorwidgets) ## qbs does not build this either
add_subdirectory(qtpromaker)
# add_subdirectory(screenshotcropper) ## qbs does not build this either
add_subdirectory(screenshotcropper)
add_subdirectory(sdktool)
add_subdirectory(valgrindfake)
add_subdirectory(wininterrupt) ## windows only

View File

@@ -1,22 +1,9 @@
#
# Copyright (C) YourCompany. All rights reserved.
#
# GENERATED BY CPP-DEPENDENCIES - do not edit, your changes will be lost
# If you must edit, remove these two lines to avoid regeneration
project(src.tools.screenshotcropper)
add_library(${PROJECT_NAME} STATIC
cropimageview.cpp
cropimageview.h
main.cpp
screenshotcropperwindow.cpp
screenshotcropperwindow.h
add_qtc_executable(screenshotcropper
SKIP_INSTALL
DEPENDS Qt5::Widgets Utils Core QtSupport
SOURCES
main.cpp
cropimageview.cpp
cropimageview.h
screenshotcropperwindow.h screenshotcropperwindow.cpp screenshotcropperwindow.ui
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
src.plugins.qtsupport
)

View File

@@ -24,6 +24,7 @@
****************************************************************************/
#include "cropimageview.h"
#include <QPainter>
#include <QMouseEvent>
@@ -34,19 +35,18 @@ CropImageView::CropImageView(QWidget *parent)
void CropImageView::mousePressEvent(QMouseEvent *event)
{
setArea(QRect(event->pos(), m_area.bottomRight()));
update();
m_initialPoint = event->pos();
setEndPoint(m_initialPoint);
}
void CropImageView::mouseMoveEvent(QMouseEvent *event)
{
setArea(QRect(m_area.topLeft(), event->pos()));
update();
setEndPoint(event->pos());
}
void CropImageView::mouseReleaseEvent(QMouseEvent *event)
{
mouseMoveEvent(event);
setEndPoint(event->pos());
}
void CropImageView::setImage(const QImage &image)
@@ -63,6 +63,11 @@ void CropImageView::setArea(const QRect &area)
update();
}
void CropImageView::setEndPoint(const QPoint &point)
{
setArea(QRect(m_initialPoint, point));
}
void CropImageView::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)

View File

@@ -41,6 +41,7 @@ public:
void setImage(const QImage &image);
void setArea(const QRect &area);
void setEndPoint(const QPoint &point);
signals:
void cropAreaChanged(const QRect &area);
@@ -48,4 +49,5 @@ signals:
private:
QImage m_image;
QRect m_area;
QPoint m_initialPoint;
};

View File

@@ -29,8 +29,6 @@
#include "screenshotcropperwindow.h"
using namespace QtSupport::Internal;
const QString settingsKeyAreasXmlFile = QLatin1String("areasXmlFile");
const QString settingsKeyImagesFolder = QLatin1String("imagesFolder");

View File

@@ -25,11 +25,13 @@
#include "screenshotcropperwindow.h"
#include "ui_screenshotcropperwindow.h"
#include <coreplugin/welcomepagehelper.h>
#include <qtsupport/screenshotcropper.h>
#include <QListWidget>
#include <QDebug>
using namespace QtSupport::Internal;
ScreenShotCropperWindow::ScreenShotCropperWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::ScreenShotCropperWindow)
@@ -51,7 +53,7 @@ void ScreenShotCropperWindow::loadData(const QString &areasXmlFile, const QStrin
typedef QMap<QString, QRect>::ConstIterator StringRectConstIt;
m_areasOfInterestFile = areasXmlFile;
m_areasOfInterest = ScreenshotCropper::loadAreasOfInterest(m_areasOfInterestFile);
m_areasOfInterest = QtSupport::ScreenshotCropper::loadAreasOfInterest(m_areasOfInterestFile);
m_imagesFolder = imagesFolder;
const StringRectConstIt cend = m_areasOfInterest.constEnd();
for (StringRectConstIt it = m_areasOfInterest.constBegin(); it != cend; ++it)
@@ -70,12 +72,25 @@ void ScreenShotCropperWindow::setArea(const QRect &area)
const QListWidgetItem *item = ui->m_filenamesList->currentItem();
if (!item)
return;
if (!area.isValid()) {
ui->m_previewLabel->setPixmap({});
return;
}
const QString currentFile = item->text();
m_areasOfInterest.insert(currentFile, area);
const QImage img(m_imagesFolder + QLatin1Char('/') + currentFile);
const QPixmap cropped = QPixmap::fromImage(
QtSupport::ScreenshotCropper::croppedImage(img, currentFile,
Core::ListModel::defaultImageSize,
area));
ui->m_previewLabel->setPixmap(cropped);
}
void ScreenShotCropperWindow::saveData()
{
if (!ScreenshotCropper::saveAreasOfInterest(m_areasOfInterestFile, m_areasOfInterest))
if (!QtSupport::ScreenshotCropper::saveAreasOfInterest(m_areasOfInterestFile,
m_areasOfInterest))
qFatal("Cannot write %s", qPrintable(m_areasOfInterestFile));
}

View File

@@ -25,11 +25,9 @@
#pragma once
#include <qtsupport/screenshotcropper.h>
#include <QMainWindow>
using namespace QtSupport::Internal;
#include <QMap>
#include <QRect>
namespace Ui { class ScreenShotCropperWindow; }

View File

@@ -15,6 +15,13 @@
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QDialogButtonBox" name="m_buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
@@ -43,29 +50,39 @@
<rect>
<x>0</x>
<y>0</y>
<width>398</width>
<height>435</height>
<width>386</width>
<height>438</height>
</rect>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="margin" stdset="0">
<number>0</number>
</property>
<item>
<widget class="CropImageView" name="m_cropImageView" native="true"/>
<widget class="CropImageView" name="m_cropImageView" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QDialogButtonBox" name="m_buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close|QDialogButtonBox::Save</set>
<item row="0" column="1">
<widget class="QLabel" name="m_previewLabel">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>