rework ImportDialog and remove ImageCropper
This commit is contained in:
		
							parent
							
								
									23663d389b
								
							
						
					
					
						commit
						d6968792aa
					
				
					 7 changed files with 8 additions and 831 deletions
				
			
		| 
						 | 
				
			
			@ -86,7 +86,6 @@ set(GTA5VIEW_SOURCES
 | 
			
		|||
    src/StringParser.cpp
 | 
			
		||||
    src/TranslationClass.cpp
 | 
			
		||||
    src/UserInterface.cpp
 | 
			
		||||
    src/anpro/imagecropper.cpp
 | 
			
		||||
    src/pcg/pcg_basic.c
 | 
			
		||||
    src/uimod/JSHighlighter.cpp
 | 
			
		||||
    src/uimod/UiModLabel.cpp
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +126,6 @@ set(GTA5VIEW_HEADERS
 | 
			
		|||
    src/StringParser.h
 | 
			
		||||
    src/TranslationClass.h
 | 
			
		||||
    src/UserInterface.h
 | 
			
		||||
    src/anpro/imagecropper.h
 | 
			
		||||
    src/pcg/pcg_basic.h
 | 
			
		||||
    src/uimod/JSHighlighter.h
 | 
			
		||||
    src/uimod/UiModLabel.h
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,6 @@
 | 
			
		|||
#include "SnapmaticPicture.h"
 | 
			
		||||
#include "StandardPaths.h"
 | 
			
		||||
#include "ImportDialog.h"
 | 
			
		||||
#include "imagecropper.h"
 | 
			
		||||
#include "AppEnv.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include <QStringBuilder>
 | 
			
		||||
| 
						 | 
				
			
			@ -86,9 +85,9 @@ ImportDialog::ImportDialog(QString profileName, QWidget *parent) :
 | 
			
		|||
    ui->cbResolution->addItem("GTA V (536p)", QSize(960, 536));
 | 
			
		||||
    ui->cbResolution->addItem("FiveM (1072p)", QSize(1920, 1072));
 | 
			
		||||
    ui->cbResolution->addItem("RDR 2 (1080p)", QSize(1920, 1080));
 | 
			
		||||
    ui->cbResolution->addItem("Preset (720p)", QSize(1280, 720));
 | 
			
		||||
    ui->cbResolution->addItem("Preset (1440p)", QSize(2560, 1440));
 | 
			
		||||
    ui->cbResolution->addItem("Preset (2160p)", QSize(3840, 2160));
 | 
			
		||||
    ui->cbResolution->addItem("HD (720p)", QSize(1280, 720));
 | 
			
		||||
    ui->cbResolution->addItem("WQHD (1440p)", QSize(2560, 1440));
 | 
			
		||||
    ui->cbResolution->addItem("4K/UHD (2160p)", QSize(3840, 2160));
 | 
			
		||||
 | 
			
		||||
    // Set Import Settings
 | 
			
		||||
    QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
 | 
			
		||||
| 
						 | 
				
			
			@ -120,11 +119,10 @@ ImportDialog::ImportDialog(QString profileName, QWidget *parent) :
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
    // Options menu
 | 
			
		||||
    optionsMenu.addAction(tr("&Import new Picture..."), this, SLOT(importNewPicture()));
 | 
			
		||||
    optionsMenu.addAction(tr("&Crop Picture..."), this, SLOT(cropPicture()));
 | 
			
		||||
    optionsMenu.addAction(tr("&Import new Picture..."), this, &ImportDialog::importNewPicture);
 | 
			
		||||
    optionsMenu.addSeparator();
 | 
			
		||||
    optionsMenu.addAction(tr("&Load Settings..."), this, SLOT(loadImportSettings()));
 | 
			
		||||
    optionsMenu.addAction(tr("&Save Settings..."), this, SLOT(saveImportSettings()));
 | 
			
		||||
    optionsMenu.addAction(tr("&Load Settings..."), this, &ImportDialog::loadImportSettings);
 | 
			
		||||
    optionsMenu.addAction(tr("&Save Settings..."), this, &ImportDialog::saveImportSettings);
 | 
			
		||||
    ui->cmdOptions->setMenu(&optionsMenu);
 | 
			
		||||
 | 
			
		||||
    const QSize windowSize = sizeHint();
 | 
			
		||||
| 
						 | 
				
			
			@ -439,72 +437,6 @@ void ImportDialog::saveSettings(QString settingsProfile)
 | 
			
		|||
    settings.endGroup();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImportDialog::cropPicture()
 | 
			
		||||
{
 | 
			
		||||
    qreal screenRatio = AppEnv::screenRatio();
 | 
			
		||||
 | 
			
		||||
    QDialog cropDialog(this);
 | 
			
		||||
#if QT_VERSION >= 0x050000
 | 
			
		||||
    cropDialog.setObjectName(QStringLiteral("CropDialog"));
 | 
			
		||||
#else
 | 
			
		||||
    cropDialog.setObjectName(QString::fromUtf8("CropDialog"));
 | 
			
		||||
#endif
 | 
			
		||||
    cropDialog.setWindowTitle(tr("Crop Picture..."));
 | 
			
		||||
    cropDialog.setWindowFlags(cropDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
 | 
			
		||||
    cropDialog.setModal(true);
 | 
			
		||||
 | 
			
		||||
    QVBoxLayout cropLayout;
 | 
			
		||||
#if QT_VERSION >= 0x050000
 | 
			
		||||
    cropLayout.setObjectName(QStringLiteral("CropLayout"));
 | 
			
		||||
#else
 | 
			
		||||
    cropLayout.setObjectName(QString::fromUtf8("CropLayout"));
 | 
			
		||||
#endif
 | 
			
		||||
    cropLayout.setContentsMargins(0, 0, 0, 0);
 | 
			
		||||
    cropLayout.setSpacing(0);
 | 
			
		||||
    cropDialog.setLayout(&cropLayout);
 | 
			
		||||
 | 
			
		||||
    ImageCropper imageCropper(&cropDialog);
 | 
			
		||||
#if QT_VERSION >= 0x050000
 | 
			
		||||
    imageCropper.setObjectName(QStringLiteral("ImageCropper"));
 | 
			
		||||
#else
 | 
			
		||||
    imageCropper.setObjectName(QString::fromUtf8("ImageCropper"));
 | 
			
		||||
#endif
 | 
			
		||||
    imageCropper.setBackgroundColor(Qt::black);
 | 
			
		||||
    imageCropper.setCroppingRectBorderColor(QColor(255, 255, 255, 127));
 | 
			
		||||
    imageCropper.setImage(QPixmap::fromImage(origImage, Qt::AutoColor));
 | 
			
		||||
    imageCropper.setProportion(QSize(1, 1));
 | 
			
		||||
    imageCropper.setFixedSize(workImage.size());
 | 
			
		||||
    cropLayout.addWidget(&imageCropper);
 | 
			
		||||
 | 
			
		||||
    QHBoxLayout buttonLayout;
 | 
			
		||||
#if QT_VERSION >= 0x050000
 | 
			
		||||
    cropLayout.setObjectName(QStringLiteral("ButtonLayout"));
 | 
			
		||||
#else
 | 
			
		||||
    cropLayout.setObjectName(QString::fromUtf8("ButtonLayout"));
 | 
			
		||||
#endif
 | 
			
		||||
    cropLayout.addLayout(&buttonLayout);
 | 
			
		||||
 | 
			
		||||
    QPushButton cropButton(&cropDialog);
 | 
			
		||||
#if QT_VERSION >= 0x050000
 | 
			
		||||
    cropButton.setObjectName(QStringLiteral("CropButton"));
 | 
			
		||||
#else
 | 
			
		||||
    cropButton.setObjectName(QString::fromUtf8("CropButton"));
 | 
			
		||||
#endif
 | 
			
		||||
    cropButton.setMinimumSize(0, 40 * screenRatio);
 | 
			
		||||
    cropButton.setText(tr("&Crop"));
 | 
			
		||||
    cropButton.setToolTip(tr("Crop Picture"));
 | 
			
		||||
    QObject::connect(&cropButton, SIGNAL(clicked(bool)), &cropDialog, SLOT(accept()));
 | 
			
		||||
 | 
			
		||||
    buttonLayout.addWidget(&cropButton);
 | 
			
		||||
 | 
			
		||||
    cropDialog.show();
 | 
			
		||||
    cropDialog.setFixedSize(cropDialog.sizeHint());
 | 
			
		||||
    if (cropDialog.exec() == QDialog::Accepted) {
 | 
			
		||||
        QImage *croppedImage = new QImage(imageCropper.cropImage().toImage());
 | 
			
		||||
        setImage(croppedImage);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImportDialog::importNewPicture()
 | 
			
		||||
{
 | 
			
		||||
    QSettings settings(GTA5SYNC_APPVENDOR, GTA5SYNC_APPSTR);
 | 
			
		||||
| 
						 | 
				
			
			@ -518,7 +450,7 @@ fileDialogPreOpen: //Work?
 | 
			
		|||
    fileDialog.setViewMode(QFileDialog::Detail);
 | 
			
		||||
    fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
 | 
			
		||||
    fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
 | 
			
		||||
    fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
 | 
			
		||||
    fileDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
 | 
			
		||||
    fileDialog.setWindowTitle(QApplication::translate("ProfileInterface", "Import..."));
 | 
			
		||||
    fileDialog.setLabelText(QFileDialog::Accept, QApplication::translate("ProfileInterface", "Import"));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -824,7 +756,7 @@ fileDialogPreOpen:
 | 
			
		|||
    fileDialog.setViewMode(QFileDialog::Detail);
 | 
			
		||||
    fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
 | 
			
		||||
    fileDialog.setOption(QFileDialog::DontUseNativeDialog, dontUseNativeDialog);
 | 
			
		||||
    fileDialog.setWindowFlags(fileDialog.windowFlags()^Qt::WindowContextHelpButtonHint);
 | 
			
		||||
    fileDialog.setWindowFlag(Qt::WindowContextHelpButtonHint, false);
 | 
			
		||||
    fileDialog.setWindowTitle(QApplication::translate("ProfileInterface", "Import..."));
 | 
			
		||||
    fileDialog.setLabelText(QFileDialog::Accept, QApplication::translate("ProfileInterface", "Import"));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,6 @@ public:
 | 
			
		|||
private slots:
 | 
			
		||||
    void processImage();
 | 
			
		||||
    void reworkImage();
 | 
			
		||||
    void cropPicture();
 | 
			
		||||
    void importNewPicture();
 | 
			
		||||
    void loadImportSettings();
 | 
			
		||||
    void saveImportSettings();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,537 +0,0 @@
 | 
			
		|||
/*****************************************************************************
 | 
			
		||||
* ImageCropper Qt Widget for cropping images
 | 
			
		||||
* Copyright (C) 2013 Dimka Novikov, to@dimkanovikov.pro
 | 
			
		||||
* Copyright (C) 2020 Syping
 | 
			
		||||
*
 | 
			
		||||
* This library is free software; you can redistribute it and/or
 | 
			
		||||
* modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
* License as published by the Free Software Foundation; either
 | 
			
		||||
* version 3 of the License, or any later version.
 | 
			
		||||
*
 | 
			
		||||
* This library is distributed in the hope that it will be useful,
 | 
			
		||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
* Lesser General Public License for more details.
 | 
			
		||||
*
 | 
			
		||||
* You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "imagecropper.h"
 | 
			
		||||
#include "AppEnv.h"
 | 
			
		||||
 | 
			
		||||
#include <QPainterPath>
 | 
			
		||||
#include <QMouseEvent>
 | 
			
		||||
#include <QPainter>
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
    static const QSize WIDGET_MINIMUM_SIZE(470, 470);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ImageCropper::ImageCropper(QWidget* parent) :
 | 
			
		||||
	QWidget(parent),
 | 
			
		||||
	pimpl(new ImageCropperPrivate)
 | 
			
		||||
{
 | 
			
		||||
	setMinimumSize(WIDGET_MINIMUM_SIZE);
 | 
			
		||||
	setMouseTracking(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ImageCropper::~ImageCropper()
 | 
			
		||||
{
 | 
			
		||||
	delete pimpl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::setImage(const QPixmap& _image)
 | 
			
		||||
{
 | 
			
		||||
	pimpl->imageForCropping = _image;
 | 
			
		||||
	update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::setBackgroundColor(const QColor& _backgroundColor)
 | 
			
		||||
{
 | 
			
		||||
	pimpl->backgroundColor = _backgroundColor;
 | 
			
		||||
	update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::setCroppingRectBorderColor(const QColor& _borderColor)
 | 
			
		||||
{
 | 
			
		||||
	pimpl->croppingRectBorderColor = _borderColor;
 | 
			
		||||
	update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::setProportion(const QSizeF& _proportion)
 | 
			
		||||
{
 | 
			
		||||
	// Пропорции хранятся в коэффициентах приращения сторон
 | 
			
		||||
	// Таким образом, при изменении размера области выделения,
 | 
			
		||||
	// размеры сторон изменяются на размер зависящий от
 | 
			
		||||
	// коэффициентов приращения.
 | 
			
		||||
 | 
			
		||||
	// Сохраним пропорциональную зависимость области выделения в коэффициентах приращения сторон
 | 
			
		||||
	if (pimpl->proportion != _proportion) {
 | 
			
		||||
		pimpl->proportion = _proportion;
 | 
			
		||||
		// ... расчитаем коэффициенты
 | 
			
		||||
		float heightDelta = (float)_proportion.height() / _proportion.width();
 | 
			
		||||
		float widthDelta = (float)_proportion.width() / _proportion.height();
 | 
			
		||||
		// ... сохраним коэффициенты
 | 
			
		||||
		pimpl->deltas.setHeight(heightDelta);
 | 
			
		||||
		pimpl->deltas.setWidth(widthDelta);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Обновим пропорции области выделения
 | 
			
		||||
	if ( pimpl->isProportionFixed ) {
 | 
			
		||||
		float croppintRectSideRelation =
 | 
			
		||||
				(float)pimpl->croppingRect.width() / pimpl->croppingRect.height();
 | 
			
		||||
		float proportionSideRelation =
 | 
			
		||||
				(float)pimpl->proportion.width() / pimpl->proportion.height();
 | 
			
		||||
		// Если область выделения не соответствует необходимым пропорциям обновим её
 | 
			
		||||
		if (croppintRectSideRelation != proportionSideRelation) {
 | 
			
		||||
			bool widthShotrerThenHeight =
 | 
			
		||||
					pimpl->croppingRect.width() < pimpl->croppingRect.height();
 | 
			
		||||
			// ... установим размер той стороны, что длиннее
 | 
			
		||||
			if (widthShotrerThenHeight) {
 | 
			
		||||
				pimpl->croppingRect.setHeight(
 | 
			
		||||
							pimpl->croppingRect.width() * pimpl->deltas.height());
 | 
			
		||||
			} else {
 | 
			
		||||
				pimpl->croppingRect.setWidth(
 | 
			
		||||
							pimpl->croppingRect.height() * pimpl->deltas.width());
 | 
			
		||||
			}
 | 
			
		||||
			// ... перерисуем виджет
 | 
			
		||||
			update();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::setProportionFixed(const bool _isFixed)
 | 
			
		||||
{
 | 
			
		||||
	if (pimpl->isProportionFixed != _isFixed) {
 | 
			
		||||
		pimpl->isProportionFixed = _isFixed;
 | 
			
		||||
		setProportion(pimpl->proportion);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QPixmap ImageCropper::cropImage()
 | 
			
		||||
{
 | 
			
		||||
	// Получим размер отображаемого изображения
 | 
			
		||||
	QSize scaledImageSize =
 | 
			
		||||
			pimpl->imageForCropping.scaled(
 | 
			
		||||
                size(), Qt::KeepAspectRatio, Qt::SmoothTransformation
 | 
			
		||||
				).size();
 | 
			
		||||
	// Определим расстояние от левого и верхнего краёв
 | 
			
		||||
	float leftDelta = 0;
 | 
			
		||||
	float topDelta = 0;
 | 
			
		||||
	const float HALF_COUNT = 2;
 | 
			
		||||
    if (size().height() == scaledImageSize.height()) {
 | 
			
		||||
        leftDelta = (width() - scaledImageSize.width()) / HALF_COUNT;
 | 
			
		||||
	} else {
 | 
			
		||||
        topDelta = (height() - scaledImageSize.height()) / HALF_COUNT;
 | 
			
		||||
	}
 | 
			
		||||
	// Определим пропорцию области обрезки по отношению к исходному изображению
 | 
			
		||||
	float xScale = (float)pimpl->imageForCropping.width()  / scaledImageSize.width();
 | 
			
		||||
	float yScale = (float)pimpl->imageForCropping.height() / scaledImageSize.height();
 | 
			
		||||
	// Расчитаем область обрезки с учётом коррекции размеров исходного изображения
 | 
			
		||||
	QRectF realSizeRect(
 | 
			
		||||
				QPointF(pimpl->croppingRect.left() - leftDelta, pimpl->croppingRect.top() - topDelta),
 | 
			
		||||
				pimpl->croppingRect.size());
 | 
			
		||||
	// ... корректируем левый и верхний края
 | 
			
		||||
	realSizeRect.setLeft((pimpl->croppingRect.left() - leftDelta) * xScale);
 | 
			
		||||
	realSizeRect.setTop ((pimpl->croppingRect.top() - topDelta) * yScale);
 | 
			
		||||
	// ... корректируем размер
 | 
			
		||||
	realSizeRect.setWidth(pimpl->croppingRect.width() * xScale);
 | 
			
		||||
	realSizeRect.setHeight(pimpl->croppingRect.height() * yScale);
 | 
			
		||||
	// Получаем обрезанное изображение
 | 
			
		||||
	return pimpl->imageForCropping.copy(realSizeRect.toRect());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ********
 | 
			
		||||
// Protected section
 | 
			
		||||
 | 
			
		||||
void ImageCropper::paintEvent(QPaintEvent* _event)
 | 
			
		||||
{
 | 
			
		||||
    QWidget::paintEvent(_event);
 | 
			
		||||
	//
 | 
			
		||||
	QPainter widgetPainter(this);
 | 
			
		||||
	// Рисуем изображение по центру виджета
 | 
			
		||||
	{
 | 
			
		||||
#if QT_VERSION >= 0x050600
 | 
			
		||||
        qreal screenRatioPR = AppEnv::screenRatioPR();
 | 
			
		||||
		// ... подгоним изображение для отображения по размеру виджета
 | 
			
		||||
		QPixmap scaledImage =
 | 
			
		||||
                pimpl->imageForCropping.scaled(qRound((double)width() * screenRatioPR), qRound((double)height() * screenRatioPR), Qt::KeepAspectRatio, Qt::SmoothTransformation);
 | 
			
		||||
        scaledImage.setDevicePixelRatio(screenRatioPR);
 | 
			
		||||
#else
 | 
			
		||||
        QPixmap scaledImage =
 | 
			
		||||
                pimpl->imageForCropping.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
 | 
			
		||||
#endif
 | 
			
		||||
		// ... заливаем фон
 | 
			
		||||
        widgetPainter.fillRect(rect(), pimpl->backgroundColor);
 | 
			
		||||
		// ... рисуем изображение по центру виджета
 | 
			
		||||
#if QT_VERSION >= 0x050600
 | 
			
		||||
        if (qRound((double)height() * screenRatioPR) == scaledImage.height()) {
 | 
			
		||||
            widgetPainter.drawPixmap( ( qRound((double)width() * screenRatioPR) - scaledImage.width() ) / 2, 0, scaledImage );
 | 
			
		||||
		} else {
 | 
			
		||||
            widgetPainter.drawPixmap( 0, ( qRound((double)height() * screenRatioPR) - scaledImage.height() ) / 2, scaledImage );
 | 
			
		||||
		}
 | 
			
		||||
#else
 | 
			
		||||
        if (height() == scaledImage.height()) {
 | 
			
		||||
            widgetPainter.drawPixmap( ( width()- scaledImage.width() ) / 2, 0, scaledImage );
 | 
			
		||||
        } else {
 | 
			
		||||
            widgetPainter.drawPixmap( 0, ( height() - scaledImage.height() ) / 2, scaledImage );
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
	// Рисуем область обрезки
 | 
			
		||||
	{
 | 
			
		||||
		// ... если это первое отображение после инициилизации, то центруем областо обрезки
 | 
			
		||||
		if (pimpl->croppingRect.isNull()) {
 | 
			
		||||
            const int cwidth = WIDGET_MINIMUM_SIZE.width()/2;
 | 
			
		||||
            const int cheight = WIDGET_MINIMUM_SIZE.height()/2;
 | 
			
		||||
            pimpl->croppingRect.setSize(QSize(cwidth, cheight));
 | 
			
		||||
            float x = (width() - pimpl->croppingRect.width())/2;
 | 
			
		||||
            float y = (height() - pimpl->croppingRect.height())/2;
 | 
			
		||||
			pimpl->croppingRect.moveTo(x, y);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// ... рисуем затемненную область
 | 
			
		||||
		QPainterPath p;
 | 
			
		||||
		p.addRect(pimpl->croppingRect);
 | 
			
		||||
        p.addRect(rect());
 | 
			
		||||
		widgetPainter.setBrush(QBrush(QColor(0,0,0,120)));
 | 
			
		||||
		widgetPainter.setPen(Qt::transparent);
 | 
			
		||||
		widgetPainter.drawPath(p);
 | 
			
		||||
		// Рамка и контрольные точки
 | 
			
		||||
		widgetPainter.setPen(pimpl->croppingRectBorderColor);
 | 
			
		||||
		// ... рисуем прямоугольник области обрезки
 | 
			
		||||
		{
 | 
			
		||||
			widgetPainter.setBrush(QBrush(Qt::transparent));
 | 
			
		||||
			widgetPainter.drawRect(pimpl->croppingRect);
 | 
			
		||||
		}
 | 
			
		||||
		// ... рисуем контрольные точки
 | 
			
		||||
		{
 | 
			
		||||
			widgetPainter.setBrush(QBrush(pimpl->croppingRectBorderColor));
 | 
			
		||||
			// Вспомогательные X координаты
 | 
			
		||||
			int leftXCoord   = pimpl->croppingRect.left() - 2;
 | 
			
		||||
			int centerXCoord = pimpl->croppingRect.center().x() - 3;
 | 
			
		||||
			int rightXCoord  = pimpl->croppingRect.right() - 2;
 | 
			
		||||
			// Вспомогательные Y координаты
 | 
			
		||||
			int topYCoord    = pimpl->croppingRect.top() - 2;
 | 
			
		||||
			int middleYCoord = pimpl->croppingRect.center().y() - 3;
 | 
			
		||||
			int bottomYCoord = pimpl->croppingRect.bottom() - 2;
 | 
			
		||||
			//
 | 
			
		||||
			const QSize pointSize(6, 6);
 | 
			
		||||
			//
 | 
			
		||||
			QVector<QRect> points;
 | 
			
		||||
			points
 | 
			
		||||
					// левая сторона
 | 
			
		||||
					<< QRect( QPoint(leftXCoord, topYCoord), pointSize )
 | 
			
		||||
					<< QRect( QPoint(leftXCoord, middleYCoord), pointSize )
 | 
			
		||||
					<< QRect( QPoint(leftXCoord, bottomYCoord), pointSize )
 | 
			
		||||
					// центр
 | 
			
		||||
					<< QRect( QPoint(centerXCoord, topYCoord), pointSize )
 | 
			
		||||
					<< QRect( QPoint(centerXCoord, middleYCoord), pointSize )
 | 
			
		||||
					<< QRect( QPoint(centerXCoord, bottomYCoord), pointSize )
 | 
			
		||||
					// правая сторона
 | 
			
		||||
					<< QRect( QPoint(rightXCoord, topYCoord), pointSize )
 | 
			
		||||
					<< QRect( QPoint(rightXCoord, middleYCoord), pointSize )
 | 
			
		||||
					<< QRect( QPoint(rightXCoord, bottomYCoord), pointSize );
 | 
			
		||||
			//
 | 
			
		||||
			widgetPainter.drawRects( points );
 | 
			
		||||
		}
 | 
			
		||||
		// ... рисуем пунктирные линии
 | 
			
		||||
		{
 | 
			
		||||
			QPen dashPen(pimpl->croppingRectBorderColor);
 | 
			
		||||
			dashPen.setStyle(Qt::DashLine);
 | 
			
		||||
			widgetPainter.setPen(dashPen);
 | 
			
		||||
			// ... вертикальная
 | 
			
		||||
			widgetPainter.drawLine(
 | 
			
		||||
						QPoint(pimpl->croppingRect.center().x(), pimpl->croppingRect.top()),
 | 
			
		||||
						QPoint(pimpl->croppingRect.center().x(), pimpl->croppingRect.bottom()) );
 | 
			
		||||
			// ... горизонтальная
 | 
			
		||||
			widgetPainter.drawLine(
 | 
			
		||||
						QPoint(pimpl->croppingRect.left(), pimpl->croppingRect.center().y()),
 | 
			
		||||
						QPoint(pimpl->croppingRect.right(), pimpl->croppingRect.center().y()) );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	//
 | 
			
		||||
	widgetPainter.end();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::mousePressEvent(QMouseEvent* _event)
 | 
			
		||||
{
 | 
			
		||||
	if (_event->button() == Qt::LeftButton) {
 | 
			
		||||
		pimpl->isMousePressed = true;
 | 
			
		||||
		pimpl->startMousePos = _event->pos();
 | 
			
		||||
		pimpl->lastStaticCroppingRect = pimpl->croppingRect;
 | 
			
		||||
	}
 | 
			
		||||
	//
 | 
			
		||||
	updateCursorIcon(_event->pos());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::mouseMoveEvent(QMouseEvent* _event)
 | 
			
		||||
{
 | 
			
		||||
	QPointF mousePos = _event->pos(); // относительно себя (виджета)
 | 
			
		||||
	//
 | 
			
		||||
	if (!pimpl->isMousePressed) {
 | 
			
		||||
		// Обработка обычного состояния, т.е. не изменяется размер
 | 
			
		||||
		// области обрезки, и она не перемещается по виджету
 | 
			
		||||
		pimpl->cursorPosition = cursorPosition(pimpl->croppingRect, mousePos);
 | 
			
		||||
		updateCursorIcon(mousePos);
 | 
			
		||||
	} else if (pimpl->cursorPosition != CursorPositionUndefined) {
 | 
			
		||||
		// Обработка действий над областью обрезки
 | 
			
		||||
		// ... определим смещение курсора мышки
 | 
			
		||||
		QPointF mouseDelta;
 | 
			
		||||
		mouseDelta.setX( mousePos.x() - pimpl->startMousePos.x() );
 | 
			
		||||
		mouseDelta.setY( mousePos.y() - pimpl->startMousePos.y() );
 | 
			
		||||
		//
 | 
			
		||||
		if (pimpl->cursorPosition != CursorPositionMiddle) {
 | 
			
		||||
			// ... изменяем размер области обрезки
 | 
			
		||||
			QRectF newGeometry =
 | 
			
		||||
					calculateGeometry(
 | 
			
		||||
						pimpl->lastStaticCroppingRect,
 | 
			
		||||
						pimpl->cursorPosition,
 | 
			
		||||
						mouseDelta);
 | 
			
		||||
			// ... пользователь пытается вывернуть область обрезки наизнанку
 | 
			
		||||
			if (!newGeometry.isNull()) {
 | 
			
		||||
				pimpl->croppingRect = newGeometry;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			// ... перемещаем область обрезки
 | 
			
		||||
			pimpl->croppingRect.moveTo( pimpl->lastStaticCroppingRect.topLeft() + mouseDelta );
 | 
			
		||||
		}
 | 
			
		||||
		// Перерисуем виджет
 | 
			
		||||
		update();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::mouseReleaseEvent(QMouseEvent* _event)
 | 
			
		||||
{
 | 
			
		||||
	pimpl->isMousePressed = false;
 | 
			
		||||
	updateCursorIcon(_event->pos());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ********
 | 
			
		||||
// Private section
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
	// Находится ли точка рядом с координатой стороны
 | 
			
		||||
	static bool isPointNearSide (const int _sideCoordinate, const int _pointCoordinate)
 | 
			
		||||
	{
 | 
			
		||||
		static const int indent = 10;
 | 
			
		||||
		return (_sideCoordinate - indent) < _pointCoordinate && _pointCoordinate < (_sideCoordinate + indent);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CursorPosition ImageCropper::cursorPosition(const QRectF& _cropRect, const QPointF& _mousePosition)
 | 
			
		||||
{
 | 
			
		||||
	CursorPosition cursorPosition = CursorPositionUndefined;
 | 
			
		||||
	//
 | 
			
		||||
	if ( _cropRect.contains( _mousePosition ) ) {
 | 
			
		||||
		// Двухстороннее направление
 | 
			
		||||
		if (isPointNearSide(_cropRect.top(), _mousePosition.y()) &&
 | 
			
		||||
			isPointNearSide(_cropRect.left(), _mousePosition.x())) {
 | 
			
		||||
			cursorPosition = CursorPositionTopLeft;
 | 
			
		||||
		} else if (isPointNearSide(_cropRect.bottom(), _mousePosition.y()) &&
 | 
			
		||||
				   isPointNearSide(_cropRect.left(), _mousePosition.x())) {
 | 
			
		||||
			cursorPosition = CursorPositionBottomLeft;
 | 
			
		||||
		} else if (isPointNearSide(_cropRect.top(), _mousePosition.y()) &&
 | 
			
		||||
				   isPointNearSide(_cropRect.right(), _mousePosition.x())) {
 | 
			
		||||
			cursorPosition = CursorPositionTopRight;
 | 
			
		||||
		} else if (isPointNearSide(_cropRect.bottom(), _mousePosition.y()) &&
 | 
			
		||||
				   isPointNearSide(_cropRect.right(), _mousePosition.x())) {
 | 
			
		||||
			cursorPosition = CursorPositionBottomRight;
 | 
			
		||||
		// Одностороннее направление
 | 
			
		||||
		} else if (isPointNearSide(_cropRect.left(), _mousePosition.x())) {
 | 
			
		||||
			cursorPosition = CursorPositionLeft;
 | 
			
		||||
		} else if (isPointNearSide(_cropRect.right(), _mousePosition.x())) {
 | 
			
		||||
			cursorPosition = CursorPositionRight;
 | 
			
		||||
		} else if (isPointNearSide(_cropRect.top(), _mousePosition.y())) {
 | 
			
		||||
			cursorPosition = CursorPositionTop;
 | 
			
		||||
		} else if (isPointNearSide(_cropRect.bottom(), _mousePosition.y())) {
 | 
			
		||||
			cursorPosition = CursorPositionBottom;
 | 
			
		||||
		// Без направления
 | 
			
		||||
		} else {
 | 
			
		||||
			cursorPosition = CursorPositionMiddle;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	//
 | 
			
		||||
	return cursorPosition;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImageCropper::updateCursorIcon(const QPointF& _mousePosition)
 | 
			
		||||
{
 | 
			
		||||
	QCursor cursorIcon;
 | 
			
		||||
	//
 | 
			
		||||
	switch (cursorPosition(pimpl->croppingRect, _mousePosition))
 | 
			
		||||
	{
 | 
			
		||||
		case CursorPositionTopRight:
 | 
			
		||||
		case CursorPositionBottomLeft:
 | 
			
		||||
			cursorIcon = QCursor(Qt::SizeBDiagCursor);
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionTopLeft:
 | 
			
		||||
		case CursorPositionBottomRight:
 | 
			
		||||
			cursorIcon = QCursor(Qt::SizeFDiagCursor);
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionTop:
 | 
			
		||||
		case CursorPositionBottom:
 | 
			
		||||
			cursorIcon = QCursor(Qt::SizeVerCursor);
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionLeft:
 | 
			
		||||
		case CursorPositionRight:
 | 
			
		||||
			cursorIcon = QCursor(Qt::SizeHorCursor);
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionMiddle:
 | 
			
		||||
			cursorIcon = pimpl->isMousePressed ?
 | 
			
		||||
						QCursor(Qt::ClosedHandCursor) :
 | 
			
		||||
						QCursor(Qt::OpenHandCursor);
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionUndefined:
 | 
			
		||||
		default:
 | 
			
		||||
			cursorIcon = QCursor(Qt::ArrowCursor);
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	//
 | 
			
		||||
	this->setCursor(cursorIcon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QRectF ImageCropper::calculateGeometry(
 | 
			
		||||
		const QRectF& _sourceGeometry,
 | 
			
		||||
		const CursorPosition _cursorPosition,
 | 
			
		||||
		const QPointF& _mouseDelta
 | 
			
		||||
		)
 | 
			
		||||
{
 | 
			
		||||
	QRectF resultGeometry;
 | 
			
		||||
	//
 | 
			
		||||
	if ( pimpl->isProportionFixed ) {
 | 
			
		||||
		resultGeometry =
 | 
			
		||||
				calculateGeometryWithFixedProportions(
 | 
			
		||||
					_sourceGeometry, _cursorPosition, _mouseDelta, pimpl->deltas);
 | 
			
		||||
	} else {
 | 
			
		||||
		resultGeometry =
 | 
			
		||||
				calculateGeometryWithCustomProportions(
 | 
			
		||||
					_sourceGeometry, _cursorPosition, _mouseDelta);
 | 
			
		||||
	}
 | 
			
		||||
	// Если пользователь пытается вывернуть область обрезки наизнанку,
 | 
			
		||||
	// возвращаем null-прямоугольник
 | 
			
		||||
	if ((resultGeometry.left() >= resultGeometry.right()) ||
 | 
			
		||||
		(resultGeometry.top() >= resultGeometry.bottom())) {
 | 
			
		||||
		resultGeometry = QRect();
 | 
			
		||||
	}
 | 
			
		||||
	//
 | 
			
		||||
	return resultGeometry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QRectF ImageCropper::calculateGeometryWithCustomProportions(
 | 
			
		||||
		const QRectF& _sourceGeometry,
 | 
			
		||||
		const CursorPosition _cursorPosition,
 | 
			
		||||
		const QPointF& _mouseDelta
 | 
			
		||||
		)
 | 
			
		||||
{
 | 
			
		||||
	QRectF resultGeometry = _sourceGeometry;
 | 
			
		||||
	//
 | 
			
		||||
	switch ( _cursorPosition )
 | 
			
		||||
	{
 | 
			
		||||
		case CursorPositionTopLeft:
 | 
			
		||||
			resultGeometry.setLeft( _sourceGeometry.left() + _mouseDelta.x() );
 | 
			
		||||
			resultGeometry.setTop ( _sourceGeometry.top()  + _mouseDelta.y() );
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionTopRight:
 | 
			
		||||
			resultGeometry.setTop  ( _sourceGeometry.top()   + _mouseDelta.y() );
 | 
			
		||||
			resultGeometry.setRight( _sourceGeometry.right() + _mouseDelta.x() );
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionBottomLeft:
 | 
			
		||||
			resultGeometry.setBottom( _sourceGeometry.bottom() + _mouseDelta.y() );
 | 
			
		||||
			resultGeometry.setLeft  ( _sourceGeometry.left()   + _mouseDelta.x() );
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionBottomRight:
 | 
			
		||||
			resultGeometry.setBottom( _sourceGeometry.bottom() + _mouseDelta.y() );
 | 
			
		||||
			resultGeometry.setRight ( _sourceGeometry.right()  + _mouseDelta.x() );
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionTop:
 | 
			
		||||
			resultGeometry.setTop( _sourceGeometry.top() + _mouseDelta.y() );
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionBottom:
 | 
			
		||||
			resultGeometry.setBottom( _sourceGeometry.bottom() + _mouseDelta.y() );
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionLeft:
 | 
			
		||||
			resultGeometry.setLeft( _sourceGeometry.left() + _mouseDelta.x() );
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionRight:
 | 
			
		||||
			resultGeometry.setRight( _sourceGeometry.right() + _mouseDelta.x() );
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	//
 | 
			
		||||
	return resultGeometry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const QRectF ImageCropper::calculateGeometryWithFixedProportions(
 | 
			
		||||
		const QRectF& _sourceGeometry,
 | 
			
		||||
		const CursorPosition _cursorPosition,
 | 
			
		||||
		const QPointF& _mouseDelta,
 | 
			
		||||
		const QSizeF& _deltas
 | 
			
		||||
		)
 | 
			
		||||
{
 | 
			
		||||
	QRectF resultGeometry = _sourceGeometry;
 | 
			
		||||
	//
 | 
			
		||||
	switch (_cursorPosition)
 | 
			
		||||
	{
 | 
			
		||||
		case CursorPositionLeft:
 | 
			
		||||
			resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.x() * _deltas.height());
 | 
			
		||||
			resultGeometry.setLeft(_sourceGeometry.left() + _mouseDelta.x());
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionRight:
 | 
			
		||||
			resultGeometry.setTop(_sourceGeometry.top() - _mouseDelta.x() * _deltas.height());
 | 
			
		||||
			resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.x());
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionTop:
 | 
			
		||||
			resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.y());
 | 
			
		||||
			resultGeometry.setRight(_sourceGeometry.right() - _mouseDelta.y() * _deltas.width());
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionBottom:
 | 
			
		||||
			resultGeometry.setBottom(_sourceGeometry.bottom() + _mouseDelta.y());
 | 
			
		||||
			resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.y() * _deltas.width());
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionTopLeft:
 | 
			
		||||
			if ((_mouseDelta.x() * _deltas.height()) < (_mouseDelta.y())) {
 | 
			
		||||
				resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.x() * _deltas.height());
 | 
			
		||||
				resultGeometry.setLeft(_sourceGeometry.left() + _mouseDelta.x());
 | 
			
		||||
			} else {
 | 
			
		||||
				resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.y());
 | 
			
		||||
				resultGeometry.setLeft(_sourceGeometry.left() + _mouseDelta.y() * _deltas.width());
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionTopRight:
 | 
			
		||||
			if ((_mouseDelta.x() * _deltas.height() * -1) < (_mouseDelta.y())) {
 | 
			
		||||
				resultGeometry.setTop(_sourceGeometry.top() - _mouseDelta.x() * _deltas.height());
 | 
			
		||||
				resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.x() );
 | 
			
		||||
			} else {
 | 
			
		||||
				resultGeometry.setTop(_sourceGeometry.top() + _mouseDelta.y());
 | 
			
		||||
				resultGeometry.setRight(_sourceGeometry.right() - _mouseDelta.y() * _deltas.width());
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionBottomLeft:
 | 
			
		||||
			if ((_mouseDelta.x() * _deltas.height()) < (_mouseDelta.y() * -1)) {
 | 
			
		||||
				resultGeometry.setBottom(_sourceGeometry.bottom() - _mouseDelta.x() * _deltas.height());
 | 
			
		||||
				resultGeometry.setLeft(_sourceGeometry.left() + _mouseDelta.x());
 | 
			
		||||
			} else {
 | 
			
		||||
				resultGeometry.setBottom(_sourceGeometry.bottom() + _mouseDelta.y());
 | 
			
		||||
				resultGeometry.setLeft(_sourceGeometry.left() - _mouseDelta.y() * _deltas.width());
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case CursorPositionBottomRight:
 | 
			
		||||
			if ((_mouseDelta.x() * _deltas.height()) > (_mouseDelta.y())) {
 | 
			
		||||
				resultGeometry.setBottom(_sourceGeometry.bottom() + _mouseDelta.x() * _deltas.height());
 | 
			
		||||
				resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.x());
 | 
			
		||||
			} else {
 | 
			
		||||
				resultGeometry.setBottom(_sourceGeometry.bottom() + _mouseDelta.y());
 | 
			
		||||
				resultGeometry.setRight(_sourceGeometry.right() + _mouseDelta.y() * _deltas.width());
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	//
 | 
			
		||||
	return resultGeometry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,103 +0,0 @@
 | 
			
		|||
/*****************************************************************************
 | 
			
		||||
* ImageCropper Qt Widget for cropping images
 | 
			
		||||
* Copyright (C) 2013 Dimka Novikov, to@dimkanovikov.pro
 | 
			
		||||
*
 | 
			
		||||
* This library is free software; you can redistribute it and/or
 | 
			
		||||
* modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
* License as published by the Free Software Foundation; either
 | 
			
		||||
* version 3 of the License, or any later version.
 | 
			
		||||
*
 | 
			
		||||
* This library is distributed in the hope that it will be useful,
 | 
			
		||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
* Lesser General Public License for more details.
 | 
			
		||||
*
 | 
			
		||||
* You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef IMAGECROPPER_H
 | 
			
		||||
#define IMAGECROPPER_H
 | 
			
		||||
 | 
			
		||||
#include "imagecropper_p.h"
 | 
			
		||||
#include "imagecropper_e.h"
 | 
			
		||||
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
 | 
			
		||||
class ImageCropper : public QWidget
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    ImageCropper(QWidget *parent = 0);
 | 
			
		||||
    ~ImageCropper();
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
	// Установить изображение для обрезки
 | 
			
		||||
	void setImage(const QPixmap& _image);
 | 
			
		||||
	// Установить цвет фона виджета обрезки
 | 
			
		||||
	void setBackgroundColor(const QColor& _backgroundColor);
 | 
			
		||||
	// Установить цвет рамки области обрезки
 | 
			
		||||
	void setCroppingRectBorderColor(const QColor& _borderColor);
 | 
			
		||||
	// Установить пропорции области выделения
 | 
			
		||||
	void setProportion(const QSizeF& _proportion);
 | 
			
		||||
	// Использовать фиксированные пропорции области виделения
 | 
			
		||||
	void setProportionFixed(const bool _isFixed);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	// Обрезать изображение
 | 
			
		||||
	const QPixmap cropImage();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	virtual void paintEvent(QPaintEvent* _event);
 | 
			
		||||
	virtual void mousePressEvent(QMouseEvent* _event);
 | 
			
		||||
	virtual void mouseMoveEvent(QMouseEvent* _event);
 | 
			
		||||
	virtual void mouseReleaseEvent(QMouseEvent* _event);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	// Определение местоположения курсора над виджетом
 | 
			
		||||
	CursorPosition cursorPosition(const QRectF& _cropRect, const QPointF& _mousePosition);
 | 
			
		||||
	// Обновить иконку курсора соответствующую местоположению мыши
 | 
			
		||||
	void updateCursorIcon(const QPointF& _mousePosition);
 | 
			
		||||
 | 
			
		||||
	// Получить размер виджета после его изменения мышью
 | 
			
		||||
	// --------
 | 
			
		||||
    // Контракты:
 | 
			
		||||
    // 1. Метод должен вызываться, только при зажатой кнопке мыши
 | 
			
		||||
    //    (т.е. при перемещении или изменении размера виджета)
 | 
			
		||||
	// --------
 | 
			
		||||
	// В случае неудачи возвращает null-прямоугольник
 | 
			
		||||
	const QRectF calculateGeometry(
 | 
			
		||||
			const QRectF& _sourceGeometry,
 | 
			
		||||
			const CursorPosition _cursorPosition,
 | 
			
		||||
			const QPointF& _mouseDelta
 | 
			
		||||
			);
 | 
			
		||||
    // Получить размер виджета после его изменения мышью
 | 
			
		||||
    // Метод изменяет виджет не сохраняя начальных пропорций сторон
 | 
			
		||||
    // ------
 | 
			
		||||
    // Контракты:
 | 
			
		||||
    // 1. Метод должен вызываться, только при зажатой кнопке мыши
 | 
			
		||||
    //    (т.е. при перемещении или изменении размера виджета)
 | 
			
		||||
	const QRectF calculateGeometryWithCustomProportions(
 | 
			
		||||
			const QRectF& _sourceGeometry,
 | 
			
		||||
			const CursorPosition _cursorPosition,
 | 
			
		||||
			const QPointF& _mouseDelta
 | 
			
		||||
			);
 | 
			
		||||
    // Получить размер виджета после его изменения мышью
 | 
			
		||||
    // Метод изменяет виджет сохраняя начальные пропорции сторон
 | 
			
		||||
    // ------
 | 
			
		||||
    // Контракты:
 | 
			
		||||
    // 1. Метод должен вызываться, только при зажатой кнопке мыши
 | 
			
		||||
    //    (т.е. при перемещении или изменении размера виджета)
 | 
			
		||||
	const QRectF calculateGeometryWithFixedProportions(const QRectF &_sourceGeometry,
 | 
			
		||||
												 const CursorPosition _cursorPosition,
 | 
			
		||||
												 const QPointF &_mouseDelta,
 | 
			
		||||
												 const QSizeF &_deltas
 | 
			
		||||
                                                 );
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	// Private data implementation
 | 
			
		||||
	ImageCropperPrivate* pimpl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // IMAGECROPPER_H
 | 
			
		||||
| 
						 | 
				
			
			@ -1,36 +0,0 @@
 | 
			
		|||
/*****************************************************************************
 | 
			
		||||
* ImageCropper Qt Widget for cropping images
 | 
			
		||||
* Copyright (C) 2013 Dimka Novikov, to@dimkanovikov.pro
 | 
			
		||||
*
 | 
			
		||||
* This library is free software; you can redistribute it and/or
 | 
			
		||||
* modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
* License as published by the Free Software Foundation; either
 | 
			
		||||
* version 3 of the License, or any later version.
 | 
			
		||||
*
 | 
			
		||||
* This library is distributed in the hope that it will be useful,
 | 
			
		||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
* Lesser General Public License for more details.
 | 
			
		||||
*
 | 
			
		||||
* You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef IMAGECROPPER_E_H
 | 
			
		||||
#define IMAGECROPPER_E_H
 | 
			
		||||
 | 
			
		||||
enum CursorPosition
 | 
			
		||||
{
 | 
			
		||||
    CursorPositionUndefined,
 | 
			
		||||
    CursorPositionMiddle,
 | 
			
		||||
    CursorPositionTop,
 | 
			
		||||
    CursorPositionBottom,
 | 
			
		||||
    CursorPositionLeft,
 | 
			
		||||
    CursorPositionRight,
 | 
			
		||||
    CursorPositionTopLeft,
 | 
			
		||||
    CursorPositionTopRight,
 | 
			
		||||
    CursorPositionBottomLeft,
 | 
			
		||||
    CursorPositionBottomRight
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // IMAGECROPPER_E_H
 | 
			
		||||
| 
						 | 
				
			
			@ -1,76 +0,0 @@
 | 
			
		|||
/*****************************************************************************
 | 
			
		||||
* ImageCropper Qt Widget for cropping images
 | 
			
		||||
* Copyright (C) 2013 Dimka Novikov, to@dimkanovikov.pro
 | 
			
		||||
*
 | 
			
		||||
* This library is free software; you can redistribute it and/or
 | 
			
		||||
* modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
* License as published by the Free Software Foundation; either
 | 
			
		||||
* version 3 of the License, or any later version.
 | 
			
		||||
*
 | 
			
		||||
* This library is distributed in the hope that it will be useful,
 | 
			
		||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
* Lesser General Public License for more details.
 | 
			
		||||
*
 | 
			
		||||
* You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef IMAGECROPPER_P_H
 | 
			
		||||
#define IMAGECROPPER_P_H
 | 
			
		||||
 | 
			
		||||
#include "imagecropper_e.h"
 | 
			
		||||
 | 
			
		||||
#include <QtCore/QRect>
 | 
			
		||||
#include <QtGui/QPixmap>
 | 
			
		||||
#include <QtGui/QColor>
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
	const QRect INIT_CROPPING_RECT = QRect();
 | 
			
		||||
	const QSizeF INIT_PROPORTION = QSizeF(1.0, 1.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ImageCropperPrivate {
 | 
			
		||||
public:
 | 
			
		||||
	ImageCropperPrivate() :
 | 
			
		||||
		imageForCropping(QPixmap()),
 | 
			
		||||
		croppingRect(INIT_CROPPING_RECT),
 | 
			
		||||
		lastStaticCroppingRect(QRect()),
 | 
			
		||||
		cursorPosition(CursorPositionUndefined),
 | 
			
		||||
		isMousePressed(false),
 | 
			
		||||
		isProportionFixed(false),
 | 
			
		||||
		startMousePos(QPoint()),
 | 
			
		||||
		proportion(INIT_PROPORTION),
 | 
			
		||||
        deltas(INIT_PROPORTION),
 | 
			
		||||
		backgroundColor(Qt::black),
 | 
			
		||||
		croppingRectBorderColor(Qt::white)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	// Изображение для обрезки
 | 
			
		||||
	QPixmap imageForCropping;
 | 
			
		||||
	// Область обрезки
 | 
			
		||||
	QRectF croppingRect;
 | 
			
		||||
	// Последняя фиксированная область обрезки
 | 
			
		||||
	QRectF lastStaticCroppingRect;
 | 
			
		||||
	// Позиция курсора относительно области обрезки
 | 
			
		||||
	CursorPosition cursorPosition;
 | 
			
		||||
	// Зажата ли левая кнопка мыши
 | 
			
		||||
	bool isMousePressed;
 | 
			
		||||
	// Фиксировать пропорции области обрезки
 | 
			
		||||
	bool isProportionFixed;
 | 
			
		||||
	// Начальная позиция курсора при изменении размера области обрезки
 | 
			
		||||
	QPointF startMousePos;
 | 
			
		||||
    // Пропорции
 | 
			
		||||
	QSizeF proportion;
 | 
			
		||||
    // Приращения
 | 
			
		||||
    // width  - приращение по x
 | 
			
		||||
    // height - приращение по y
 | 
			
		||||
    QSizeF deltas;
 | 
			
		||||
	// Цвет заливки фона под изображением
 | 
			
		||||
	QColor backgroundColor;
 | 
			
		||||
	// Цвет рамки области обрезки
 | 
			
		||||
	QColor croppingRectBorderColor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // IMAGECROPPER_P_H
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue