8ebd6975d7
- renamed library - added support for saving loading current game - added (still crappy) nonogram solver - some code cleanups
748 lines
21 KiB
C++
748 lines
21 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2008 by Oliver Groß *
|
|
* z.o.gross@gmx.de *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program 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 General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
#include "ccrossfieldwidget.h"
|
|
|
|
#include <libqnono/cnonogram.h>
|
|
#include <libqnono/cnonogramsolver.h>
|
|
|
|
#include <QPainter>
|
|
#include <QMouseEvent>
|
|
#include <QLCDNumber>
|
|
#include <QDebug>
|
|
#include <QFrame>
|
|
#include <QLabel>
|
|
#include <QHBoxLayout>
|
|
#include <QStyle>
|
|
#include <QApplication>
|
|
|
|
namespace qcross {
|
|
using namespace libqnono;
|
|
|
|
int min(int a, int b) {
|
|
return (a < b) ? a : b;
|
|
}
|
|
|
|
int max(int a, int b) {
|
|
return (a > b) ? a : b;
|
|
}
|
|
|
|
//public
|
|
CCrossFieldWidget::CCrossFieldWidget(CNonogram * picture, QWidget * parent) : QWidget(parent),
|
|
m_Picture(picture),
|
|
m_OverlayData(NULL),
|
|
m_MouseMark(CMT_NONE),
|
|
m_ErrorAware(false),
|
|
m_NumbersMarkable(true),
|
|
m_Time(0),
|
|
m_Paused(true),
|
|
m_Solved(false),
|
|
m_TimerId(-1),
|
|
m_MessageTimeoutId(-1),
|
|
m_Clock(NULL),
|
|
m_ErrorCount(0),
|
|
m_LastErrorMark(-1, -1)
|
|
{
|
|
// m_Notifier = new QFrame(this);
|
|
// m_Notifier->setLineWidth(10);
|
|
// m_Notifier->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
|
|
QPalette notifierPalette(QApplication::palette().color(QPalette::ToolTipBase));
|
|
notifierPalette.setColor(QPalette::Text, QApplication::palette().color(QPalette::ToolTipText));
|
|
|
|
// m_Notifier->setPalette(notifierPalette);
|
|
// m_Notifier->setAutoFillBackground(true);
|
|
|
|
// QHBoxLayout * notifierLayout = new QHBoxLayout(m_Notifier);
|
|
// m_NotifierIcon = new QLabel(m_Notifier);
|
|
// m_NotifierText = new QLabel(m_Notifier);
|
|
|
|
// m_NotifierText->setWordWrap(true);
|
|
// notifierLayout->addWidget(m_NotifierIcon);
|
|
// notifierLayout->addWidget(m_NotifierText);
|
|
// notifierLayout->addStretch();
|
|
// m_Notifier->setLayout(notifierLayout);
|
|
|
|
// m_Notifier->hide();
|
|
|
|
m_Clock = new QLCDNumber(8, this);
|
|
m_Clock->setVisible(m_Picture);
|
|
|
|
if (m_Picture) {
|
|
initialize();
|
|
m_RemainingPixels = m_Picture->blackPixels();
|
|
updateTimeDisplay();
|
|
}
|
|
|
|
setEnabled(false);
|
|
}
|
|
|
|
CCrossFieldWidget::~CCrossFieldWidget() {
|
|
cleanup();
|
|
|
|
// delete m_Clock;
|
|
}
|
|
|
|
void CCrossFieldWidget::setPicture(CNonogram * picture) {
|
|
if (m_Picture)
|
|
cleanup();
|
|
|
|
m_Picture = picture;
|
|
|
|
if (m_Picture) {
|
|
m_LastErrorMark.setX(-1);
|
|
m_LastErrorMark.setY(-1);
|
|
m_ErrorCount = 0;
|
|
m_Time = picture->timeout();
|
|
m_ErrorAware = picture->timeout();
|
|
m_Solved = false;
|
|
|
|
updateTimeDisplay();
|
|
emit timeChanged(m_Time);
|
|
|
|
initialize();
|
|
|
|
m_Messages.clear();
|
|
nextMessage();
|
|
|
|
updateMetrics();
|
|
|
|
m_RemainingPixels = m_Picture->blackPixels();
|
|
}
|
|
m_Clock->setVisible(m_Picture);
|
|
}
|
|
|
|
void CCrossFieldWidget::showMessage(const QString message, int timeout, MessageType type) {
|
|
if (!message.isEmpty()) {
|
|
Message newMessage;
|
|
newMessage.type = type;
|
|
newMessage.text = message;
|
|
newMessage.timeout = timeout;
|
|
m_Messages.enqueue(newMessage);
|
|
}
|
|
|
|
if (m_MessageTimeoutId == -1)
|
|
nextMessage();
|
|
}
|
|
|
|
void CCrossFieldWidget::applyState(QDataStream & stream) {
|
|
qDebug("trying to apply state...");
|
|
qDebug("reading basic stuff:");
|
|
|
|
// error state
|
|
stream >> m_ErrorAware; qDebug("m_ErrorAware = %i", int(m_ErrorAware));
|
|
stream >> m_ErrorCount; qDebug("m_ErrorCount = %i", m_ErrorCount);
|
|
|
|
// time(out)
|
|
stream >> m_Time; qDebug("m_Time = %i", m_Time);
|
|
updateTimeDisplay();
|
|
emit timeChanged(m_Time);
|
|
|
|
// messages
|
|
int messageCount;
|
|
stream >> messageCount; qDebug("messageCount = %i", messageCount);
|
|
|
|
m_Messages.clear();
|
|
|
|
unsigned char byteBuffer;
|
|
for (int i = 0; i < messageCount; i++) {
|
|
qDebug("message #%i:", i);
|
|
stream >> byteBuffer; qDebug("type = %i", byteBuffer);
|
|
m_Message.type = MessageType(byteBuffer);
|
|
if (m_Message.type != Invalid) {
|
|
stream >> m_Message.timeout; qDebug("timeout = %i", m_Message.timeout);
|
|
stream >> m_Message.text; qDebug("text = %s", qPrintable(m_Message.text));
|
|
|
|
m_Messages.enqueue(m_Message);
|
|
}
|
|
}
|
|
nextMessage();
|
|
|
|
// overlaydata
|
|
for (int iy = 0; iy < m_Picture->height(); iy++) {
|
|
for (int ix = 0; ix < m_Picture->width(); ix++) {
|
|
stream >> byteBuffer;
|
|
m_OverlayData[ix][iy] = MarkerType(byteBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCrossFieldWidget::dumpState(QDataStream & stream) {
|
|
if (!m_OverlayData || !m_Picture)
|
|
return;
|
|
|
|
// error state
|
|
stream << m_ErrorAware;
|
|
stream << m_ErrorCount;
|
|
|
|
// time(out)
|
|
stream << m_Time;
|
|
|
|
// messages
|
|
// actually we should dump the message queue
|
|
// for now only dump last displayed
|
|
// TODO dump message queue
|
|
stream << 1; // dummy message count
|
|
stream << (unsigned char)(m_Message.type);
|
|
if (m_Message.type != Invalid) {
|
|
stream << m_Message.timeout;
|
|
stream << m_Message.text;
|
|
}
|
|
|
|
// overlaydata
|
|
for (int iy = 0; iy < m_Picture->height(); iy++) {
|
|
for (int ix = 0; ix < m_Picture->width(); ix++)
|
|
stream << (unsigned char)(m_OverlayData[ix][iy]);
|
|
}
|
|
}
|
|
|
|
//public slots
|
|
void CCrossFieldWidget::mark(int x, int y, int type) {
|
|
if (type == CMT_NONE || x < 0 || x >= m_Picture->width() || y < 0 || y >= m_Picture->height())
|
|
return;
|
|
|
|
MarkerType marker = static_cast<qcross::MarkerType>(type);
|
|
|
|
execMark(x, y, marker);
|
|
}
|
|
|
|
void CCrossFieldWidget::setTime(int value) {
|
|
if (value < 0)
|
|
value = 0;
|
|
|
|
if (m_Time != value) {
|
|
m_Time = value;
|
|
|
|
if (m_ErrorAware && !m_Time) {
|
|
killTimer(m_TimerId);
|
|
m_TimerId = -1;
|
|
m_Paused = true;
|
|
emit timeUp();
|
|
}
|
|
|
|
updateTimeDisplay();
|
|
|
|
emit timeChanged(m_Time);
|
|
}
|
|
}
|
|
|
|
void CCrossFieldWidget::setErrorAware(bool value) {
|
|
m_ErrorAware = value;
|
|
}
|
|
|
|
void CCrossFieldWidget::setNumbersMarkable(bool value) {
|
|
m_NumbersMarkable = value;
|
|
}
|
|
|
|
void CCrossFieldWidget::start() {
|
|
reset();
|
|
resume();
|
|
}
|
|
|
|
void CCrossFieldWidget::pause() {
|
|
if (m_Solved)
|
|
return;
|
|
|
|
killTimer(m_TimerId);
|
|
m_TimerId = -1;
|
|
|
|
if (m_Message.type != Invalid) {
|
|
m_Messages.enqueue(m_Message);
|
|
|
|
if (m_MessageTimeoutId != -1) {
|
|
killTimer(m_MessageTimeoutId);
|
|
m_MessageTimeoutId = -1;
|
|
}
|
|
}
|
|
|
|
m_Paused = true;
|
|
setEnabled(false);
|
|
}
|
|
|
|
void CCrossFieldWidget::resume() {
|
|
if (m_Solved)
|
|
return;
|
|
|
|
m_Paused = false;
|
|
setEnabled(true);
|
|
update();
|
|
m_TimerId = startTimer(1000);
|
|
}
|
|
|
|
//protected
|
|
void CCrossFieldWidget::nextMessage() {
|
|
if (m_MessageTimeoutId != -1)
|
|
killTimer(m_MessageTimeoutId);
|
|
|
|
m_MessageTimeoutId = -1;
|
|
|
|
if (m_Messages.isEmpty()) {
|
|
m_Message.type = Invalid;
|
|
// m_Notifier->hide();
|
|
// updateMetrics();
|
|
update();
|
|
return;
|
|
}
|
|
|
|
m_Message = m_Messages.dequeue();
|
|
update();
|
|
|
|
/* switch (m_Message.type) {
|
|
case Information:
|
|
m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxInformation).pixmap(22, 22));
|
|
break;
|
|
case Warning:
|
|
m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(22, 22));
|
|
break;
|
|
case Critical:
|
|
m_NotifierIcon->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(22, 22));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
m_NotifierText->setText(m_Message.text);
|
|
|
|
m_Notifier->show();
|
|
updateMetrics();*/
|
|
|
|
if (m_Message.timeout)
|
|
m_MessageTimeoutId = startTimer(m_Message.timeout);
|
|
}
|
|
|
|
void CCrossFieldWidget::initialize() {
|
|
m_OverlayData = new MarkerType *[m_Picture->width()];
|
|
for (int i = 0; i < m_Picture->width(); i++) {
|
|
m_OverlayData[i] = new MarkerType[m_Picture->height()];
|
|
for (int j = 0; j < m_Picture->height(); j++)
|
|
m_OverlayData[i][j] = CMT_UNMARKED;
|
|
}
|
|
|
|
int minimumW = max(m_Picture->maximumNumberCount()+1, 5);
|
|
int minimumH = minimumW;
|
|
|
|
minimumW += m_Picture->width();
|
|
minimumH += m_Picture->height();
|
|
|
|
int minimumBoxSize = max(fontMetrics().width(QString::number(m_Picture->height())), fontMetrics().width(QString::number(m_Picture->width())));
|
|
minimumBoxSize = max(minimumBoxSize, fontInfo().pixelSize() * 1.5);
|
|
|
|
minimumW *= minimumBoxSize;
|
|
minimumH *= minimumBoxSize;
|
|
|
|
setMinimumSize(minimumW, minimumH);
|
|
}
|
|
|
|
void CCrossFieldWidget::cleanup() {
|
|
qDebug("m_TimerId = %i m_MessageTimeoutId = %i", m_TimerId, m_MessageTimeoutId);
|
|
if (m_TimerId != -1) {
|
|
killTimer(m_TimerId);
|
|
m_TimerId = -1;
|
|
}
|
|
|
|
if (m_MessageTimeoutId != -1) {
|
|
killTimer(m_MessageTimeoutId);
|
|
m_MessageTimeoutId = -1;
|
|
}
|
|
|
|
if (m_OverlayData) {
|
|
for (int i = 0; i < m_Picture->width(); i++)
|
|
delete[] m_OverlayData[i];
|
|
delete[] m_OverlayData;
|
|
m_OverlayData = NULL;
|
|
}
|
|
}
|
|
|
|
void CCrossFieldWidget::reset() {
|
|
m_Messages.clear();
|
|
nextMessage();
|
|
|
|
for (int i = 0; i < m_Picture->width(); i++) {
|
|
for (int j = 0; j < m_Picture->height(); j++)
|
|
m_OverlayData[i][j] = CMT_UNMARKED;
|
|
}
|
|
|
|
m_Solved = false;
|
|
m_ErrorCount = 0;
|
|
m_LastErrorMark.setX(-1);
|
|
m_LastErrorMark.setY(-1);
|
|
m_RemainingPixels = m_Picture->blackPixels();
|
|
}
|
|
|
|
bool CCrossFieldWidget::checkNoError(int x, int y) {
|
|
return (m_OverlayData[x][y] == CMT_MARKED) || m_Picture->pixel(x, y);
|
|
}
|
|
|
|
void CCrossFieldWidget::timerEvent(QTimerEvent * event) {
|
|
if (event->timerId() == m_TimerId)
|
|
setTime(m_Time + (m_ErrorAware ? -1 : +1));
|
|
else if (event->timerId() == m_MessageTimeoutId)
|
|
nextMessage();
|
|
}
|
|
|
|
void CCrossFieldWidget::updateTimeDisplay() {
|
|
quint8 seconds = m_Time % 60;
|
|
quint8 minutes = m_Time / 60;
|
|
quint8 hours = minutes / 60;
|
|
minutes %= 60;
|
|
|
|
QString time("");
|
|
|
|
if (hours)
|
|
time += QString::number(hours) + ':';
|
|
|
|
if (minutes < 10)
|
|
time += '0';
|
|
|
|
time += QString::number(minutes) + ':';
|
|
|
|
if (seconds < 10)
|
|
time += '0';
|
|
|
|
time += QString::number(seconds);
|
|
|
|
m_Clock->display(time);
|
|
}
|
|
|
|
void CCrossFieldWidget::execMark(int x, int y, MarkerType & marker) {
|
|
switch (marker) {
|
|
case CMT_MARKED:
|
|
if (m_Picture->pixel(x, y)) {
|
|
m_RemainingPixels--;
|
|
m_OverlayData[x][y] = marker;
|
|
}
|
|
else {
|
|
m_ErrorCount++;
|
|
if (m_ErrorAware) {
|
|
m_OverlayData[x][y] = CMT_CROSSED;
|
|
marker = CMT_NONE;
|
|
m_LastErrorMark.setX(x);
|
|
m_LastErrorMark.setY(y);
|
|
emit markError();
|
|
}
|
|
else
|
|
m_OverlayData[x][y] = marker;
|
|
}
|
|
break;
|
|
case CMT_CROSSED:
|
|
case CMT_UNMARKED:
|
|
if (m_ErrorAware && x == m_LastErrorMark.x() && y == m_LastErrorMark.y()) {
|
|
m_LastErrorMark.setX(-1);
|
|
m_LastErrorMark.setY(-1);
|
|
}
|
|
|
|
if (m_OverlayData[x][y] == CMT_MARKED) {
|
|
if (m_Picture->pixel(x, y))
|
|
m_RemainingPixels++;
|
|
else if (!m_ErrorAware)
|
|
m_ErrorCount--;
|
|
}
|
|
|
|
m_OverlayData[x][y] = marker;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!m_RemainingPixels && (m_ErrorAware || !m_ErrorCount)) {
|
|
killTimer(m_TimerId);
|
|
m_TimerId = -1;
|
|
m_Paused = true;
|
|
m_Solved = true;
|
|
emit solved();
|
|
}
|
|
}
|
|
|
|
void CCrossFieldWidget::paintEvent(QPaintEvent *) {
|
|
QPainter painter(this);
|
|
|
|
if (!m_Picture) {
|
|
/* painter.drawText(originX, originY, m_BoxSize, m_BoxSize,
|
|
Qt::AlignVCenter | Qt::AlignCenter, QString::number(m_Picture->rowNumbers(i)[m_Picture->rowNumbers(i).size() - j]));*/
|
|
return;
|
|
}
|
|
|
|
int originX = m_OffsetX + m_HeaderWidth;
|
|
int originY = m_OffsetY + m_HeaderHeight;
|
|
|
|
int gridWidth = m_RasterWidth - m_HeaderWidth;
|
|
int gridHeight = m_RasterHeight - m_HeaderHeight;
|
|
|
|
// draw background
|
|
{
|
|
const int delta = 5 * m_BoxSize;
|
|
|
|
int offsetX = 0;
|
|
int offsetY;
|
|
int deltaX = delta;
|
|
int deltaY;
|
|
|
|
bool useBaseX;
|
|
bool useBaseY = true;
|
|
|
|
while (offsetX < gridWidth) {
|
|
if (gridWidth - offsetX < delta)
|
|
deltaX = gridWidth - offsetX;
|
|
|
|
offsetY = 0;
|
|
deltaY = delta;
|
|
|
|
useBaseX = useBaseY;
|
|
while (offsetY < gridHeight) {
|
|
if (gridHeight - offsetY < delta)
|
|
deltaY = gridHeight - offsetY;
|
|
|
|
painter.fillRect(originX + offsetX, originY + offsetY, deltaX, deltaY,
|
|
palette().color(useBaseX ? QPalette::Base : QPalette::AlternateBase));
|
|
|
|
useBaseX = !useBaseX;
|
|
|
|
offsetY += deltaY;
|
|
}
|
|
|
|
useBaseY = !useBaseY;
|
|
|
|
offsetX += deltaX;
|
|
}
|
|
}
|
|
|
|
// draw markers and crosses
|
|
{
|
|
QPen pen;
|
|
pen.setWidth(m_MarkerSize / 8);
|
|
painter.setPen(pen);
|
|
|
|
QRectF markerRect(m_MarkerOffset, m_MarkerOffset, m_MarkerSize, m_MarkerSize);
|
|
|
|
QColor markerColor = palette().color(QPalette::Highlight);
|
|
QColor errorColor = markerColor;
|
|
errorColor.setAlpha(128);
|
|
|
|
painter.setBrush(markerColor);
|
|
for (int i = 0; i < m_Picture->width(); i++) {
|
|
originX = m_OffsetX + m_HeaderWidth + i * m_BoxSize;
|
|
markerRect.moveLeft(originX + m_MarkerOffset);
|
|
|
|
for (int j = 0; j < m_Picture->height(); j++) {
|
|
originY = m_OffsetY + m_HeaderHeight + j * m_BoxSize;
|
|
markerRect.moveTop(originY + m_MarkerOffset);
|
|
|
|
switch (m_OverlayData[i][j]) {
|
|
case CMT_MARKED:
|
|
painter.fillRect(markerRect, painter.brush());
|
|
break;
|
|
case CMT_CROSSED:
|
|
if (m_Solved)
|
|
break;
|
|
|
|
if (m_ErrorAware && m_ErrorCount && i == m_LastErrorMark.x() && j == m_LastErrorMark.y()) {
|
|
painter.setBrush(errorColor);
|
|
painter.fillRect(markerRect, painter.brush());
|
|
painter.setBrush(markerColor);
|
|
}
|
|
|
|
painter.drawLine(markerRect.topLeft(), markerRect.bottomRight());
|
|
painter.drawLine(markerRect.bottomLeft(), markerRect.topRight());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// draw grid lines
|
|
painter.setPen(palette().color(QPalette::Dark));
|
|
|
|
for (int i = m_OffsetX + m_HeaderWidth; i < m_OffsetX + m_RasterWidth; i += m_BoxSize) {
|
|
painter.drawLine(i, m_OffsetY + m_HeaderHeight, i, m_OffsetY + m_RasterHeight-1);
|
|
}
|
|
|
|
for (int i = m_OffsetY + m_HeaderHeight; i < m_OffsetY + m_RasterHeight; i += m_BoxSize) {
|
|
painter.drawLine(m_OffsetX + m_HeaderWidth, i, m_OffsetX + m_RasterWidth-1, i);
|
|
}
|
|
|
|
// draw numbers area
|
|
if (m_Paused)
|
|
painter.setPen(palette().color(QPalette::Shadow));
|
|
|
|
QFont font = painter.font();
|
|
font.setPixelSize(m_MarkerSize * 0.9);
|
|
|
|
painter.setFont(font);
|
|
|
|
for (int i = 0; i < m_Picture->width(); i++) {
|
|
originX = m_OffsetX + m_HeaderWidth + i * m_BoxSize;
|
|
painter.fillRect(originX, m_OffsetY, m_BoxSize, m_HeaderHeight, palette().color((i % 2) ? QPalette::AlternateBase : QPalette::Base));
|
|
if (!m_Paused) {
|
|
painter.setPen(palette().color(QPalette::WindowText));
|
|
for (int j = 1; j <= m_Picture->columnNumbers(i).size(); j++) {
|
|
originY = m_OffsetY + m_HeaderHeight - j * m_BoxSize;
|
|
|
|
painter.drawText(originX, originY, m_BoxSize, m_BoxSize,
|
|
Qt::AlignVCenter | Qt::AlignCenter, QString::number(m_Picture->columnNumbers(i)[m_Picture->columnNumbers(i).size() - j]));
|
|
}
|
|
painter.setPen(palette().color(QPalette::Shadow));
|
|
}
|
|
if (!(i % 5))
|
|
painter.drawLine(originX, m_OffsetY, originX, m_OffsetY + m_RasterHeight-1);
|
|
}
|
|
// painter.drawLine(m_OffsetX + m_RasterWidth, m_OffsetY, m_OffsetX + m_RasterWidth, m_OffsetY + m_RasterHeight);
|
|
|
|
for (int i = 0; i < m_Picture->height(); i++) {
|
|
originY = m_OffsetY + m_HeaderHeight + i * m_BoxSize;
|
|
painter.fillRect(m_OffsetX, originY, m_HeaderWidth, m_BoxSize, palette().color((i % 2) ? QPalette::AlternateBase : QPalette::Base));
|
|
if (!m_Paused) {
|
|
painter.setPen(palette().color(QPalette::WindowText));
|
|
for (int j = 1; j <= m_Picture->rowNumbers(i).size(); j++) {
|
|
originX = m_OffsetX + m_HeaderWidth - j * m_BoxSize;
|
|
painter.drawText(originX, originY, m_BoxSize, m_BoxSize,
|
|
Qt::AlignVCenter | Qt::AlignCenter, QString::number(m_Picture->rowNumbers(i)[m_Picture->rowNumbers(i).size() - j]));
|
|
}
|
|
painter.setPen(palette().color(QPalette::Shadow));
|
|
}
|
|
if (!(i % 5))
|
|
painter.drawLine(m_OffsetX, originY, m_OffsetX + m_RasterWidth-1, originY);
|
|
}
|
|
|
|
// draw message if needed
|
|
if (m_Message.type != Invalid) {
|
|
QRect boxrect(m_HeaderWidth + m_OffsetX, m_HeaderHeight + m_OffsetY, m_RasterWidth - m_HeaderWidth, m_RasterHeight - m_HeaderHeight);
|
|
|
|
QColor fillColor = palette().color(QPalette::Base);
|
|
fillColor.setAlpha(220);
|
|
painter.fillRect(boxrect, fillColor);
|
|
|
|
font.setPixelSize(font.pixelSize() * 2);
|
|
|
|
painter.setFont(font);
|
|
painter.drawText(boxrect, Qt::AlignVCenter | Qt::AlignCenter | Qt::TextWordWrap, m_Message.text);
|
|
}
|
|
}
|
|
|
|
/* void CCrossFieldWidget::updateCell(int x, int y) {
|
|
QPainter painter(this);
|
|
int originX, originY;
|
|
originX = m_OffsetX + m_HeaderWidth + x * m_BoxSize;
|
|
originY = m_OffsetY + m_HeaderHeight + y * m_BoxSize;
|
|
painter.fillRect(originX + 1, originY + 1, m_BoxSize - 2, m_BoxSize - 2, palette().color(QPalette::Base));
|
|
switch (m_OverlayData[x][y]) {
|
|
case CMT_MARKED:
|
|
painter.drawRect(originX + 2, originY + 2, m_BoxSize - 4, m_BoxSize - 4);
|
|
break;
|
|
case CMT_CROSSED:
|
|
painter.drawLine(originX + 2, originY + 2, originX + m_BoxSize - 2, originY + m_BoxSize - 2);
|
|
painter.drawLine(originX + 2, originY + m_BoxSize - 2, originX + m_BoxSize - 2, originY + 2);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}*/
|
|
|
|
void CCrossFieldWidget::resizeEvent(QResizeEvent * /*event*/) {
|
|
if (!m_Picture)
|
|
return;
|
|
|
|
updateMetrics();
|
|
}
|
|
|
|
void CCrossFieldWidget::updateMetrics() {
|
|
m_HeaderWidth = max(m_Picture->maximumNumberCount()+1, 5);
|
|
/* m_HeaderWidth = max(m_Picture->width() / 2 + 1, m_Picture->height() / 2 + 1);
|
|
m_HeaderWidth = m_Picture->width() / 2 + 1;
|
|
m_HeaderHeight = m_Picture->height() / 2 + 1;*/
|
|
|
|
int fieldsize = min((m_Picture->width() + m_HeaderWidth), (m_Picture->height() + m_HeaderWidth));
|
|
int widgetsize = min(width(), height());
|
|
|
|
m_BoxSize = ((double)widgetsize / fieldsize);
|
|
/*min((double)width() / (m_Picture->width() + m_HeaderWidth), (double)height() / (m_Picture->height() + m_HeaderWidth));*/
|
|
|
|
m_MarkerSize = m_BoxSize * 2.0/3.0;
|
|
m_MarkerOffset = ((m_BoxSize - m_MarkerSize) / 2.0);
|
|
|
|
m_HeaderWidth *= m_BoxSize;
|
|
m_HeaderHeight = m_HeaderWidth;
|
|
|
|
m_RasterWidth = m_BoxSize * m_Picture->width() + m_HeaderWidth;
|
|
m_RasterHeight = m_BoxSize * m_Picture->height() + m_HeaderHeight;
|
|
|
|
m_OffsetX = (width() - m_RasterWidth) / 2;
|
|
m_OffsetY = (height() - m_RasterHeight) / 2;
|
|
|
|
int clockHeight = /*m_Notifier->isVisible() ? m_HeaderHeight - m_Notifier->sizeHint().height()*/ /* * 3.0 / 4.0 */ /*:*/ m_HeaderHeight;
|
|
|
|
if (m_Clock)
|
|
m_Clock->setGeometry(m_OffsetX, m_OffsetY, m_HeaderWidth, clockHeight);
|
|
// if (m_Notifier && m_Notifier->isVisible())
|
|
// m_Notifier->setGeometry(m_OffsetX, m_OffsetY + clockHeight, m_HeaderWidth, m_Notifier->sizeHint().height());
|
|
}
|
|
|
|
void CCrossFieldWidget::mousePressEvent(QMouseEvent * event) {
|
|
if (m_Paused)
|
|
return;
|
|
|
|
int pressedX = event->x() - m_OffsetX;
|
|
int pressedY = event->y() - m_OffsetY;
|
|
|
|
if (pressedX < m_HeaderWidth || pressedY < m_HeaderHeight || pressedX >= m_RasterWidth || pressedY >= m_RasterHeight)
|
|
return;
|
|
|
|
pressedX = (pressedX - m_HeaderWidth) / m_BoxSize;
|
|
pressedY = (pressedY - m_HeaderHeight) / m_BoxSize;
|
|
|
|
|
|
if (event->button() == Qt::RightButton)
|
|
m_MouseMark = CMT_CROSSED;
|
|
else
|
|
m_MouseMark = CMT_MARKED;
|
|
|
|
if (m_OverlayData[pressedX][pressedY] == m_MouseMark)
|
|
m_MouseMark = CMT_UNMARKED;
|
|
|
|
execMark(pressedX, pressedY, m_MouseMark);
|
|
update();
|
|
}
|
|
|
|
void CCrossFieldWidget::mouseMoveEvent(QMouseEvent * event) {
|
|
if (m_Paused)
|
|
return;
|
|
|
|
if (m_MouseMark == CMT_NONE)
|
|
return;
|
|
|
|
int pressedX = event->x() - m_OffsetX;
|
|
int pressedY = event->y() - m_OffsetY;
|
|
|
|
if (pressedX < m_HeaderWidth || pressedY < m_HeaderHeight || pressedX >= m_RasterWidth || pressedY >= m_RasterHeight)
|
|
return;
|
|
|
|
pressedX = (pressedX - m_HeaderWidth) / m_BoxSize;
|
|
pressedY = (pressedY - m_HeaderHeight) / m_BoxSize;
|
|
|
|
if (m_OverlayData[pressedX][pressedY] != m_MouseMark) {
|
|
execMark(pressedX, pressedY, m_MouseMark);
|
|
update();
|
|
}
|
|
}
|
|
|
|
void CCrossFieldWidget::mouseReleaseEvent(QMouseEvent *) {
|
|
m_MouseMark = CMT_NONE;
|
|
}
|
|
}
|