pré-voyage
This commit is contained in:
parent
8a0c368243
commit
f31358e6dd
501
Sources/ImageCropper/imagecropper.cpp
Normal file
501
Sources/ImageCropper/imagecropper.cpp
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
#include "imagecropper.h"
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const QSize WIDGET_MINIMUM_SIZE(300, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
|
this->size(), Qt::KeepAspectRatio, Qt::FastTransformation
|
||||||
|
).size();
|
||||||
|
// Определим расстояние от левого и верхнего краёв
|
||||||
|
float leftDelta = 0;
|
||||||
|
float topDelta = 0;
|
||||||
|
const float HALF_COUNT = 2;
|
||||||
|
if (this->size().height() == scaledImageSize.height()) {
|
||||||
|
leftDelta = (this->width() - scaledImageSize.width()) / HALF_COUNT;
|
||||||
|
} else {
|
||||||
|
topDelta = (this->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);
|
||||||
|
// Рисуем изображение по центру виджета
|
||||||
|
{
|
||||||
|
// ... подгоним изображение для отображения по размеру виджета
|
||||||
|
QPixmap scaledImage =
|
||||||
|
pimpl->imageForCropping.scaled(this->size(), Qt::KeepAspectRatio, Qt::FastTransformation);
|
||||||
|
// ... заливаем фон
|
||||||
|
widgetPainter.fillRect( this->rect(), pimpl->backgroundColor );
|
||||||
|
// ... рисуем изображение по центру виджета
|
||||||
|
if ( this->size().height() == scaledImage.height() ) {
|
||||||
|
widgetPainter.drawPixmap( ( this->width() - scaledImage.width() ) / 2, 0, scaledImage );
|
||||||
|
} else {
|
||||||
|
widgetPainter.drawPixmap( 0, ( this->height() - scaledImage.height() ) / 2, scaledImage );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Рисуем область обрезки
|
||||||
|
{
|
||||||
|
// ... если это первое отображение после инициилизации, то центруем областо обрезки
|
||||||
|
if (pimpl->croppingRect.isNull()) {
|
||||||
|
const int width = WIDGET_MINIMUM_SIZE.width()/2;
|
||||||
|
const int height = WIDGET_MINIMUM_SIZE.height()/2;
|
||||||
|
pimpl->croppingRect.setSize(QSize(width, height));
|
||||||
|
float x = (this->width() - pimpl->croppingRect.width())/2;
|
||||||
|
float y = (this->height() - pimpl->croppingRect.height())/2;
|
||||||
|
pimpl->croppingRect.moveTo(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... рисуем затемненную область
|
||||||
|
QPainterPath p;
|
||||||
|
p.addRect(pimpl->croppingRect);
|
||||||
|
p.addRect(this->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;
|
||||||
|
}
|
||||||
|
|
||||||
85
Sources/ImageCropper/imagecropper.h
Normal file
85
Sources/ImageCropper/imagecropper.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#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
|
||||||
18
Sources/ImageCropper/imagecropper_e.h
Normal file
18
Sources/ImageCropper/imagecropper_e.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef IMAGECROPPER_E_H
|
||||||
|
#define IMAGECROPPER_E_H
|
||||||
|
|
||||||
|
enum CursorPosition
|
||||||
|
{
|
||||||
|
CursorPositionUndefined,
|
||||||
|
CursorPositionMiddle,
|
||||||
|
CursorPositionTop,
|
||||||
|
CursorPositionBottom,
|
||||||
|
CursorPositionLeft,
|
||||||
|
CursorPositionRight,
|
||||||
|
CursorPositionTopLeft,
|
||||||
|
CursorPositionTopRight,
|
||||||
|
CursorPositionBottomLeft,
|
||||||
|
CursorPositionBottomRight
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IMAGECROPPER_E_H
|
||||||
58
Sources/ImageCropper/imagecropper_p.h
Normal file
58
Sources/ImageCropper/imagecropper_p.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#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
|
||||||
@ -58,6 +58,8 @@ int CNetworkDevicesMgr::CreateNewSprinklerDevice(int Address, CAbstractNetworkCo
|
|||||||
|
|
||||||
CSprinklerDevice *SprinklerDevice = new CSprinklerDevice(Address,NetworkIF,mSprinklerMgrHandle);
|
CSprinklerDevice *SprinklerDevice = new CSprinklerDevice(Address,NetworkIF,mSprinklerMgrHandle);
|
||||||
mNetworkDevicesList.append((CNetworkDevice*)SprinklerDevice);
|
mNetworkDevicesList.append((CNetworkDevice*)SprinklerDevice);
|
||||||
|
mSprinklerMgrHandle->NewSprinklerDeviceCreated(SprinklerDevice);
|
||||||
|
|
||||||
|
|
||||||
return RET_OK;
|
return RET_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,8 @@ QByteArray CNetworkProtocol::GetTxPacket(unsigned char MessageID, unsigned char
|
|||||||
Frame.append((Size & 0x00FF0000) >> 16);
|
Frame.append((Size & 0x00FF0000) >> 16);
|
||||||
Frame.append((Size & 0x0000FF00) >> 8);
|
Frame.append((Size & 0x0000FF00) >> 8);
|
||||||
Frame.append(Size & 0x000000FF);
|
Frame.append(Size & 0x000000FF);
|
||||||
Frame.append(Data,Size);
|
if(Size > 0)
|
||||||
|
Frame.append(Data,Size);
|
||||||
char CRC = CalcCRC(Frame.data(),FrameSize);
|
char CRC = CalcCRC(Frame.data(),FrameSize);
|
||||||
Frame.append(CRC);
|
Frame.append(CRC);
|
||||||
|
|
||||||
@ -350,6 +351,7 @@ void CNetworkProtocol::PrepareForNewPacket()
|
|||||||
int CNetworkProtocol::AnalyzeRxBuffer(QByteArray Buffer)
|
int CNetworkProtocol::AnalyzeRxBuffer(QByteArray Buffer)
|
||||||
{
|
{
|
||||||
int ret = PROTOCOL_RET_ERROR_EMPTY_BUFFER;
|
int ret = PROTOCOL_RET_ERROR_EMPTY_BUFFER;
|
||||||
|
qDebug("Rx %d bytes",Buffer.size());
|
||||||
for(int i = 0; i < Buffer.size(); i++)
|
for(int i = 0; i < Buffer.size(); i++)
|
||||||
{
|
{
|
||||||
ret = RxStateMachine(Buffer.at(i));
|
ret = RxStateMachine(Buffer.at(i));
|
||||||
|
|||||||
@ -7,13 +7,28 @@
|
|||||||
CSprinklerDevice::CSprinklerDevice(int Address, CAbstractNetworkCommIF *NetworkInterface, CSprinklerMgr *SprinklerMgr):
|
CSprinklerDevice::CSprinklerDevice(int Address, CAbstractNetworkCommIF *NetworkInterface, CSprinklerMgr *SprinklerMgr):
|
||||||
CNetworkDevice(ID_SPRINKLER_DEVICE,Address,NetworkInterface)
|
CNetworkDevice(ID_SPRINKLER_DEVICE,Address,NetworkInterface)
|
||||||
{
|
{
|
||||||
|
mSprinklerState = SPRINKLER_UNKNOWN_STATE;
|
||||||
|
|
||||||
mSprinklerMgr = SprinklerMgr;
|
mSprinklerMgr = SprinklerMgr;
|
||||||
|
mSprinklerStatusTimer = new QTimer();
|
||||||
|
|
||||||
|
mSprinklerStatusTimer->setInterval(5000);
|
||||||
|
mSprinklerStatusTimer->setSingleShot(true);
|
||||||
|
connect(mSprinklerStatusTimer,SIGNAL(timeout()),this,SLOT(StatusTimerExpired()));
|
||||||
|
mSprinklerStatusTimer->start();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSprinklerDevice::~CSprinklerDevice()
|
CSprinklerDevice::~CSprinklerDevice()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SprinklerState CSprinklerDevice::GetSprinklerState()
|
||||||
|
{
|
||||||
|
return mSprinklerState;
|
||||||
|
}
|
||||||
|
|
||||||
int CSprinklerDevice::NewDeviceFrameReceived(int DeviceID, int DeviceAddress, int MessageID, int DataSize, QByteArray Data)
|
int CSprinklerDevice::NewDeviceFrameReceived(int DeviceID, int DeviceAddress, int MessageID, int DataSize, QByteArray Data)
|
||||||
{
|
{
|
||||||
Q_UNUSED(DeviceID)
|
Q_UNUSED(DeviceID)
|
||||||
@ -21,12 +36,31 @@ int CSprinklerDevice::NewDeviceFrameReceived(int DeviceID, int DeviceAddress, in
|
|||||||
Q_UNUSED(DataSize)
|
Q_UNUSED(DataSize)
|
||||||
Q_UNUSED(Data)
|
Q_UNUSED(Data)
|
||||||
|
|
||||||
return RET_OK;
|
|
||||||
|
|
||||||
switch(MessageID)
|
switch(MessageID)
|
||||||
{
|
{
|
||||||
case SPRINKLER_DEVICE_STATUS_RESPONSE:
|
case SPRINKLER_DEVICE_STATUS_RESPONSE:
|
||||||
{
|
{
|
||||||
|
if(Data.at(0) != (unsigned char)mSprinklerState)
|
||||||
|
{
|
||||||
|
if(Data.at(0) == SPRINKLER_ON_STATE || Data.at(0) == SPRINKLER_OFF_STATE)
|
||||||
|
{
|
||||||
|
mSprinklerState = (SprinklerState)Data.at(0);
|
||||||
|
//TODO: emit sprinkler change event.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mSprinklerState = SPRINKLER_UNKNOWN_STATE;
|
||||||
|
qDebug("Rx Invalid sprinkler state [%d] from device [%d]",Data.at(0),DeviceAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mFlowMeter = Data.at(1);
|
||||||
|
mFlowMeter <<= 8;
|
||||||
|
mFlowMeter |= (unsigned short)Data.at(2);
|
||||||
|
|
||||||
|
qDebug("Sprinkler status RX. Valve:%d, flow:%d",Data.at(0),mFlowMeter);
|
||||||
|
|
||||||
|
mSprinklerStatusTimer->start();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPRINKLER_DEVICE_ACK:
|
case SPRINKLER_DEVICE_ACK:
|
||||||
@ -35,14 +69,33 @@ int CSprinklerDevice::NewDeviceFrameReceived(int DeviceID, int DeviceAddress, in
|
|||||||
}
|
}
|
||||||
case SPRINKLER_DEVICE_SET_SPRINKLER_STATE_ACK:
|
case SPRINKLER_DEVICE_SET_SPRINKLER_STATE_ACK:
|
||||||
{
|
{
|
||||||
|
mNetworkInterfacePtr->SendNetworkMessage(ID_SPRINKLER_DEVICE,1,SPRINKLER_DEVICE_GET_SPRINKLER_STATE_REQUEST,0,QByteArray());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPRINKLER_DEVICE_GET_SPRINKLER_STATE_RESPONSE:
|
case SPRINKLER_DEVICE_GET_SPRINKLER_STATE_RESPONSE:
|
||||||
{
|
{
|
||||||
|
if(Data.at(0) != (unsigned char)mSprinklerState)
|
||||||
|
{
|
||||||
|
if(Data.at(0) == SPRINKLER_ON_STATE || Data.at(0) == SPRINKLER_OFF_STATE)
|
||||||
|
{
|
||||||
|
mSprinklerState = (SprinklerState)Data.at(0);
|
||||||
|
//TODO: emit sprinkler change event.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mSprinklerState = SPRINKLER_UNKNOWN_STATE;
|
||||||
|
qDebug("Rx Invalid sprinkler state [%d] from device [%d]",Data.at(0),DeviceAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug("Valve state RX. Valve:%d",Data.at(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPRINKLER_DEVICE_GET_WATER_FLOW_RESPONSE:
|
case SPRINKLER_DEVICE_GET_WATER_FLOW_RESPONSE:
|
||||||
{
|
{
|
||||||
|
mFlowMeter = Data.at(0);
|
||||||
|
mFlowMeter <<= 8;
|
||||||
|
mFlowMeter |= (unsigned short)Data.at(1);
|
||||||
|
qDebug("Flow value RX. flow:%d",mFlowMeter);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPRINKLER_DEVICE_GET_MOISTURE_RESPONSE:
|
case SPRINKLER_DEVICE_GET_MOISTURE_RESPONSE:
|
||||||
@ -88,4 +141,7 @@ int CSprinklerDevice::NewDeviceFrameReceived(int DeviceID, int DeviceAddress, in
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSprinklerDevice::StatusTimerExpired()
|
||||||
|
{
|
||||||
|
mNetworkInterfacePtr->SendNetworkMessage(ID_SPRINKLER_DEVICE,1,SPRINKLER_DEVICE_STATUS_REQUEST,0,QByteArray());
|
||||||
|
}
|
||||||
|
|||||||
@ -3,6 +3,14 @@
|
|||||||
|
|
||||||
#include "GlobalDefine.h"
|
#include "GlobalDefine.h"
|
||||||
#include "NetworkDevice.h"
|
#include "NetworkDevice.h"
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
typedef enum eSprinklerState
|
||||||
|
{
|
||||||
|
SPRINKLER_OFF_STATE = 0,
|
||||||
|
SPRINKLER_ON_STATE,
|
||||||
|
SPRINKLER_UNKNOWN_STATE
|
||||||
|
}SprinklerState;
|
||||||
|
|
||||||
class CSprinklerMgr;
|
class CSprinklerMgr;
|
||||||
|
|
||||||
@ -15,8 +23,16 @@ public:
|
|||||||
|
|
||||||
virtual int NewDeviceFrameReceived(int DeviceID, int DeviceAddress, int MessageID, int DataSize, QByteArray Data);
|
virtual int NewDeviceFrameReceived(int DeviceID, int DeviceAddress, int MessageID, int DataSize, QByteArray Data);
|
||||||
|
|
||||||
|
SprinklerState GetSprinklerState();
|
||||||
|
unsigned short mFlowMeter;
|
||||||
|
|
||||||
|
|
||||||
CSprinklerMgr *mSprinklerMgr;
|
CSprinklerMgr *mSprinklerMgr;
|
||||||
|
QTimer *mSprinklerStatusTimer;
|
||||||
|
SprinklerState mSprinklerState;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void StatusTimerExpired();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include "ProtocolDefs.h"
|
#include "ProtocolDefs.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "SprinklerMgr.h"
|
#include "SprinklerMgr.h"
|
||||||
|
#include "SprinklerDevice.h"
|
||||||
|
|
||||||
|
|
||||||
CSprinklerInterface::CSprinklerInterface(int Address, CAbstractNetworkCommIF *NetworkInterface, CSprinklerMgr *SprinklerMgr):
|
CSprinklerInterface::CSprinklerInterface(int Address, CAbstractNetworkCommIF *NetworkInterface, CSprinklerMgr *SprinklerMgr):
|
||||||
@ -47,6 +48,23 @@ int CSprinklerInterface::NewDeviceFrameReceived(int DeviceID, int DeviceAddress,
|
|||||||
}
|
}
|
||||||
case SPRINKLER_INTERFACE_GET_SPRINKLER_STATE_REQUEST:
|
case SPRINKLER_INTERFACE_GET_SPRINKLER_STATE_REQUEST:
|
||||||
{
|
{
|
||||||
|
// if(Data.at(0) == 0xFF)
|
||||||
|
// {
|
||||||
|
// //send all devices...
|
||||||
|
|
||||||
|
// }
|
||||||
|
// if(Data.at(0) == 1)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
CSprinklerDevice *Sprinkler = mSprinklerMgr->GetSprinkler(1);
|
||||||
|
QByteArray Frame, MsgData;
|
||||||
|
MsgData.append(1); //1 device.
|
||||||
|
MsgData.append(Sprinkler->mDeviceAddress); //1st device address
|
||||||
|
MsgData.append((unsigned char)Sprinkler->mSprinklerState);
|
||||||
|
|
||||||
|
mNetworkInterfacePtr->SendNetworkMessage(ID_SPRINKLER_INTERFACE,mDeviceAddress,SPRINKLER_INTERFACE_GET_SPRINKLER_STATE_RESPONSE,MsgData.size(),MsgData);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPRINKLER_INTERFACE_SET_SPRINKLER_STATE_REQUEST:
|
case SPRINKLER_INTERFACE_SET_SPRINKLER_STATE_REQUEST:
|
||||||
|
|||||||
@ -1,6 +1,31 @@
|
|||||||
#include "SprinklerMgr.h"
|
#include "SprinklerMgr.h"
|
||||||
|
#include "SprinklerDevice.h"
|
||||||
|
|
||||||
CSprinklerMgr::CSprinklerMgr(QObject *parent) : QObject(parent)
|
CSprinklerMgr::CSprinklerMgr(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
mProgramHandle = 0;
|
mProgramHandle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CSprinklerMgr::NewSprinklerDeviceCreated(CSprinklerDevice *Device)
|
||||||
|
{
|
||||||
|
mSprinklersList.append(Device);
|
||||||
|
return RET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSprinklerDevice* CSprinklerMgr::GetSprinkler(int SprinklerNetworkAddress)
|
||||||
|
{
|
||||||
|
if(mSprinklersList.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < mSprinklersList.size(); i++)
|
||||||
|
{
|
||||||
|
if(mSprinklersList.at(i)->mDeviceAddress == SprinklerNetworkAddress)
|
||||||
|
{
|
||||||
|
return mSprinklersList.at(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -2,9 +2,11 @@
|
|||||||
#define SPRINKLERMGR_H
|
#define SPRINKLERMGR_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
|
||||||
class CMasterCtrl;
|
class CMasterCtrl;
|
||||||
|
class CSprinklerDevice;
|
||||||
|
|
||||||
class CSprinklerMgr : public QObject
|
class CSprinklerMgr : public QObject
|
||||||
{
|
{
|
||||||
@ -13,6 +15,11 @@ public:
|
|||||||
explicit CSprinklerMgr(QObject *parent = 0);
|
explicit CSprinklerMgr(QObject *parent = 0);
|
||||||
|
|
||||||
CMasterCtrl *mProgramHandle;
|
CMasterCtrl *mProgramHandle;
|
||||||
|
QList<CSprinklerDevice*> mSprinklersList;
|
||||||
|
|
||||||
|
|
||||||
|
int NewSprinklerDeviceCreated(CSprinklerDevice* Device);
|
||||||
|
CSprinklerDevice* GetSprinkler(int SprinklerNetworkAddress);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
|||||||
@ -138,7 +138,7 @@ int CVoipMsSMSClient::DownloadNewSMS()
|
|||||||
int CVoipMsSMSClient::CheckForNewSMS()
|
int CVoipMsSMSClient::CheckForNewSMS()
|
||||||
{
|
{
|
||||||
// qDebug("Check new SMS");
|
// qDebug("Check new SMS");
|
||||||
qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << ":" << "Check New SMS";
|
// qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << ":" << "Check New SMS";
|
||||||
if(mSMSMessagesList.isEmpty() == true)
|
if(mSMSMessagesList.isEmpty() == true)
|
||||||
{
|
{
|
||||||
return RET_ERROR;
|
return RET_ERROR;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user