commit 6aa6b59c8896f84cd95b8dfff7016a74de2e21f5 Author: Oliver Groß Date: Wed Jun 16 14:53:56 2010 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6f5a05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +build +Makefile* +ui +moc_* +qcrosssuite.kde* +qcrosssuite.pro.* +Doxyfile diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..94de1cc --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +project(qcrosssuite) +cmake_minimum_required(VERSION 2.8) + +MACRO(ADD_TARGET_PROPERTIES _target _name) + SET(_properties) + FOREACH(_prop ${ARGN}) + SET(_properties "${_properties} ${_prop}") + ENDFOREACH(_prop) + GET_TARGET_PROPERTY(_old_properties ${_target} ${_name}) + MESSAGE(STATUS "adding property to ${_target} ${_name}:" ${_properties}) + IF(NOT _old_properties) + # in case it's NOTFOUND + SET(_old_properties) + ENDIF(NOT _old_properties) + SET_TARGET_PROPERTIES(${_target} PROPERTIES ${_name} "${_old_properties} ${_properties}") +ENDMACRO(ADD_TARGET_PROPERTIES) + +set(DEBUG_FLAGS "-Wall -Wno-long-long -pedantic") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${DEBUG_FLAGS}") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${DEBUG_FLAGS}") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEBUG_FLAGS}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${DEBUG_FLAGS}") + +add_subdirectory(libqnono libqcross) + +add_subdirectory(qcross qcross) +add_dependencies(qcross qnono) + +add_subdirectory(qcrossedit qcrossedit) +add_dependencies(qcrossedit qnono) diff --git a/libqnono/.gitignore b/libqnono/.gitignore new file mode 100644 index 0000000..b8debb4 --- /dev/null +++ b/libqnono/.gitignore @@ -0,0 +1,8 @@ +build +Makefile* +ui +moc_* +libqcross.a +libqcross.so* +Doxyfile +libqcross.pro.* diff --git a/libqnono/CMakeLists.txt b/libqnono/CMakeLists.txt new file mode 100644 index 0000000..68aa1e0 --- /dev/null +++ b/libqnono/CMakeLists.txt @@ -0,0 +1,29 @@ +project(qnono) +cmake_minimum_required(VERSION 2.8) + +find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) + +include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}) +include(${QT_USE_FILE}) + +set(SOURCES_MOC_H + cnonogramsolver.h + ccrosspackagemodel.h + ccrosspackagelistmodel.h +) + +set(SOURCES_CPP + cnonogram.cpp + cnonogramsolver.cpp + ccrosspackage.cpp + ccrosspackagemodel.cpp + ccrosspackagelistmodel.cpp +) + +qt4_wrap_cpp(SOURCES_MOC_CPP ${SOURCES_MOC_H}) + +add_library(${PROJECT_NAME} STATIC ${SOURCES_CPP} ${SOURCES_MOC_CPP}) + +target_link_libraries(${PROJECT_NAME} + ${QT_LIBRARIES} +) diff --git a/libqnono/ccrosspackage.cpp b/libqnono/ccrosspackage.cpp new file mode 100644 index 0000000..7a45abd --- /dev/null +++ b/libqnono/ccrosspackage.cpp @@ -0,0 +1,269 @@ +/*************************************************************************** + * 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 "ccrosspackage.h" +#include "cnonogram.h" +#include +#include + +namespace libqcross { +//public: + CCrossPackage::CCrossPackage() {} + CCrossPackage::CCrossPackage(QString fileName) : m_FileName(fileName) {} + + CCrossPackage::~CCrossPackage() { + foreach (CNonogram * i, m_PictureList) { + delete i; + } + } + + bool CCrossPackage::open() { + if (m_FileName.isEmpty()) + return false; + + qDebug("opening file: %s", m_FileName.toAscii().data()); + QFile file(m_FileName); + if (!file.open(QIODevice::ReadOnly)) + return false; + + QDataStream in(&file); + in.setVersion(QDataStream::Qt_4_0); + + QString stringBuffer; +// qint32 intBuffer; + QSize sizeBuffer; + +// CNonogram * newPicture = NULL; + +// qint32 pictureCount = 0; + + if (in.atEnd()) { + qCritical("invalid package file - no header"); + file.close(); + return false; + } + in >> stringBuffer; + + if ((stringBuffer != "QCROSSPACKAGE")) { + qCritical("invalid package file - invalid header: %s", stringBuffer.toAscii().data()); + file.close(); + return false; + } + + if (in.atEnd()) { + qCritical("invalid package file - no package name"); + file.close(); + return false; + } + in >> m_Name; + + file.close(); + return true; + } + + bool CCrossPackage::readAll() { + if (m_FileName.isEmpty()) + return false; + + qDebug("reading file: %s", m_FileName.toAscii().data()); + QFile file(m_FileName); + if (!file.open(QIODevice::ReadOnly)) + return false; + + m_PictureList.clear(); + + QDataStream in(&file); + in.setVersion(QDataStream::Qt_4_0); + + QString stringBuffer; + qint32 intBuffer; + QSize sizeBuffer; + + CNonogram * newPicture = NULL; + + qint32 pictureCount = 0; + + if (in.atEnd()) { + qCritical("invalid package file - no header"); + file.close(); + return false; + } + in >> stringBuffer; + + if ((stringBuffer != "QCROSSPACKAGE")) { + qCritical("invalid package file - invalid header: %s", stringBuffer.toAscii().data()); + file.close(); + return false; + } + + if (in.atEnd()) { + qCritical("invalid package file - no package name"); + file.close(); + return false; + } + in >> stringBuffer; + + if (in.atEnd()) { + qCritical("invalid package file - no picture count"); + file.close(); + return false; + } + in >> pictureCount; + + unsigned char data; + int i; + for (i = 0; i < pictureCount && !in.atEnd(); i++) { + in >> stringBuffer; + qDebug("reading image: %s", stringBuffer.toAscii().data()); + if (in.atEnd()) { + qCritical("invalid package file - no picture name"); + file.close(); + return false; + } + + in >> intBuffer; + qDebug("width %i", intBuffer); + if (in.atEnd()) { + qCritical("invalid package file - no picture width"); + file.close(); + return false; + } + + sizeBuffer.setWidth(intBuffer); + + in >> intBuffer; + qDebug("height %i", intBuffer); + if (in.atEnd()) { + qCritical("invalid package file - no picture height"); + file.close(); + return false; + } + + sizeBuffer.setHeight(intBuffer); + + newPicture = new CNonogram(sizeBuffer); + newPicture->setName(stringBuffer); + + in >> intBuffer; + qDebug("timeout %i", intBuffer); + if (in.atEnd()) { + qCritical("invalid package file - no picture timeout"); + delete newPicture; + file.close(); + return false; + } + + newPicture->setTimeout(intBuffer); + + for (int x = 0; x < sizeBuffer.width(); x++) { + int y = 0; + + while (y < sizeBuffer.height()) { + if (in.atEnd()) { + qCritical("invalid package file - data"); + delete newPicture; + file.close(); + return false; + } + + in.readRawData((char *)&data, 1); + + int b; + for (b = 0; b < 8; b++) { + if (y < sizeBuffer.height()) + newPicture->setPixel(x, y, (bool)(data & 0x80)); + data = data << 1; + y++; + } + + +// out.writeRawData((char *)&data, 1); +// newPicture->setPixel(x, y, (bool)(data & 0x80)); +// data = data << 1; +// y++; +// if (!(y % 8)) +// in.readRawData((char *)&data, 1); + } + } + + + m_PictureList << newPicture; + } + + if (i < pictureCount) + qWarning("damaged package file - invalid picture count"); + + file.close(); + return true; + } + + bool CCrossPackage::save() { + QFile file(m_FileName); + if (!file.open(QIODevice::WriteOnly)) + return false; + + QDataStream out(&file); + out.setVersion(QDataStream::Qt_4_0); + + out << QString("QCROSSPACKAGE"); + out << m_Name; + out << (qint32)(m_PictureList.size()); + + unsigned char data = 0; + + foreach (CNonogram * i, m_PictureList) { + out << i->name(); + out << (qint32)i->width(); + out << (qint32)i->height(); + out << (qint32)i->timeout(); + + for (int x = 0; x < i->width(); x++) { + data = 0x00; + int y = 0; + while (y < i->height()) { + int b; + for (b = 0; b < 8; b++) { + data = data << 1; + if (y < i->height() && i->pixel(x, y)) + data |= 0x01; + y++; + } + + out.writeRawData((char *)&data, 1); + +// if (i->pixel(x, y)) +// data |= 0x01; +// +// y++; +// if (!(y % 8)) { +// out.writeRawData((char *)&data, 1); +// data = 0x00; +// } +// +// data = data << 1; + } +// if (y % 8) +// out.writeRawData((char *)&data, 1); + } + } + + file.close(); + return true; + } +} diff --git a/libqnono/ccrosspackage.h b/libqnono/ccrosspackage.h new file mode 100644 index 0000000..1b83575 --- /dev/null +++ b/libqnono/ccrosspackage.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef LIBQCROSS_CCROSSPACKAGE_H +#define LIBQCROSS_CCROSSPACKAGE_H + +#include +#include + +namespace libqcross { + class CNonogram; + + typedef QList QMonoPictureList; + + class CCrossPackage { + public: + CCrossPackage(); + CCrossPackage(QString fileName); + ~CCrossPackage(); + + virtual void setFileName(QString & value) { m_FileName = value; } + QString fileName() const { return m_FileName; } + + void setName(QString value) { m_Name = value; } + QString name() const { return m_Name; } + + virtual bool open(); + virtual bool readAll(); + virtual bool save(); + + QMonoPictureList & pictures() { return m_PictureList; } + private: + QMonoPictureList m_PictureList; + QString m_FileName; + QString m_Name; + }; +} + +#endif diff --git a/libqnono/ccrosspackagelistmodel.cpp b/libqnono/ccrosspackagelistmodel.cpp new file mode 100644 index 0000000..1f6575b --- /dev/null +++ b/libqnono/ccrosspackagelistmodel.cpp @@ -0,0 +1,97 @@ +/*************************************************************************** + * 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 +#include "ccrosspackage.h" +#include "cnonogram.h" +#include "ccrosspackagelistmodel.h" + +namespace libqcross { +//public: + CCrossPackageListModel::CCrossPackageListModel(QString dataPath, QObject * parent) : QAbstractItemModel(parent), + m_DataPath(dataPath) { + update(); + } + + CCrossPackageListModel::~CCrossPackageListModel() { + foreach (CCrossPackage * i, m_PackageList) + delete i; + } + + void CCrossPackageListModel::update() { + foreach (CCrossPackage * i, m_PackageList) + delete i; + + m_PackageList.clear(); + + CCrossPackage * newPackage; + + QDir workDir(m_DataPath); + QStringList fileNames = workDir.entryList(QStringList("*.cpk"), QDir::Files | QDir::NoDotAndDotDot, QDir::Name); + foreach (QString fileName, fileNames) { + newPackage = new CCrossPackage(workDir.filePath(fileName)); + if (newPackage->open()) + m_PackageList << newPackage; + else + delete newPackage; + } + + reset(); + } + + QModelIndex CCrossPackageListModel::index(int row, int column, const QModelIndex & /*parent*/) const { + return (column > 0) || (row < 0) || (row >= m_PackageList.size()) ? + QModelIndex() : + createIndex(row, column, static_cast(m_PackageList[row])); + } + + QVariant CCrossPackageListModel::data(const QModelIndex & index, int role) const { + if (!index.isValid()) + return QVariant(); + + if (role == Qt::DisplayRole) + return static_cast(index.internalPointer())->name(); + else + return QVariant(); + } + + int CCrossPackageListModel::rowCount(const QModelIndex & /*parent*/) const { + return m_PackageList.size(); + } + + int CCrossPackageListModel::columnCount(const QModelIndex & /*parent*/) const { + return 1; + } + + QVariant CCrossPackageListModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const { + return QVariant(); + } + +// Qt::ItemFlags CCrossPackageListModel::flags(const QModelIndex & index) const { +// return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; +// } + + QModelIndex CCrossPackageListModel::parent(const QModelIndex &) const { + return QModelIndex(); + } + + bool CCrossPackageListModel::hasChildren(const QModelIndex & parent) const { + return !parent.isValid(); + } +} diff --git a/libqnono/ccrosspackagelistmodel.h b/libqnono/ccrosspackagelistmodel.h new file mode 100644 index 0000000..1fa9484 --- /dev/null +++ b/libqnono/ccrosspackagelistmodel.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef LIBCCROSS_CCROSSPACKAGELISTMODEL_H +#define LIBCCROSS_CCROSSPACKAGELISTMODEL_H + +#include +#include + +namespace libqcross { + class CCrossPackage; + + /** + @author Oliver Groß + */ + class CCrossPackageListModel : public QAbstractItemModel { + Q_OBJECT + public: + CCrossPackageListModel(QString dataPath, QObject * parent = 0); + ~CCrossPackageListModel(); + + void update(); + + virtual QModelIndex index(int row, int column = 0, const QModelIndex & parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; + virtual int rowCount(const QModelIndex & parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex & parent = QModelIndex()) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; +// virtual Qt::ItemFlags flags(const QModelIndex & index) const; + virtual QModelIndex parent(const QModelIndex & index) const; + virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const; + private: + QString m_DataPath; + + QList m_PackageList; + }; +} + +#endif diff --git a/libqnono/ccrosspackagemodel.cpp b/libqnono/ccrosspackagemodel.cpp new file mode 100644 index 0000000..0accb94 --- /dev/null +++ b/libqnono/ccrosspackagemodel.cpp @@ -0,0 +1,245 @@ +/*************************************************************************** + * 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 +#include + +#include "ccrosspackage.h" +#include "cnonogram.h" +#include "ccrosspackagemodel.h" +#include "constants.h" + +#define COL_NAME 0 +#define COL_TIME 1 + +namespace libqcross { + QString formatedTime(quint32 seconds, bool showSeconds = false) { + quint32 strippedSeconds = seconds % 60; + quint8 minutes = seconds / 60; + quint8 hours = minutes / 60; + + QString result; + + if (hours) { + if (hours < 10) + result += '0'; + result += QString::number(hours); + result += ':'; + } + + minutes %= 60; + + if (minutes < 10) + result += '0'; + result += QString::number(minutes); + + if (showSeconds) { + result += ':'; + if (strippedSeconds < 10) + result += '0'; + result += QString::number(strippedSeconds); + } + return result; + } + +//public: + CCrossPackageModel::CCrossPackageModel(QObject * parent) : QAbstractItemModel(parent), + m_Package(NULL) { + } + + CCrossPackageModel::~CCrossPackageModel() { + setPackage(NULL); + } + + void CCrossPackageModel::setPackage(libqcross::CCrossPackage * package) { + if (m_Package) + m_Package->pictures().clear(); + + m_Package = package; + + if (m_Package && m_Package->pictures().isEmpty()) + m_Package->readAll(); + + reset(); + } + + QModelIndex CCrossPackageModel::index(int row, int column, const QModelIndex & /*parent*/) const { + return (m_Package) && (column >= 0) && (row >= 0) && (row < m_Package->pictures().size()) ? + createIndex(row, column, static_cast(m_Package->pictures()[row])) : + QModelIndex(); + } + + QVariant CCrossPackageModel::data(const QModelIndex & index, int role) const { + if (!index.isValid()) + return QVariant(); + + switch (index.column()) { + case COL_NAME: + switch (role) { + case Qt::DecorationRole: + return static_cast(index.internalPointer())->timeout() ? + QIcon(LIBQCROSS_ICON_TIMEOUT) : + QIcon(LIBQCROSS_ICON_TIMETRIAL); + case Qt::EditRole: + case Qt::DisplayRole: + return static_cast(index.internalPointer())->name(); + default: + break; + } + break; + case COL_TIME: + if (role == Qt::DisplayRole) + return formatedTime(static_cast(index.internalPointer())->timeout()); + break; + default: + break; + } + return QVariant(); + } + + int CCrossPackageModel::rowCount(const QModelIndex & parent) const { + if (m_Package && !parent.isValid()) + return m_Package->pictures().size(); + else + return 0; + } + + int CCrossPackageModel::columnCount(const QModelIndex & /*parent*/) const { + return 2; + } + + QVariant CCrossPackageModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const { + if (role == Qt::DisplayRole) { + switch (section) { + case COL_NAME: + return tr("Nonogram"); + case COL_TIME: + return tr("Time"); + default: + break; + } + } + + return QVariant(); + } + + Qt::ItemFlags CCrossPackageModel::flags(const QModelIndex & index) const { + if (index.column() == COL_NAME) + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; + else + return QAbstractItemModel::flags(index); + } + + QModelIndex CCrossPackageModel::parent(const QModelIndex &) const { + return QModelIndex(); + } + + bool CCrossPackageModel::hasChildren(const QModelIndex & parent) const { + return m_Package && !parent.isValid(); + } + + bool CCrossPackageModel::setData(const QModelIndex & index, const QVariant & value, int role) { + if (index.isValid() && role == Qt::EditRole) { + QString name = value.toString(); + if (name.isEmpty()) + return false; + + foreach (CNonogram * i, m_Package->pictures()) { + if (i->name() == name) + return false; + } + + m_Package->pictures()[index.row()]->setName(name); + emit dataChanged(index, index); + return true; + } + return false; + } + + bool CCrossPackageModel::appendEmpty(QString name, QSize size, bool fillValue) { + if (!m_Package) + return false; + + beginInsertRows(QModelIndex(), m_Package->pictures().size(), 1); + + CNonogram * newNonogram = new CNonogram(size); + newNonogram->fill(fillValue); + newNonogram->setName(name); + + m_Package->pictures() << newNonogram; + + endInsertRows(); + return true; + } + + bool CCrossPackageModel::appendImage(QString name, QImage image) { + if (!m_Package) + return false; + + CNonogram * newNonogram = new CNonogram(); + newNonogram->loadFromImage(image); + newNonogram->setName(name); + newNonogram->setTimeout(60*60); // set an hour as default timeout + + if (newNonogram->isValid()) { + beginInsertRows(QModelIndex(), m_Package->pictures().size(), 1); + + m_Package->pictures() << newNonogram; + + endInsertRows(); + return true; + } + else { + delete newNonogram; + return false; + } + } + + bool CCrossPackageModel::insertRows(int row, int count, const QModelIndex & parent) { + if (!m_Package) + return false; + + beginInsertRows(parent, row, count); + + CNonogram * newNonogram; + + for (int i = row; i < row+count; ++i) { + newNonogram = new CNonogram(); + newNonogram->fill(false); + m_Package->pictures() << newNonogram; + } + + endInsertRows(); + return true; + } + + bool CCrossPackageModel::removeRows(int row, int count, const QModelIndex & parent) { + if (!m_Package) + return false; + + beginRemoveRows(parent, row, row+count-1); + + for (int i = row; i < row+count; ++i) + delete m_Package->pictures().takeAt(i); + + endRemoveRows(); + return true; + } + +} diff --git a/libqnono/ccrosspackagemodel.h b/libqnono/ccrosspackagemodel.h new file mode 100644 index 0000000..629f360 --- /dev/null +++ b/libqnono/ccrosspackagemodel.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef LIBQCROSS_CCROSSPACKAGEMODEL_H +#define LIBQCROSS_CCROSSPACKAGEMODEL_H + +#include + +namespace libqcross { + class CCrossPackage; + + /** + @author Oliver Groß + */ + class CCrossPackageModel : public QAbstractItemModel { + Q_OBJECT + public: + CCrossPackageModel(QObject * parent = 0); + ~CCrossPackageModel(); + + void setPackage(libqcross::CCrossPackage * package); + + virtual QModelIndex index(int row, int column = 0, const QModelIndex & parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; + virtual int rowCount(const QModelIndex & parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex & parent = QModelIndex()) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual Qt::ItemFlags flags(const QModelIndex & index) const; + virtual QModelIndex parent(const QModelIndex & index) const; + virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const; + + virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole); + + bool appendEmpty(QString name, QSize size, bool fillValue); + bool appendImage(QString name, QImage image); + + virtual bool insertRows(int row, int count, const QModelIndex & parent = QModelIndex()); + virtual bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex()); + protected: + libqcross::CCrossPackage * m_Package; + }; +} + +#endif diff --git a/libqnono/cnonogram.cpp b/libqnono/cnonogram.cpp new file mode 100644 index 0000000..6a664fc --- /dev/null +++ b/libqnono/cnonogram.cpp @@ -0,0 +1,133 @@ +/*************************************************************************** + * 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 "cnonogram.h" +#include + +namespace libqcross { + CNonogram::CNonogram() + : m_Size(0, 0), + m_Data(NULL), + m_Timeout(0), + m_MaximumNumberCount(0) { + } + + CNonogram::CNonogram(QSize size) : m_Size(size), m_MaximumNumberCount(0) { + init(); + } + + CNonogram::~CNonogram() { + cleanup(); + } + + void CNonogram::loadFromImage(QImage & image) { + if (image.isNull()) + return; + + resize(image.size()); + + for (int i = 0; i < m_Size.width(); i++) + for (int j = 0; j < m_Size.height(); j++) + m_Data[i][j] = !(image.pixel(i, j) & 0x00FFFFFF); + } + + void CNonogram::resize(QSize size) { + if (m_Data) + cleanup(); + + m_Size = size; + init(); + } + + void CNonogram::setPixel(int x, int y, bool value) { + m_Data[x][y] = value; + } + + void CNonogram::updateNumbers() { + m_BlackPixels = 0; + int pixelCount; + + m_MaximumNumberCount = 0; + + for (int i = 0; i < m_Size.height(); i++) { + m_RowNumbers[i].clear(); + pixelCount = 0; + for (int j = 0; j < m_Size.width(); j++) { + if (m_Data[j][i]) { + pixelCount++; + m_BlackPixels++; + } + else if (pixelCount) { + m_RowNumbers[i] << pixelCount; + pixelCount = 0; + } + } + if (pixelCount || m_RowNumbers[i].empty()) + m_RowNumbers[i] << pixelCount; + + if (m_RowNumbers[i].count() > m_MaximumNumberCount) + m_MaximumNumberCount = m_RowNumbers[i].count(); + } + + for (int j = 0; j < m_Size.width(); j++) { + m_ColumnNumbers[j].clear(); + pixelCount = 0; + for (int i = 0; i < m_Size.height(); i++) { + if (m_Data[j][i]) { + pixelCount++; + } + else if (pixelCount) { + m_ColumnNumbers[j] << pixelCount; + pixelCount = 0; + } + } + if (pixelCount || m_ColumnNumbers[j].empty()) + m_ColumnNumbers[j] << pixelCount; + + if (m_ColumnNumbers[j].count() > m_MaximumNumberCount) + m_MaximumNumberCount = m_ColumnNumbers[j].count(); + } + } + + void CNonogram::fill(bool value) { + for (int i = 0; i < m_Size.width(); i++) + for (int j = 0; j < m_Size.height(); j++) + m_Data[i][j] = value; + } + + void CNonogram::cleanup() { + delete[] m_RowNumbers; + delete[] m_ColumnNumbers; + + for (int i = 0; i < m_Size.width(); i++) + delete[] m_Data[i]; + delete[] m_Data; + + m_Data = NULL; + } + + void CNonogram::init() { + m_Data = new bool *[m_Size.width()]; + for (int i = 0; i < m_Size.width(); i++) + m_Data[i] = new bool[m_Size.height()]; + + m_RowNumbers = new NumbersVector[m_Size.height()]; + m_ColumnNumbers = new NumbersVector[m_Size.width()]; + } +} diff --git a/libqnono/cnonogram.h b/libqnono/cnonogram.h new file mode 100644 index 0000000..ae3ab11 --- /dev/null +++ b/libqnono/cnonogram.h @@ -0,0 +1,84 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef LIBQCROSS_CMONOPICTURE_H +#define LIBQCROSS_CMONOPICTURE_H + +#include +#include +#include + +class QImage; + +namespace libqcross { + class CNonogram { + public: + typedef QVector NumbersVector; + + CNonogram(); + CNonogram(QSize size); + ~CNonogram(); + + void loadFromImage(QImage & image); + void resize(QSize size); + + QString name() const { return m_Name; } + void setName(QString value) { m_Name = value; } + + quint16 timeout() const { return m_Timeout; } + void setTimeout(quint16 value) { m_Timeout = value; } + + int width() const { return m_Size.width(); } + int height() const { return m_Size.height(); } + + bool pixel(int x, int y) const { return m_Data[x][y]; } + void setPixel(int x, int y, bool value); + + NumbersVector & rowNumbers(int index) const { return m_RowNumbers[index]; } + NumbersVector & columnNumbers(int index) const { return m_ColumnNumbers[index]; } + + int maximumNumberCount() const { return m_MaximumNumberCount; } + + quint32 blackPixels() const { return m_BlackPixels; } + + void updateNumbers(); + + void fill(bool value); + + bool isValid() const { return m_Data; } + + protected: + QSize m_Size; + + bool ** m_Data; + + QString m_Name; + quint16 m_Timeout; + + NumbersVector * m_RowNumbers; + NumbersVector * m_ColumnNumbers; + quint32 m_BlackPixels; + int m_MaximumNumberCount; + + void cleanup(); + void init(); + }; +} + +#endif diff --git a/libqnono/cnonogramsolver.cpp b/libqnono/cnonogramsolver.cpp new file mode 100644 index 0000000..161c786 --- /dev/null +++ b/libqnono/cnonogramsolver.cpp @@ -0,0 +1,65 @@ +#include "cnonogramsolver.h" +#include "cnonogram.h" + +namespace libqcross { + CNonogramSolver::CNonogramSolver(QObject * parent) : QObject(parent), m_Nonogram(NULL), m_OverlayData(NULL) { + } + + CNonogramSolver::~CNonogramSolver() { + cleanup(); + } + + bool CNonogramSolver::solve() { + if (!m_Nonogram) + return false; + + cleanup(); + + m_OverlayData = new int *[m_Nonogram->width()]; + for (int i = 0; i < m_Nonogram->width(); i++) { + m_OverlayData[i] = new int[m_Nonogram->height()]; + for (int j = 0; j < m_Nonogram->height(); j++) + m_OverlayData[i][j] = 0; + } + + for (int i = 0; i < m_Nonogram->height(); i++) + solveRow(i); + + return false; + } + + void CNonogramSolver::cleanup() { + if (m_OverlayData && m_Nonogram) { + for (int i = 0; i < m_Nonogram->width(); i++) + delete[] m_OverlayData[i]; + delete[] m_OverlayData; + } + } + + bool CNonogramSolver::solveRow(int /*y*/) { + return false; +// int left = 0; +// int right = m_Nonogram->width()-1; +// +// foreach (int k, m_Nonogram->rowNumbers(y)) { +// if (k == m_Nonogram->width()) +// for (int i = 0; ) +// m_OverlayData[i][y] = 1; +// } + +// +// while (m_OverlayData[right][y] && left < right) +// right++; +// +// if (left == right) +// return true; +// +// if (m_Nonogram->rowNumbers(y)[0] == 0) +// for (int i = left; i <= right; i++) +// m_OverlayData[i][y] = MT_CROSSED; +// +// foreach (int k, m_Nonogram->rowNumbers(y)) { +// +// } + } +} diff --git a/libqnono/cnonogramsolver.h b/libqnono/cnonogramsolver.h new file mode 100644 index 0000000..b9c80f0 --- /dev/null +++ b/libqnono/cnonogramsolver.h @@ -0,0 +1,39 @@ +#ifndef LIBQCROSS_CNONOGRAMSOLVER_H +#define LIBQCROSS_CNONOGRAMSOLVER_H + +#include + +namespace libqcross { + class CNonogram; + + class CNonogramSolver : public QObject { + Q_OBJECT + public: + CNonogramSolver(QObject * parent = 0); + ~CNonogramSolver(); + + void setNonogram(CNonogram * nonogram) { m_Nonogram = nonogram; } + bool solve(); + signals: + void markRequested(int x, int y, int type); + protected: +// struct Range { +// int left; +// int right; +// +// Range() : left(-1), right(-1) {} +// bool isNULL() { return left == -1; } +// }; + + CNonogram * m_Nonogram; + + int ** m_OverlayData; + + void cleanup(); + + bool solveRow(int y); + bool solveColumn(int x); + }; +} + +#endif diff --git a/libqnono/constants.h b/libqnono/constants.h new file mode 100644 index 0000000..4c97dfd --- /dev/null +++ b/libqnono/constants.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef LIBQCROSS_CONSTANTS_H +#define LIBQCROSS_CONSTANTS_H + +#define LIBQCROSS_STRING_ICONPATH "/usr/share/qcross/icons/" + +#define LIBQCROSS_ICON_TIMEOUT LIBQCROSS_STRING_ICONPATH "timeout.png" +#define LIBQCROSS_ICON_TIMETRIAL LIBQCROSS_STRING_ICONPATH "timetrial.png" + +#endif // CONSTANTS_H diff --git a/qcross/.gitignore b/qcross/.gitignore new file mode 100644 index 0000000..d56038c --- /dev/null +++ b/qcross/.gitignore @@ -0,0 +1,13 @@ +build +Makefile* +ui +moc_* +fp +qnut +qnut_debug +qnut.kde* +Doxyfile +qnut.log +qnut.conf +.qnut +backup diff --git a/qcross/CMakeLists.txt b/qcross/CMakeLists.txt new file mode 100644 index 0000000..26a491c --- /dev/null +++ b/qcross/CMakeLists.txt @@ -0,0 +1,58 @@ +project(qcross) +cmake_minimum_required(VERSION 2.8) + +find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) + +include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}) +include(${QT_USE_FILE}) + +set(INSTALL_SHARE_PREFIX ${CMAKE_INSTALL_PREFIX}/share) +set(INSTALL_SHARE_TARGET_PREFIX ${INSTALL_SHARE_PREFIX}/${PROJECT_NAME}) + +set(FORMS + picselect.ui +) + +set(SOURCES_MOC_H + ccrossfieldwidget.h + cgamewindow.h + cnewgamedialog.h + cmaskedcrosspackagemodel.h +) + +set(SOURCES_CPP main.cpp + ccrossfieldwidget.cpp + cgamewindow.cpp + cnewgamedialog.cpp + cmaskedcrosspackagemodel.cpp + common.cpp + chighscore.cpp +) + +# set(TRANSLATIONS_TS ${PROJECT_NAME}_de.ts) + +qt4_wrap_ui(FORMS_H ${FORMS}) +qt4_wrap_cpp(SOURCES_MOC_CPP ${SOURCES_MOC_H}) +# qt4_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS}) + +add_executable(${PROJECT_NAME} + ${SOURCES_CPP} + ${SOURCES_MOC_CPP} + ${SOURCES_H} + ${FORMS_H} +# ${TRANSLATIONS_QM} +) + +target_link_libraries(${PROJECT_NAME} + ${qnono_BINARY_DIR}/libqnono.a + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${QT_QTNETWORK_LIBRARY} +) + +# file(GLOB RES_ICONS res/*.png res/qnut.svg res/qnut_small.svg) + +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +# install(FILES ${TRANSLATIONS_QM} DESTINATION ${INSTALL_SHARE_TARGET_PREFIX}/lang) +# install(FILES ${RES_ICONS} DESTINATION ${INSTALL_SHARE_TARGET_PREFIX}/icons) +# install(FILES ${PROJECT_NAME}.desktop DESTINATION ${INSTALL_SHARE_PREFIX}/applications) diff --git a/qcross/COPYING b/qcross/COPYING new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/qcross/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/qcross/ccrossfieldwidget.cpp b/qcross/ccrossfieldwidget.cpp new file mode 100644 index 0000000..1a08cc6 --- /dev/null +++ b/qcross/ccrossfieldwidget.cpp @@ -0,0 +1,632 @@ +/*************************************************************************** + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace qcross { + using namespace libqcross; + + 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) { + 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); + } + //beim Laden eines neuen Spiels nach einem beendeten wird das neue nicht automatisch gestartet (Restart nötig) + 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(); + } + + //public slots + void CCrossFieldWidget::mark(int x, int y, qcross::MarkerType type) { + if (type == CMT_NONE || x < 0 || x >= m_Picture->width() || y < 0 || y >= m_Picture->height()) + return; + + if (type == CMT_MARKED && checkNoError(x, y)) + m_OverlayData[x][y] = CMT_MARKED; + else + m_OverlayData[x][y] = type; + } + + 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_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_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; + update(); + return; + } + + Message m_Next = m_Messages.dequeue(); + update(); + +// switch (next.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(next.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() { + killTimer(m_TimerId); + killTimer(m_MessageTimeoutId); + + 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) { +/* if (m_OverlayData[x][y] == m_MouseMark) + return;*/ + + switch (m_MouseMark) { + case CMT_MARKED: + if (m_Picture->pixel(x, y)) { + m_RemainingPixels--; + m_OverlayData[x][y] = m_MouseMark; + } + else if (m_ErrorAware) { + m_ErrorCount++; + m_MouseMark = CMT_NONE; + m_OverlayData[x][y] = CMT_CROSSED; + m_LastErrorMark.setX(x); + m_LastErrorMark.setY(y); + emit markError(); + } + else { + m_ErrorCount++; + m_OverlayData[x][y] = m_MouseMark; + } + 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 + m_ErrorCount--; + } + + m_OverlayData[x][y] = m_MouseMark; + break; + default: + break; + } + + if (!m_RemainingPixels && (m_ErrorAware || !m_ErrorCount)) { + killTimer(m_TimerId); + 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; + + { + const int delta = 5 * m_BoxSize; + + int offsetX = 0; + int offsetY; + int deltaX = delta; + int deltaY; + + bool useBase = false; + + while (offsetX < gridWidth) { + offsetY = 0; + deltaY = delta; + while (offsetY < gridHeight) { + painter.fillRect(originX + offsetX, originY + offsetY, deltaX, deltaY, + palette().color(useBase ? QPalette::Base : QPalette::AlternateBase)); + + useBase = !useBase; + + offsetY += delta; + + if (gridWidth - offsetY < delta) + deltaY = gridWidth - offsetY; + } + + useBase = !useBase; + + offsetX += delta; + + if (gridWidth - offsetX < delta) + deltaX = gridWidth - offsetX; + } + } + + painter.setBrush(palette().color(QPalette::Highlight)); + + QFont font = painter.font(); + font.setPixelSize(m_MarkerSize * 0.9); + + { + QPen pen; + + pen.setWidth(m_MarkerSize / 10); + + painter.setPen(pen); + } + + QRectF markerRect(m_MarkerOffset, m_MarkerOffset, m_MarkerSize, m_MarkerSize); + + 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.fillRect(markerRect, painter.brush()); + } + + painter.drawLine(markerRect.topLeft(), markerRect.bottomRight()); + painter.drawLine(markerRect.bottomLeft(), markerRect.topRight()); + break; + default: + break; + } + } + } + + 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); + } + + if (m_Paused) + painter.setPen(palette().color(QPalette::Shadow)); + + 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); + } + + if (m_Message.type != Invalid) { + painter.drawText(m_HeaderWidth + m_OffsetX, m_HeaderHeight + m_OffsetY, m_Message.text); + } +// painter.drawLine(m_OffsetX, m_OffsetY + m_RasterHeight, m_OffsetX + m_RasterWidth, m_OffsetY + m_RasterHeight); + } + +/* 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); + 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); + update(); + } + } + + void CCrossFieldWidget::mouseReleaseEvent(QMouseEvent *) { + m_MouseMark = CMT_NONE; + } +} diff --git a/qcross/ccrossfieldwidget.h b/qcross/ccrossfieldwidget.h new file mode 100644 index 0000000..28f6699 --- /dev/null +++ b/qcross/ccrossfieldwidget.h @@ -0,0 +1,145 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef CCROSSFIELDWIDGET_H +#define CCROSSFIELDWIDGET_H + +#include +#include + +class QLCDNumber; +class QFrame; +class QLabel; + +namespace libqcross { + class CNonogram; +} + +namespace qcross { + enum MarkerType {CMT_UNMARKED = 0, CMT_MARKED = 1, CMT_CROSSED = 2, CMT_NONE = 3}; + + class CCrossFieldWidget : public QWidget { + Q_OBJECT + public: + enum MessageType {Information, Warning, Critical, Invalid}; + + bool isPaused() const { return m_Paused; } + bool isSolved() const { return m_Solved; } + bool isErrorAware() const { return m_ErrorAware; } + + int time() const { return m_Time; } + qint32 errorCount() const { return m_ErrorCount; } + + CCrossFieldWidget(libqcross::CNonogram * picture, QWidget * parent = 0); + ~CCrossFieldWidget(); + + QPoint lastErrorMark() const { return m_LastErrorMark; } + + void setPicture(libqcross::CNonogram * picture); + + void showMessage(const QString message = QString(), int timeout = 0, MessageType type = Information); + + public slots: + void mark(int x, int y, qcross::MarkerType type); + void setTime(int value); + void setErrorAware(bool value); + void setNumbersMarkable(bool value); + void start(); + void pause(); + void resume(); + + signals: + void markError(); + void solved(); + void timeUp(); + void timeChanged(int value); + + protected: + struct Message { + MessageType type; + QString text; + int timeout; + + Message() : type(Invalid), timeout(0) {} + }; + + QQueue m_Messages; + + libqcross::CNonogram * m_Picture; + MarkerType ** m_OverlayData; + quint32 m_RemainingPixels; + + int m_BoxSize; + qreal m_MarkerSize; + qreal m_MarkerOffset; + int m_OffsetX; + int m_OffsetY; + int m_HeaderWidth; + int m_HeaderHeight; + int m_RasterWidth; + int m_RasterHeight; + + MarkerType m_MouseMark; + + bool m_ErrorAware; + bool m_NumbersMarkable; + int m_Time; + bool m_Paused; + bool m_Solved; + int m_TimerId; + int m_MessageTimeoutId; + + QLCDNumber * m_Clock; + + QFrame * m_Notifier; + QLabel * m_NotifierIcon; + QLabel * m_NotifierText; + + qint32 m_ErrorCount; + QPoint m_LastErrorMark; + + Message m_Message; + void nextMessage(); + + inline void initialize(); + inline void cleanup(); + inline void reset(); + + inline bool checkNoError(int x, int y); + + void timerEvent(QTimerEvent * event); + inline void updateTimeDisplay(); + + inline void execMark(int x, int y); + + void paintEvent(QPaintEvent * event); + +/* void updateCell(int x, int y); + */ + void resizeEvent(QResizeEvent * event); + + void updateMetrics(); + + void mousePressEvent(QMouseEvent * event); + void mouseMoveEvent(QMouseEvent * event); + void mouseReleaseEvent(QMouseEvent * event); + }; +} + +#endif diff --git a/qcross/cgamewindow.cpp b/qcross/cgamewindow.cpp new file mode 100644 index 0000000..c5e4b4a --- /dev/null +++ b/qcross/cgamewindow.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "cgamewindow.h" +#include "ccrossfieldwidget.h" +#include "cnewgamedialog.h" +#include "chighscore.h" + +namespace qcross { + using namespace libqcross; +//public + CGameWindow::CGameWindow(QWidget * parent) : QMainWindow(parent) { + m_Highscore = NULL; + m_PictureIndex = -1; + m_Picture = new CNonogram(QSize(10, 10)); + m_Picture->updateNumbers(); + + m_Field = new CCrossFieldWidget(m_Picture, this); + m_Field->setTime(42 * 60 + 23); + + setCentralWidget(m_Field); +// m_Field->showMessage(tr("Welcome to QCross!")); + + createActions(); +// statusBar()->show(); + + connect(m_Field, SIGNAL(solved()), this, SLOT(wonGame())); + connect(m_Field, SIGNAL(timeUp()), this, SLOT(lostGame())); + connect(m_Field, SIGNAL(markError()), this, SLOT(handleErrorMark())); + } + + CGameWindow::~CGameWindow() { + m_Field->setPicture(NULL); + delete m_Picture; + } + +//protected + void CGameWindow::createActions() { + QToolBar * currentToolBar; + QMenu * currentMenu; + + //Game + currentMenu = menuBar()->addMenu(tr("&Game")); + currentMenu->addAction(tr("&New..."), this, SLOT(newGame()), Qt::CTRL + Qt::Key_N); + currentMenu->addSeparator(); + m_RestartGameAction = currentMenu->addAction(tr("&Restart"), this, SLOT(restartGame()), Qt::CTRL + Qt::Key_R); + m_RestartGameAction->setEnabled(false); + m_PauseGameAction = currentMenu->addAction(tr("&Pause")); + connect(m_PauseGameAction, SIGNAL(toggled(bool)), this, SLOT(pauseGame(bool))); + m_PauseGameAction->setShortcut(Qt::CTRL + Qt::Key_P); + m_PauseGameAction->setCheckable(true); + m_PauseGameAction->setEnabled(false); + currentMenu->addSeparator(); + currentMenu->addAction(tr("&Quit"), this, SLOT(close()), Qt::CTRL + Qt::Key_Q); +// currentMenu->addSeparator(); +// currentMenu->addAction(tr("debug: win"), this, SLOT(wonGame())); + + currentToolBar = addToolBar(currentMenu->title()); + currentToolBar->addActions(currentMenu->actions()); + + //Help + currentMenu = menuBar()->addMenu(tr("&Help")); + currentMenu->addAction(tr("&About"), this, SLOT(about())); + currentMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt())); + } + + void CGameWindow::newGame() { + bool notPaused = !m_Field->isPaused(); + if (notPaused) + m_Field->pause(); + + CNewGameDialog dialog; + if (dialog.exec() == QDialog::Accepted) { + if (m_Highscore) + delete m_Highscore; + + m_Field->setPicture(NULL); + if (m_Picture) + delete m_Picture; + + m_Highscore = dialog.takeHighscore(); + m_PictureIndex = m_Highscore ? dialog.nonogramIndex() : -1; + + m_Picture = dialog.takeNonogram(); + m_Picture->updateNumbers(); + + m_PauseGameAction->setEnabled(true); + m_RestartGameAction->setEnabled(true); + + m_Field->setPicture(m_Picture); + + m_Field->resume(); + m_Field->showMessage(tr("Game started!"), 1000); + } + else if (notPaused) + m_Field->resume(); + } + + void CGameWindow::restartGame() { + m_Field->setTime(m_Picture->timeout()); + + m_PauseGameAction->setChecked(false); + m_Field->start(); + + m_Field->showMessage(tr("Game restarted."), 1000); + } + + void CGameWindow::pauseGame(bool value) { + if (value) { + m_Field->showMessage(tr("Game paused.")); + m_Field->pause(); + } + else { + m_Field->showMessage(tr("Game resumed."), 1000); + m_Field->resume(); + } + } + + void CGameWindow::wonGame() { + m_PauseGameAction->setEnabled(false); + m_Field->showMessage(tr("Congratulations! You've solved the puzzle.")); + if (m_Highscore) { + qDebug("attempting to save highscore"); + (*m_Highscore)[m_PictureIndex] = m_Field->time(); + m_Highscore->save(); + } + } + + void CGameWindow::lostGame() { + m_PauseGameAction->setEnabled(false); + m_Field->showMessage(tr("Too bad! Time's up."), 0, CCrossFieldWidget::Critical); + } + + void CGameWindow::handleErrorMark() { + int timeDiff = (m_Field->errorCount() == 1) ? 2 : ((m_Field->errorCount() == 2) ? 4 : 8); + + m_Field->showMessage(tr("Sorry this was not correct: -%1min").arg(timeDiff), 1000, CCrossFieldWidget::Warning); + + m_Field->setTime(m_Field->time() - timeDiff*60); + } + + void CGameWindow::about() { + QMessageBox::about(this, tr("About"), tr("This is a still unfancy gui for solving nonograms.")); + } +} diff --git a/qcross/cgamewindow.h b/qcross/cgamewindow.h new file mode 100644 index 0000000..548b80f --- /dev/null +++ b/qcross/cgamewindow.h @@ -0,0 +1,70 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef QCROSS_CGAMEWINDOW_H +#define QCROSS_CGAMEWINDOW_H + +#include + +namespace libqcross { + class CNonogram; +} + +namespace qcross { + class CHighscore; + class CCrossFieldWidget; + + /** + @author Oliver Groß + */ + class CGameWindow : public QMainWindow { + Q_OBJECT + public: + CGameWindow(QWidget * parent = 0); + ~CGameWindow(); + + protected: + CCrossFieldWidget * m_Field; + libqcross::CNonogram * m_Picture; + + CHighscore * m_Highscore; + int m_PictureIndex; + + QAction * m_RestartGameAction; + QAction * m_PauseGameAction; + + void createActions(); + + protected slots: + void newGame(); +// void createPackage(); +// void openPackageImage(); + void restartGame(); + void pauseGame(bool value); + + void wonGame(); + void lostGame(); + + void handleErrorMark(); + + void about(); + }; +} + +#endif diff --git a/qcross/chighscore.cpp b/qcross/chighscore.cpp new file mode 100644 index 0000000..3ea3fa1 --- /dev/null +++ b/qcross/chighscore.cpp @@ -0,0 +1,77 @@ +/*************************************************************************** + * 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 +#include + +#include "chighscore.h" + +namespace qcross { + CHighscore::CHighscore(int initialSize) : QList() { + for (int i = 0; i < initialSize; i++) + append(0); + } + + bool CHighscore::open() { + if (m_FileName.isEmpty()) + return false; + + qDebug("reading highscore file: %s", m_FileName.toAscii().data()); + QFile file(m_FileName); + if (!file.open(QIODevice::ReadOnly)) + return false; + + clear(); + + QDataStream in(&file); + in.setVersion(QDataStream::Qt_4_0); + + quint32 intBuffer = 0; + + in >> intBuffer; + + for (quint32 i = 0; i < intBuffer; i++) { + append(0); + in >> last(); + } + + return true; + } + + bool CHighscore::save() { + if (m_FileName.isEmpty()) + return false; + + qDebug("saving highcore file: %s", m_FileName.toAscii().data()); + QFile file(m_FileName); + if (!file.open(QIODevice::WriteOnly)) + return false; + + QDataStream out(&file); + out.setVersion(QDataStream::Qt_4_0); + + out << size(); + + foreach (quint32 i, *this) + out << i; + + return true; + } + +} diff --git a/qcross/chighscore.h b/qcross/chighscore.h new file mode 100644 index 0000000..106cf97 --- /dev/null +++ b/qcross/chighscore.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef QCROSS_CHIGHSCORE_H +#define QCROSS_CHIGHSCORE_H + +#include +#include + +namespace qcross { + /** + @author Oliver Groß + */ + class CHighscore : public QList { + public: + CHighscore(int size = 0); + + void setFileName(QString value) { m_FileName = value; } + QString fileName() const { return m_FileName; } + + bool open(); + bool save(); + protected: + QString m_FileName; + }; +} + +#endif diff --git a/qcross/cmaskedcrosspackagemodel.cpp b/qcross/cmaskedcrosspackagemodel.cpp new file mode 100644 index 0000000..f0bf7b2 --- /dev/null +++ b/qcross/cmaskedcrosspackagemodel.cpp @@ -0,0 +1,102 @@ +/*************************************************************************** + * 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 +#include + +#include "cmaskedcrosspackagemodel.h" +#include "chighscore.h" +#include "common.h" + +#define COL_NAME 0 +#define COL_TIME 1 + +namespace qcross { + using namespace libqcross; +//public: + CMaskedCrossPackageModel::CMaskedCrossPackageModel(QObject * parent) : + CCrossPackageModel(parent), m_Highscore(NULL) {} + + CMaskedCrossPackageModel::~CMaskedCrossPackageModel() {} + + void CMaskedCrossPackageModel::setHighscore(CHighscore * highscore) { + m_Highscore = highscore; + reset(); + } + +// QVariant CMaskedCrossPackageModel::headerData(int section, Qt::Orientation orientation, int role) const { +// if (role == Qt::DisplayRole) { +// switch (section) { +// case COL_NAME: +// return tr("Nonogram"); +// case COL_TIME: +// return tr("Time"); +// default: +// break; +// } +// } +// +// return CCrossPackageModel::headerData(section, orientation, role); +// } + + int CMaskedCrossPackageModel::columnCount(const QModelIndex & /*parent*/) const { + return 2; + } + + QVariant CMaskedCrossPackageModel::data(const QModelIndex & index, int role) const { + if (role == Qt::DisplayRole && m_Highscore) { + switch (index.column()) { + case COL_NAME: + if ((*m_Highscore)[index.row()]) + break; + else + return tr("#%1").arg(index.row()); + case COL_TIME: + if ((*m_Highscore)[index.row()]) + return formatedTime((*m_Highscore)[index.row()]) + (m_Package->pictures()[index.row()]->timeout() ? + " (time out)" : ""); + else + return QVariant(); + default: + break; + } + } + + return CCrossPackageModel::data(index, role); + } + + Qt::ItemFlags CMaskedCrossPackageModel::flags(const QModelIndex & index) const { + return CCrossPackageModel::flags(index) & (~Qt::ItemIsEditable); + } + + CMaskedCrossPackageProxyModel::CMaskedCrossPackageProxyModel(QObject * parent) + : QSortFilterProxyModel(parent), m_UnfinishedFilter(false) {} + + void CMaskedCrossPackageProxyModel::setUnfinishedFilter(bool value) { + m_UnfinishedFilter = value; + reset(); + } + + bool CMaskedCrossPackageProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const { + QModelIndex index = sourceModel()->index(sourceRow, COL_TIME, sourceParent); + + return !m_UnfinishedFilter || sourceModel()->data(index).isNull(); + } + +} diff --git a/qcross/cmaskedcrosspackagemodel.h b/qcross/cmaskedcrosspackagemodel.h new file mode 100644 index 0000000..f727601 --- /dev/null +++ b/qcross/cmaskedcrosspackagemodel.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef QCROSS_CMASKEDCROSSPACKAGEMODEL_H +#define QCROSS_CMASKEDCROSSPACKAGEMODEL_H + +#include +#include + +namespace qcross { + class CHighscore; + + /** + @author Oliver Groß + */ + class CMaskedCrossPackageModel : public libqcross::CCrossPackageModel { + Q_OBJECT + public: + CMaskedCrossPackageModel(QObject * parent = 0); + ~CMaskedCrossPackageModel(); + + void setHighscore(CHighscore * highscore); + +// virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual int columnCount(const QModelIndex & parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; + virtual Qt::ItemFlags flags(const QModelIndex & index) const; + protected: + CHighscore * m_Highscore; + }; + + class CMaskedCrossPackageProxyModel : public QSortFilterProxyModel { + Q_OBJECT + public: + CMaskedCrossPackageProxyModel(QObject * parent = 0); + + bool unfinishedFilter() { return m_UnfinishedFilter; } + public slots: + void setUnfinishedFilter(bool value); + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + private: + bool m_UnfinishedFilter; + }; + +} + +#endif diff --git a/qcross/cnewgamedialog.cpp b/qcross/cnewgamedialog.cpp new file mode 100644 index 0000000..04068e6 --- /dev/null +++ b/qcross/cnewgamedialog.cpp @@ -0,0 +1,184 @@ +/*************************************************************************** + * 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 +#include +#include +#include +#include +#include +#include + +#include +// #include +#include +#include +#include "cmaskedcrosspackagemodel.h" +#include "chighscore.h" +#include "cnewgamedialog.h" +#include "constants.h" +#include "common.h" + +namespace qcross { + using namespace libqcross; + +//public: + CNewGameDialog::CNewGameDialog(QWidget * parent, Qt::WindowFlags f) : + QDialog(parent, f), + m_Highscore(new CHighscore(0)), + m_Nonogram(NULL) + { + ui.setupUi(this); + ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + QPushButton * importButton = new QPushButton(tr("Import package..."), this); + QPushButton * openPicFileButton = new QPushButton(tr("Open picture file..."), this); + + connect(importButton, SIGNAL(clicked()), this, SLOT(importPackage())); + connect(openPicFileButton, SIGNAL(clicked()), this, SLOT(openPictureFile())); + + ui.buttonBox->addButton(importButton, QDialogButtonBox::ActionRole); + ui.buttonBox->addButton(openPicFileButton, QDialogButtonBox::ActionRole); + + ui.packageList->setModel(new CCrossPackageListModel(QCROSS_STRING_DATAPATH)); + m_PicModel = new CMaskedCrossPackageModel(); + m_PicProxyModel = new CMaskedCrossPackageProxyModel(); + m_PicProxyModel->setSourceModel(m_PicModel); + m_PicModel->setHighscore(m_Highscore); + ui.picList->setModel(m_PicProxyModel); + +// ui.picList->header()->setResizeMode(1, QHeaderView::Fixed); +// ui.picList->header()->setResizeMode(0, QHeaderView::Stretch); + + connect(ui.unfinishedCheck, SIGNAL(toggled(bool)), m_PicProxyModel, SLOT(setUnfinishedFilter(bool))); + + connect(ui.packageList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + this, SLOT(handlePackageSelectionChanged(const QItemSelection &, const QItemSelection &))); + + connect(ui.picList, SIGNAL(activated(QModelIndex)), this, SLOT(accept())); + connect(ui.picList->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(handlePictureSelectionChanged(QItemSelection,QItemSelection))); + } + + CNewGameDialog::~CNewGameDialog() { + if (m_Highscore) + delete m_Highscore; + + if (m_Nonogram) + delete m_Nonogram; + } + +/* libqcross::CNonogram * CNewGameDialog::selectedNonogramData() const { + QModelIndex selected = ui.picList->selectionModel()->selectedIndexes()[0]; + return static_cast(selected.internalPointer()); + }*/ + + int CNewGameDialog::nonogramIndex() const { + QModelIndex selected = m_PicProxyModel->mapToSource(ui.picList->selectionModel()->selectedIndexes()[0]); + return selected.row(); + } + + libqcross::CCrossPackage * CNewGameDialog::selectedPackage() const { + QModelIndex selected = ui.packageList->selectionModel()->selectedIndexes()[0]; + return static_cast(selected.internalPointer()); + } + + libqcross::CNonogram * CNewGameDialog::takeNonogram() { + libqcross::CNonogram * result; + + if (m_Nonogram) { + result = m_Nonogram; + m_Nonogram = NULL; + } + else { + QModelIndexList selected = ui.packageList->selectionModel()->selectedIndexes(); + if (selected.isEmpty()) + result = NULL; + else { + result = static_cast(selected[0].internalPointer())->pictures().takeAt(nonogramIndex()); + m_PicModel->setPackage(NULL); + } + } + + return result; + } + + CHighscore * CNewGameDialog::takeHighscore() { + if (m_Nonogram) + return NULL; + + CHighscore * result = m_Highscore; + m_Highscore = NULL; + + return result; + } + +//protected: + void CNewGameDialog::importPackage() { + QString fileName = QFileDialog::getOpenFileName(this, tr("Select a package to import"), + QDir::homePath(), tr("QCross Package (*.cpk)")); + if (!fileName.isEmpty()) { + QString newFileName = QCROSS_STRING_DATAPATH + QDir::separator() + fileName.section(QDir::separator(), -1); + if (QFile::copy(fileName, newFileName)) + dynamic_cast(ui.packageList->model())->update(); + else + qCritical("could not copy file %s to %s", fileName.toAscii().data(), newFileName.toAscii().data()); + } + } + + void CNewGameDialog::openPictureFile() { + QString fileName = QFileDialog::getOpenFileName(this, tr("Select a picture to open"), + QDir::homePath(), tr("Images (*.png *.xpm *.xbm *.jpg)")); + if (!fileName.isEmpty()) { + if (m_Nonogram) + delete m_Nonogram; + + QImage image(fileName); + if (!image.isNull()) { + m_Nonogram = new CNonogram(); + m_Nonogram->loadFromImage(image); + m_Nonogram->updateNumbers(); + accept(); + } + else + m_Nonogram = NULL; + } + } + +//private: + void CNewGameDialog::handlePackageSelectionChanged(const QItemSelection & selected, const QItemSelection &) { + QModelIndex index = selected.indexes()[0]; + + CCrossPackage * package = static_cast(index.internalPointer()); + m_PicModel->setHighscore(NULL); + m_PicModel->setPackage(package); + + m_Highscore->setFileName(getHighscoreFileName(package->fileName())); + if (!m_Highscore->open()) { + qDebug("opening highscore file failed. will create a new one when nonogram is solved"); + m_Highscore->clear(); + for (int i = 0; i < package->pictures().size(); i++) + m_Highscore->append(0); + } + m_PicModel->setHighscore(m_Highscore); + } + void CNewGameDialog::handlePictureSelectionChanged(const QItemSelection & selected, const QItemSelection &) { + ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(selected.isEmpty()); + } +} diff --git a/qcross/cnewgamedialog.h b/qcross/cnewgamedialog.h new file mode 100644 index 0000000..c33b348 --- /dev/null +++ b/qcross/cnewgamedialog.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ +#ifndef QCROSS_CNEWGAMEDIALOG_H +#define QCROSS_CNEWGAMEDIALOG_H + +#include +#include "ui_picselect.h" + +namespace libqcross { + class CNonogram; + class CCrossPackage; +} + +namespace qcross { + class CHighscore; + class CMaskedCrossPackageModel; + class CMaskedCrossPackageProxyModel; + + /** + @author Oliver Groß + */ + class CNewGameDialog : public QDialog { + Q_OBJECT + public: + CNewGameDialog(QWidget * parent = 0, Qt::WindowFlags f = 0); + ~CNewGameDialog(); + + int nonogramIndex() const; + libqcross::CCrossPackage * selectedPackage() const; + + libqcross::CNonogram * takeNonogram(); + CHighscore * takeHighscore(); + protected slots: + void importPackage(); + void openPictureFile(); + private: + Ui::picselect ui; + CHighscore * m_Highscore; + libqcross::CNonogram * m_Nonogram; + CMaskedCrossPackageModel * m_PicModel; + CMaskedCrossPackageProxyModel * m_PicProxyModel; + private slots: + void handlePackageSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected); + void handlePictureSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected); + }; +} + +#endif diff --git a/qcross/common.cpp b/qcross/common.cpp new file mode 100644 index 0000000..ae4c852 --- /dev/null +++ b/qcross/common.cpp @@ -0,0 +1,58 @@ +/*************************************************************************** + * 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 "common.h" + +QString formatedTime(quint32 seconds, bool showSeconds) { + quint32 strippedSeconds = seconds % 60; + quint8 minutes = seconds / 60; + quint8 hours = minutes / 60; + + QString result; + + if (hours) { + if (hours < 10) + result += '0'; + result += QString::number(hours); + result += ':'; + } + + minutes %= 60; + + if (minutes < 10) + result += '0'; + result += QString::number(minutes); + + if (showSeconds) { + result += ':'; + if (strippedSeconds < 10) + result += '0'; + result += QString::number(strippedSeconds); + } + return result; +} + +QString getHighscoreFileName(QString packageFileName) { + if (packageFileName.isEmpty()) + return QString(); + + int tagPosition = packageFileName.lastIndexOf('.'); + + return ((tagPosition == -1) ? packageFileName : packageFileName.left(tagPosition)) + ".hsc"; +} diff --git a/qcross/common.h b/qcross/common.h new file mode 100644 index 0000000..ea9a201 --- /dev/null +++ b/qcross/common.h @@ -0,0 +1,23 @@ +/*************************************************************************** + * 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 + +QString formatedTime(quint32 seconds, bool showSeconds = false); +QString getHighscoreFileName(QString packageFileName); diff --git a/qcross/constants.h b/qcross/constants.h new file mode 100644 index 0000000..94bb8fd --- /dev/null +++ b/qcross/constants.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#ifndef QCROSS_CONSTANTS_H +#define QCROSS_CONSTANTS_H + +#include + +#define QCROSS_STRING_DATAPATH ((QDir::homePath() + QDir::separator()) + ".qcross") + +#endif diff --git a/qcross/debug.xbm b/qcross/debug.xbm new file mode 100644 index 0000000..cd5ac0a --- /dev/null +++ b/qcross/debug.xbm @@ -0,0 +1,4 @@ +#define debug_width 5 +#define debug_height 5 +static unsigned char debug_bits[] = { + 0x00, 0x00, 0x04, 0x00, 0x00 }; diff --git a/qcross/main.cpp b/qcross/main.cpp new file mode 100644 index 0000000..641ee65 --- /dev/null +++ b/qcross/main.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * 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 +//#include +#include "cgamewindow.h" +//#include "constants.h" + +using namespace qcross; + +int main(int argc, char * argv[]) +{ + QApplication app(argc, argv); + +/* QString locale = QLocale::system().name(); + QTranslator translator; + translator.load(QString(UI_PATH_TRANSLATIONS "qcross_") + locale); + app.installTranslator(&translator);*/ +// app.setQuitOnLastWindowClosed(false); + +// { +// QDir workdir(UI_PATH_WORK); +// if (!workdir.exists()) { +// workdir.cdUp(); +// workdir.mkdir(UI_DIR_WORK); +// } +// } + CGameWindow mainwin; + mainwin.show(); + return app.exec(); +} diff --git a/qcross/pic.xbm b/qcross/pic.xbm new file mode 100644 index 0000000..509c02f --- /dev/null +++ b/qcross/pic.xbm @@ -0,0 +1,9 @@ +#define pic_width 22 +#define pic_height 22 +static unsigned char pic_bits[] = { + 0xff, 0xff, 0x3f, 0xff, 0xff, 0x3f, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0x3c, + 0xff, 0x73, 0x3c, 0xff, 0x33, 0x3e, 0xbf, 0x13, 0x3f, 0x1f, 0x02, 0x3f, + 0x3f, 0x83, 0x3f, 0xbf, 0x83, 0x3f, 0xdf, 0x13, 0x3f, 0xc7, 0x33, 0x3e, + 0xcf, 0x73, 0x3c, 0xdf, 0xf3, 0x3c, 0xbf, 0xff, 0x3f, 0x1f, 0x1f, 0x3f, + 0x3f, 0x04, 0x3e, 0xf7, 0x71, 0x3f, 0xe3, 0xf3, 0x3f, 0xc3, 0xff, 0x3f, + 0xff, 0xff, 0x3f, 0xff, 0xff, 0x3f }; diff --git a/qcross/pic.xpm b/qcross/pic.xpm new file mode 100644 index 0000000..a2dd23d --- /dev/null +++ b/qcross/pic.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static char * pic_xpm[] = { +"24 24 2 1", +" c #000000", +". c #FFFFFF", +"....... ........ .......", +"...... . ...... . ......", +"...... . ...... . ......", +"...... . ...... . ......", +"...... . ...... . ......", +"...... . ...... . ......", +"...... . ...... . ......", +"...... . ...... . ......", +".... . . .....", +"... . . . . . ...", +"... . ...", +"... . ...", +"... ...", +"... ...", +"... ...", +"... ...", +"... ...", +".... ....", +"..... .....", +"....... .......", +".......... ..........", +".......... ..........", +".......... ..........", +"........................"}; diff --git a/qcross/pic2.xbm b/qcross/pic2.xbm new file mode 100644 index 0000000..5307968 --- /dev/null +++ b/qcross/pic2.xbm @@ -0,0 +1,5 @@ +#define pic2_width 10 +#define pic2_height 10 +static unsigned char pic2_bits[] = { + 0x86, 0x01, 0xc6, 0x01, 0xe6, 0x00, 0x76, 0x00, 0x7e, 0x00, 0x3e, 0x00, + 0x3e, 0x00, 0x76, 0x00, 0xe6, 0x00, 0xc6, 0x01 }; diff --git a/qcross/pic_bak.xbm b/qcross/pic_bak.xbm new file mode 100644 index 0000000..5ec65af --- /dev/null +++ b/qcross/pic_bak.xbm @@ -0,0 +1,9 @@ +#define pic_width 24 +#define pic_height 24 +static unsigned char pic_bits[] = { + 0x80, 0x00, 0x01, 0x40, 0x81, 0x02, 0x40, 0x81, 0x02, 0x40, 0x81, 0x02, + 0x40, 0x81, 0x02, 0x40, 0x81, 0x02, 0x40, 0x81, 0x02, 0x40, 0x81, 0x02, + 0x70, 0xff, 0x06, 0xd8, 0xaa, 0x1f, 0xb8, 0xff, 0x1f, 0xf8, 0xfe, 0x1f, + 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, + 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f, 0xe0, 0xff, 0x07, 0x80, 0xff, 0x01, + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00 }; diff --git a/qcross/picselect.ui b/qcross/picselect.ui new file mode 100644 index 0000000..6e1d0ca --- /dev/null +++ b/qcross/picselect.ui @@ -0,0 +1,150 @@ + + + picselect + + + + 0 + 0 + 544 + 297 + + + + New Game + + + + + + + + + 1 + 0 + + + + + 128 + 256 + + + + + 128 + 0 + + + + + + + + + 3 + 0 + + + + + 256 + 256 + + + + + 256 + 0 + + + + Available pictures + + + + + + false + + + + + + + + 0 + 0 + + + + + 256 + 0 + + + + none selected + + + + + + + Show unfinished only + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + picselect + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + picselect + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/qcrossedit/.gitignore b/qcrossedit/.gitignore new file mode 100644 index 0000000..a0472ae --- /dev/null +++ b/qcrossedit/.gitignore @@ -0,0 +1,7 @@ +build +Makefile* +ui +moc_* +qcrossedit +qcrossedit.pro.* +Doxyfile diff --git a/qcrossedit/CMakeLists.txt b/qcrossedit/CMakeLists.txt new file mode 100644 index 0000000..a5bc831 --- /dev/null +++ b/qcrossedit/CMakeLists.txt @@ -0,0 +1,47 @@ +project(qcrossedit) +cmake_minimum_required(VERSION 2.8) +find_package(Qt4 COMPONENTS QtCore QtGui REQUIRED) + +include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}) +include(${QT_USE_FILE}) + +set(INSTALL_SHARE_PREFIX ${CMAKE_INSTALL_PREFIX}/share) +set(INSTALL_SHARE_TARGET_PREFIX ${INSTALL_SHARE_PREFIX}/${PROJECT_NAME}) + +# set(FORMS ) + +set(SOURCES_MOC_H + cmainwindow.h +) + +set(SOURCES_CPP main.cpp + cmainwindow.cpp +) + +# set(TRANSLATIONS_TS ${PROJECT_NAME}_de.ts) + +qt4_wrap_ui(FORMS_H ${FORMS}) +qt4_wrap_cpp(SOURCES_MOC_CPP ${SOURCES_MOC_H}) +# qt4_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS}) + +add_executable(${PROJECT_NAME} + ${SOURCES_CPP} + ${SOURCES_MOC_CPP} + ${SOURCES_H} + ${FORMS_H} +# ${TRANSLATIONS_QM} +) + +target_link_libraries(${PROJECT_NAME} + ${qnono_BINARY_DIR}/libqnono.a + ${QT_QTCORE_LIBRARY} + ${QT_QTGUI_LIBRARY} + ${QT_QTNETWORK_LIBRARY} +) + +# file(GLOB RES_ICONS res/*.png res/qnut.svg res/qnut_small.svg) + +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +# install(FILES ${TRANSLATIONS_QM} DESTINATION ${INSTALL_SHARE_TARGET_PREFIX}/lang) +# install(FILES ${RES_ICONS} DESTINATION ${INSTALL_SHARE_TARGET_PREFIX}/icons) +# install(FILES ${PROJECT_NAME}.desktop DESTINATION ${INSTALL_SHARE_PREFIX}/applications) diff --git a/qcrossedit/COPYING b/qcrossedit/COPYING new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/qcrossedit/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/qcrossedit/cmainwindow.cpp b/qcrossedit/cmainwindow.cpp new file mode 100644 index 0000000..eba041d --- /dev/null +++ b/qcrossedit/cmainwindow.cpp @@ -0,0 +1,200 @@ +// +// C++ Implementation: cmainwindow +// +// Author: Oliver Groß , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "cmainwindow.h" + +namespace qcrossedit { + using namespace libqcross; +//public: + CMainWindow::CMainWindow(QWidget *parent) : + QMainWindow(parent), + m_Unsaved(false), + m_Package(NULL) + { + setupUi(); + fileNew(); + } + + + CMainWindow::~CMainWindow() { + } + +//protected: + void CMainWindow::setupUi() { + m_PicListView = new QTreeView(); + m_PicListView->setModel(new CCrossPackageModel(this)); + m_PicListView->setRootIsDecorated(false); + + setCentralWidget(m_PicListView); + + QMenu * menu; + + //file menu + menu = menuBar()->addMenu("&File"); + menu->addAction("&New", this, SLOT(fileNew()), Qt::CTRL + Qt::Key_N); + menu->addAction("&Open", this, SLOT(fileOpen()), Qt::CTRL + Qt::Key_O); + menu->addSeparator(); + menu->addAction("&Save", this, SLOT(fileSave()), Qt::CTRL + Qt::Key_S); + menu->addAction("Save as...", this, SLOT(fileSaveAs())); + menu->addSeparator(); + menu->addAction("&Quit", this, SLOT(close()), Qt::CTRL + Qt::Key_Q); + + //edit menu + menu = menuBar()->addMenu("&Edit"); + menu->addAction("&Create empty nonogram...", this, SLOT(editCreateEmpty())); + menu->addAction("&Create nonogram from picture...", this, SLOT(editCreateFromPicture())); + menu->addSeparator(); + menu->addAction("&Delete nongram", this, SLOT(editDelete())); + menu->addSeparator(); + menu->addAction("Set Package&name...", this, SLOT(editSetPackageName())); + + //help Menu + menu = menuBar()->addMenu("&Help"); + menu->addAction("About QCrossEdit", this, SLOT(helpAbout())); + menu->addAction("About Qt", qApp, SLOT(aboutQt())); + } + + bool CMainWindow::promtUnsaved() { + switch (QMessageBox::question(this, + tr("Unsaved changes"), + tr("Would you like to save your changes?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel)) { + case QMessageBox::Yes: + if (!fileSave()) + return false; + case QMessageBox::No: + return true; + default: + return false; + } + } + + void CMainWindow::closeEvent(QCloseEvent * event) { + if (m_Unsaved && !promtUnsaved()) + event->ignore(); + else + event->accept(); + } + +//protected slots: + void CMainWindow::fileNew() { + if (m_Unsaved && !promtUnsaved()) + return; + + m_Unsaved = false; + + if (m_Package) + delete m_Package; + + m_Package = new CCrossPackage(); + m_Package->setName(tr("unknown")); + qobject_cast(m_PicListView->model())->setPackage(m_Package); + statusBar()->showMessage(tr("New package created.")); + } + + void CMainWindow::fileOpen() { + if (m_Unsaved && !promtUnsaved()) + return; + + m_Unsaved = false; + + QString fileName = QFileDialog::getOpenFileName(this, tr("Select a nonogram package to open"), + QDir::homePath(), tr("QCross Package (*.cpk)")); + if (!fileName.isEmpty()) { + if (m_Package) + delete m_Package; + + m_Package = new CCrossPackage(); + m_Package->setFileName(fileName); + + if (!(m_Package->open() && m_Package->readAll())) { + delete m_Package; + m_Package = NULL; + } + else + statusBar()->showMessage(tr("Package \"%1\" opened.").arg(m_Package->name())); + + qobject_cast(m_PicListView->model())->setPackage(m_Package); + } + } + + bool CMainWindow::fileSave() { + if (m_Package->fileName().isEmpty()) + return fileSaveAs(); + + bool result = m_Package->save(); + + if (result) { + statusBar()->showMessage(tr("Package \"%1\" saved.").arg(m_Package->name())); + m_Unsaved = false; + } + else + statusBar()->showMessage(tr("Error occured on saving.").arg(m_Package->name())); + + return result; + } + + bool CMainWindow::fileSaveAs() { + QString fileName = QFileDialog::getSaveFileName(this, tr("Select a file name for the current package"), + QDir::homePath(), tr("QCross Package (*.cpk)")); + if (!fileName.isEmpty()) { + if (!QRegExp("*.cpk").exactMatch(fileName)) + fileName.append(".cpk"); + + m_Package->setFileName(fileName); + return fileSave(); + } + + return false; + } + + void CMainWindow::editCreateEmpty() { + if (qobject_cast(m_PicListView->model())->appendEmpty(tr("untitled"), QSize(32, 32), false)) + m_Unsaved = true; + } + + void CMainWindow::editCreateFromPicture() { + QString fileName = QFileDialog::getOpenFileName(this, tr("Select a image file to import"), + QDir::homePath(), tr("Images (*.png *.xpm *.xbm *.jpg)")); + if (!fileName.isEmpty()) { + if (qobject_cast(m_PicListView->model())->appendImage(fileName, QImage(fileName))) + m_Unsaved = true; + } + } + + void CMainWindow::editDelete() { + QModelIndexList selectedIndexes = m_PicListView->selectionModel()->selectedIndexes(); + foreach (QModelIndex i, selectedIndexes) + m_PicListView->model()->removeRow(i.row()); + } + + void CMainWindow::editSetPackageName() { + QString newName = QInputDialog::getText(this, tr("Set new package name"), + tr("Please enter a new name for this package:"), QLineEdit::Normal, m_Package->name()); + + if (!newName.isEmpty() && m_Package) + m_Package->setName(newName); + } + + void CMainWindow::helpAbout() { + QMessageBox::about(this, tr("About"), tr("This is still an unfancy gui for creating and editing nonogram packages.")); + } +} diff --git a/qcrossedit/cmainwindow.h b/qcrossedit/cmainwindow.h new file mode 100644 index 0000000..c65a281 --- /dev/null +++ b/qcrossedit/cmainwindow.h @@ -0,0 +1,62 @@ +// +// C++ Interface: cmainwindow +// +// Author: Oliver Groß , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +#ifndef QCROSSEDITCMAINWINDOW_H +#define QCROSSEDITCMAINWINDOW_H + +#include + +class QTreeView; +// class QBitmap; +//class QMenu; + +namespace libqcross { + class CCrossPackage; +} + +namespace qcrossedit { + class CMainWindow : public QMainWindow { + Q_OBJECT + public: + CMainWindow(QWidget * parent = 0); + ~CMainWindow(); + protected: + QTreeView * m_PicListView; + +/* QMenu * m_FileMenu; + QMenu * m_EditMenu;*/ + +// QString m_File; + bool m_Unsaved; + + libqcross::CCrossPackage * m_Package; + +/* QBitmap * m_Pics; + QString * m_PackName;*/ + + inline void setupUi(); + + void closeEvent(QCloseEvent * event); + + bool promtUnsaved(); + protected slots: + void fileNew(); + void fileOpen(); + bool fileSave(); + bool fileSaveAs(); + + void editCreateEmpty(); + void editCreateFromPicture(); + void editDelete(); + void editSetPackageName(); + + void helpAbout(); + }; + +} + +#endif diff --git a/qcrossedit/main.cpp b/qcrossedit/main.cpp new file mode 100644 index 0000000..0735ad4 --- /dev/null +++ b/qcrossedit/main.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + * 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 +//#include +#include "cmainwindow.h" +//#include "constants.h" + +using namespace qcrossedit; + +int main(int argc, char * argv[]) +{ + QApplication app(argc, argv); + +/* QString locale = QLocale::system().name(); + QTranslator translator; + translator.load(QString(UI_PATH_TRANSLATIONS "qcross_") + locale); + app.installTranslator(&translator);*/ +// app.setQuitOnLastWindowClosed(false); + +// { +// QDir workdir(UI_PATH_WORK); +// if (!workdir.exists()) { +// workdir.cdUp(); +// workdir.mkdir(UI_DIR_WORK); +// } +// } + + CMainWindow mainwin; + mainwin.show(); + return app.exec(); +}