forked from qt-creator/qt-creator
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:
@@ -58,9 +58,8 @@ static inline QString fileNameForPath(const QString &path)
|
|||||||
static QRect cropRectForAreaOfInterest(const QSize &imageSize, const QSize &cropSize, const QRect &areaOfInterest)
|
static QRect cropRectForAreaOfInterest(const QSize &imageSize, const QSize &cropSize, const QRect &areaOfInterest)
|
||||||
{
|
{
|
||||||
QRect result;
|
QRect result;
|
||||||
const qreal cropSizeToAreaSizeFactor = qMin(cropSize.width() / qreal(areaOfInterest.width()),
|
if (areaOfInterest.width() <= cropSize.width()
|
||||||
cropSize.height() / qreal(areaOfInterest.height()));
|
&& areaOfInterest.height() <= cropSize.height()) {
|
||||||
if (cropSizeToAreaSizeFactor >= 1) {
|
|
||||||
const QPoint areaOfInterestCenter = areaOfInterest.center();
|
const QPoint areaOfInterestCenter = areaOfInterest.center();
|
||||||
const int cropX = qBound(0,
|
const int cropX = qBound(0,
|
||||||
areaOfInterestCenter.x() - cropSize.width() / 2,
|
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());
|
const int cropHeight = qMin(imageSize.height(), cropSize.height());
|
||||||
result = QRect(cropX, cropY, cropWidth, cropHeight);
|
result = QRect(cropX, cropY, cropWidth, cropHeight);
|
||||||
} else {
|
} else {
|
||||||
QSize resultSize = cropSize.expandedTo(areaOfInterest.size());
|
QSize resultSize = cropSize.scaled(areaOfInterest.width(), areaOfInterest.height(),
|
||||||
|
Qt::KeepAspectRatioByExpanding);
|
||||||
result = QRect(QPoint(), resultSize);
|
result = QRect(QPoint(), resultSize);
|
||||||
|
result.moveCenter(areaOfInterest.center());
|
||||||
}
|
}
|
||||||
return result;
|
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;
|
QImage result;
|
||||||
if (areaOfInterest.isValid()) {
|
if (area.isValid()) {
|
||||||
const QRect cropRect = cropRectForAreaOfInterest(sourceImage.size(), cropSize, areaOfInterest);
|
const QRect cropRect = Internal::cropRectForAreaOfInterest(sourceImage.size(),
|
||||||
|
cropSize, areaOfInterest);
|
||||||
const QSize cropRectSize = cropRect.size();
|
const QSize cropRectSize = cropRect.size();
|
||||||
result = sourceImage.copy(cropRect);
|
result = sourceImage.copy(cropRect);
|
||||||
if (cropRectSize.width() <= cropSize.width() && cropRectSize.height() <= cropSize.height())
|
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 xmlAttributeWidth = QLatin1String("width");
|
||||||
static const QString xmlAttributeHeight = QLatin1String("height");
|
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;
|
QMap<QString, QRect> areasOfInterest;
|
||||||
QFile xmlFile(areasXmlFile);
|
QFile xmlFile(areasXmlFile);
|
||||||
@@ -146,7 +154,7 @@ QMap<QString, QRect> ScreenshotCropper::loadAreasOfInterest(const QString &areas
|
|||||||
return areasOfInterest;
|
return areasOfInterest;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScreenshotCropper::saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas)
|
bool saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas)
|
||||||
{
|
{
|
||||||
QFile file(areasXmlFile);
|
QFile file(areasXmlFile);
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
if (!file.open(QIODevice::WriteOnly))
|
||||||
@@ -169,5 +177,5 @@ bool ScreenshotCropper::saveAreasOfInterest(const QString &areasXmlFile, QMap<QS
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // ScreenshotCropper
|
||||||
} // namespace QtSupport
|
} // namespace QtSupport
|
||||||
|
@@ -25,20 +25,24 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "qtsupport_global.h"
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
#include <QImage>
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QImage;
|
||||||
|
class QSize;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace QtSupport {
|
namespace QtSupport {
|
||||||
namespace Internal {
|
namespace ScreenshotCropper {
|
||||||
|
|
||||||
class ScreenshotCropper
|
QTSUPPORT_EXPORT QImage croppedImage(const QImage &sourceImage, const QString &filePath,
|
||||||
{
|
const QSize &cropSize, const QRect &areaOfInterest = {});
|
||||||
public:
|
QTSUPPORT_EXPORT QMap<QString, QRect> loadAreasOfInterest(const QString &areasXmlFile);
|
||||||
static QImage croppedImage(const QImage &sourceImage, const QString &filePath, const QSize &cropSize);
|
QTSUPPORT_EXPORT bool saveAreasOfInterest(const QString &areasXmlFile,
|
||||||
static QMap<QString, QRect> loadAreasOfInterest(const QString &areasXmlFile);
|
QMap<QString, QRect> &areas);
|
||||||
static bool saveAreasOfInterest(const QString &areasXmlFile, QMap<QString, QRect> &areas);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // ScreenshotCropper
|
||||||
} // namespace QtSupport
|
} // namespace QtSupport
|
||||||
|
@@ -42,7 +42,7 @@ add_subdirectory(qtc-askpass)
|
|||||||
add_subdirectory(qtcreatorcrashhandler)
|
add_subdirectory(qtcreatorcrashhandler)
|
||||||
# add_subdirectory(qtcreatorwidgets) ## qbs does not build this either
|
# add_subdirectory(qtcreatorwidgets) ## qbs does not build this either
|
||||||
add_subdirectory(qtpromaker)
|
add_subdirectory(qtpromaker)
|
||||||
# add_subdirectory(screenshotcropper) ## qbs does not build this either
|
add_subdirectory(screenshotcropper)
|
||||||
add_subdirectory(sdktool)
|
add_subdirectory(sdktool)
|
||||||
add_subdirectory(valgrindfake)
|
add_subdirectory(valgrindfake)
|
||||||
add_subdirectory(wininterrupt) ## windows only
|
add_subdirectory(wininterrupt) ## windows only
|
||||||
|
@@ -1,22 +1,9 @@
|
|||||||
#
|
add_qtc_executable(screenshotcropper
|
||||||
# Copyright (C) YourCompany. All rights reserved.
|
SKIP_INSTALL
|
||||||
#
|
DEPENDS Qt5::Widgets Utils Core QtSupport
|
||||||
# GENERATED BY CPP-DEPENDENCIES - do not edit, your changes will be lost
|
SOURCES
|
||||||
# If you must edit, remove these two lines to avoid regeneration
|
main.cpp
|
||||||
|
cropimageview.cpp
|
||||||
project(src.tools.screenshotcropper)
|
cropimageview.h
|
||||||
|
screenshotcropperwindow.h screenshotcropperwindow.cpp screenshotcropperwindow.ui
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} STATIC
|
|
||||||
cropimageview.cpp
|
|
||||||
cropimageview.h
|
|
||||||
main.cpp
|
|
||||||
screenshotcropperwindow.cpp
|
|
||||||
screenshotcropperwindow.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
|
||||||
PRIVATE
|
|
||||||
src.plugins.qtsupport
|
|
||||||
)
|
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "cropimageview.h"
|
#include "cropimageview.h"
|
||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
|
||||||
@@ -34,19 +35,18 @@ CropImageView::CropImageView(QWidget *parent)
|
|||||||
|
|
||||||
void CropImageView::mousePressEvent(QMouseEvent *event)
|
void CropImageView::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
setArea(QRect(event->pos(), m_area.bottomRight()));
|
m_initialPoint = event->pos();
|
||||||
update();
|
setEndPoint(m_initialPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CropImageView::mouseMoveEvent(QMouseEvent *event)
|
void CropImageView::mouseMoveEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
setArea(QRect(m_area.topLeft(), event->pos()));
|
setEndPoint(event->pos());
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CropImageView::mouseReleaseEvent(QMouseEvent *event)
|
void CropImageView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
mouseMoveEvent(event);
|
setEndPoint(event->pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CropImageView::setImage(const QImage &image)
|
void CropImageView::setImage(const QImage &image)
|
||||||
@@ -63,6 +63,11 @@ void CropImageView::setArea(const QRect &area)
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CropImageView::setEndPoint(const QPoint &point)
|
||||||
|
{
|
||||||
|
setArea(QRect(m_initialPoint, point));
|
||||||
|
}
|
||||||
|
|
||||||
void CropImageView::paintEvent(QPaintEvent *event)
|
void CropImageView::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event)
|
||||||
|
@@ -41,6 +41,7 @@ public:
|
|||||||
|
|
||||||
void setImage(const QImage &image);
|
void setImage(const QImage &image);
|
||||||
void setArea(const QRect &area);
|
void setArea(const QRect &area);
|
||||||
|
void setEndPoint(const QPoint &point);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void cropAreaChanged(const QRect &area);
|
void cropAreaChanged(const QRect &area);
|
||||||
@@ -48,4 +49,5 @@ signals:
|
|||||||
private:
|
private:
|
||||||
QImage m_image;
|
QImage m_image;
|
||||||
QRect m_area;
|
QRect m_area;
|
||||||
|
QPoint m_initialPoint;
|
||||||
};
|
};
|
||||||
|
@@ -29,8 +29,6 @@
|
|||||||
|
|
||||||
#include "screenshotcropperwindow.h"
|
#include "screenshotcropperwindow.h"
|
||||||
|
|
||||||
using namespace QtSupport::Internal;
|
|
||||||
|
|
||||||
const QString settingsKeyAreasXmlFile = QLatin1String("areasXmlFile");
|
const QString settingsKeyAreasXmlFile = QLatin1String("areasXmlFile");
|
||||||
const QString settingsKeyImagesFolder = QLatin1String("imagesFolder");
|
const QString settingsKeyImagesFolder = QLatin1String("imagesFolder");
|
||||||
|
|
||||||
|
@@ -25,11 +25,13 @@
|
|||||||
|
|
||||||
#include "screenshotcropperwindow.h"
|
#include "screenshotcropperwindow.h"
|
||||||
#include "ui_screenshotcropperwindow.h"
|
#include "ui_screenshotcropperwindow.h"
|
||||||
|
|
||||||
|
#include <coreplugin/welcomepagehelper.h>
|
||||||
|
#include <qtsupport/screenshotcropper.h>
|
||||||
|
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
using namespace QtSupport::Internal;
|
|
||||||
|
|
||||||
ScreenShotCropperWindow::ScreenShotCropperWindow(QWidget *parent)
|
ScreenShotCropperWindow::ScreenShotCropperWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
, ui(new Ui::ScreenShotCropperWindow)
|
, ui(new Ui::ScreenShotCropperWindow)
|
||||||
@@ -51,7 +53,7 @@ void ScreenShotCropperWindow::loadData(const QString &areasXmlFile, const QStrin
|
|||||||
typedef QMap<QString, QRect>::ConstIterator StringRectConstIt;
|
typedef QMap<QString, QRect>::ConstIterator StringRectConstIt;
|
||||||
|
|
||||||
m_areasOfInterestFile = areasXmlFile;
|
m_areasOfInterestFile = areasXmlFile;
|
||||||
m_areasOfInterest = ScreenshotCropper::loadAreasOfInterest(m_areasOfInterestFile);
|
m_areasOfInterest = QtSupport::ScreenshotCropper::loadAreasOfInterest(m_areasOfInterestFile);
|
||||||
m_imagesFolder = imagesFolder;
|
m_imagesFolder = imagesFolder;
|
||||||
const StringRectConstIt cend = m_areasOfInterest.constEnd();
|
const StringRectConstIt cend = m_areasOfInterest.constEnd();
|
||||||
for (StringRectConstIt it = m_areasOfInterest.constBegin(); it != cend; ++it)
|
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();
|
const QListWidgetItem *item = ui->m_filenamesList->currentItem();
|
||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!area.isValid()) {
|
||||||
|
ui->m_previewLabel->setPixmap({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const QString currentFile = item->text();
|
const QString currentFile = item->text();
|
||||||
m_areasOfInterest.insert(currentFile, area);
|
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()
|
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));
|
qFatal("Cannot write %s", qPrintable(m_areasOfInterestFile));
|
||||||
}
|
}
|
||||||
|
@@ -25,11 +25,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <qtsupport/screenshotcropper.h>
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QMap>
|
||||||
using namespace QtSupport::Internal;
|
#include <QRect>
|
||||||
|
|
||||||
namespace Ui { class ScreenShotCropperWindow; }
|
namespace Ui { class ScreenShotCropperWindow; }
|
||||||
|
|
||||||
|
@@ -15,6 +15,13 @@
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<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">
|
<item row="0" column="0">
|
||||||
<widget class="QSplitter" name="splitter">
|
<widget class="QSplitter" name="splitter">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@@ -43,29 +50,39 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>398</width>
|
<width>386</width>
|
||||||
<height>435</height>
|
<height>438</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout">
|
<layout class="QHBoxLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="margin">
|
<property name="margin" stdset="0">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<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>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="0" column="1">
|
||||||
<widget class="QDialogButtonBox" name="m_buttonBox">
|
<widget class="QLabel" name="m_previewLabel">
|
||||||
<property name="standardButtons">
|
<property name="frameShape">
|
||||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Save</set>
|
<enum>QFrame::Box</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
Reference in New Issue
Block a user