From fa9585e1d0897d0b36e5fab37e60b80993e51872 Mon Sep 17 00:00:00 2001 From: Saki Date: Sun, 31 May 2015 21:27:43 +0800 Subject: [PATCH] Initial codes --- Robot.pro | 39 +++ barrackseditor.cpp | 24 ++ barrackseditor.h | 36 ++ barrackseditorbase.cpp | 24 ++ barrackseditorbase.h | 36 ++ generateground.cpp | 76 ++++ generateground.h | 56 +++ generategroundbase.cpp | 24 ++ generategroundbase.h | 44 +++ ground.cpp | 744 ++++++++++++++++++++++++++++++++++++++++ ground.h | 175 ++++++++++ groundbase.h | 160 +++++++++ groundeditor.cpp | 65 ++++ groundeditor.h | 59 ++++ groundpreviewwidget.cpp | 177 ++++++++++ groundpreviewwidget.h | 87 +++++ main.cpp | 39 +++ mainwindow.cpp | 69 ++++ mainwindow.h | 58 ++++ menubar.cpp | 53 +++ menubar.h | 64 ++++ panel.cpp | 127 +++++++ panel.h | 76 ++++ paneldock.cpp | 72 ++++ paneldock.h | 63 ++++ robot.cpp | 448 ++++++++++++++++++++++++ robot.h | 295 ++++++++++++++++ robotaddwidget.cpp | 135 ++++++++ robotaddwidget.h | 97 ++++++ robotmanagement.cpp | 145 ++++++++ robotmanagement.h | 94 +++++ 31 files changed, 3661 insertions(+) create mode 100644 Robot.pro create mode 100644 barrackseditor.cpp create mode 100644 barrackseditor.h create mode 100644 barrackseditorbase.cpp create mode 100644 barrackseditorbase.h create mode 100644 generateground.cpp create mode 100644 generateground.h create mode 100644 generategroundbase.cpp create mode 100644 generategroundbase.h create mode 100644 ground.cpp create mode 100644 ground.h create mode 100644 groundbase.h create mode 100644 groundeditor.cpp create mode 100644 groundeditor.h create mode 100644 groundpreviewwidget.cpp create mode 100644 groundpreviewwidget.h create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 menubar.cpp create mode 100644 menubar.h create mode 100644 panel.cpp create mode 100644 panel.h create mode 100644 paneldock.cpp create mode 100644 paneldock.h create mode 100644 robot.cpp create mode 100644 robot.h create mode 100644 robotaddwidget.cpp create mode 100644 robotaddwidget.h create mode 100644 robotmanagement.cpp create mode 100644 robotmanagement.h diff --git a/Robot.pro b/Robot.pro new file mode 100644 index 0000000..1e8feca --- /dev/null +++ b/Robot.pro @@ -0,0 +1,39 @@ +#Enabled the qt modules. +QT += core gui widgets + +#Enabled c++ 11 syntax. +CONFIG += c++11 + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + ground.cpp \ + robot.cpp \ + panel.cpp \ + menubar.cpp \ + robotmanagement.cpp \ + paneldock.cpp \ + robotaddwidget.cpp \ + groundpreviewwidget.cpp \ + generateground.cpp \ + groundeditor.cpp \ + generategroundbase.cpp \ + barrackseditor.cpp \ + barrackseditorbase.cpp + +HEADERS += \ + mainwindow.h \ + ground.h \ + robot.h \ + panel.h \ + groundbase.h \ + menubar.h \ + robotmanagement.h \ + paneldock.h \ + robotaddwidget.h \ + groundpreviewwidget.h \ + generateground.h \ + groundeditor.h \ + generategroundbase.h \ + barrackseditor.h \ + barrackseditorbase.h diff --git a/barrackseditor.cpp b/barrackseditor.cpp new file mode 100644 index 0000000..5d8a4d2 --- /dev/null +++ b/barrackseditor.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "barrackseditor.h" + +BarracksEditor::BarracksEditor(QWidget *parent) : + BarracksEditorBase(parent) +{ +} diff --git a/barrackseditor.h b/barrackseditor.h new file mode 100644 index 0000000..9a6f9c6 --- /dev/null +++ b/barrackseditor.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef BARRACKSEDITOR_H +#define BARRACKSEDITOR_H + +#include "barrackseditorbase.h" + +class BarracksEditor : public BarracksEditorBase +{ + Q_OBJECT +public: + explicit BarracksEditor(QWidget *parent = 0); + +signals: + +public slots: + +}; + +#endif // BARRACKSEDITOR_H diff --git a/barrackseditorbase.cpp b/barrackseditorbase.cpp new file mode 100644 index 0000000..09504e6 --- /dev/null +++ b/barrackseditorbase.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "barrackseditorbase.h" + +BarracksEditorBase::BarracksEditorBase(QWidget *parent) : + QWidget(parent) +{ +} diff --git a/barrackseditorbase.h b/barrackseditorbase.h new file mode 100644 index 0000000..ee22c06 --- /dev/null +++ b/barrackseditorbase.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef BARRACKSEDITORBASE_H +#define BARRACKSEDITORBASE_H + +#include + +class BarracksEditorBase : public QWidget +{ + Q_OBJECT +public: + explicit BarracksEditorBase(QWidget *parent = 0); + +signals: + +public slots: + +}; + +#endif // BARRACKSEDITORBASE_H diff --git a/generateground.cpp b/generateground.cpp new file mode 100644 index 0000000..b0171b8 --- /dev/null +++ b/generateground.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include + +#include "groundeditor.h" +#include "barrackseditor.h" + +#include "generateground.h" + +GenerateGround::GenerateGround(QWidget *parent) : + GenerateGroundBase(parent), + m_tabManager(new QTabWidget(this)), + m_groundEditor(new GroundEditor(this)), + m_barracksEditor(new BarracksEditor(this)), + m_okay(new QPushButton(this)), + m_cancel(new QPushButton(this)) +{ + //Set properties. +#ifdef Q_OS_MACX + setWindowFlags(Qt::Sheet); +#endif + + //Configure buttons. + m_cancel->setShortcut(QKeySequence(Qt::Key_Escape)); + connect(m_cancel, + static_cast(&QPushButton::clicked), + [=] + { + close(); + }); + + //Initial the layout. + QBoxLayout *mainLayout=new QBoxLayout(QBoxLayout::LeftToRight, + this); + setLayout(mainLayout); + + mainLayout->addWidget(m_tabManager, 1); + + m_tabManager->addTab(m_groundEditor, ""); + m_tabManager->addTab(m_barracksEditor, ""); + + QBoxLayout *buttonLayout=new QBoxLayout(QBoxLayout::TopToBottom, + mainLayout->widget()); + mainLayout->addLayout(buttonLayout); + buttonLayout->addWidget(m_okay); + buttonLayout->addWidget(m_cancel); + buttonLayout->addStretch(); + + retranslate(); +} + +void GenerateGround::retranslate() +{ + m_okay->setText(tr("Ok")); + m_cancel->setText(tr("Cancel")); + + m_tabManager->setTabText(0, tr("Ground")); + m_tabManager->setTabText(1, tr("Barracks")); +} diff --git a/generateground.h b/generateground.h new file mode 100644 index 0000000..12013b0 --- /dev/null +++ b/generateground.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef GENERATEGROUND_H +#define GENERATEGROUND_H + +#include "generategroundbase.h" + +class QPushButton; +class QTabWidget; +class GroundEditor; +class BarracksEditor; +/*! + * \brief The GenerateGround class is a default realization of + * GenerateGroundBase. + */ +class GenerateGround : public GenerateGroundBase +{ + Q_OBJECT +public: + /*! + * \brief Construct ground generator widget. + * \param parent The parent widget. + */ + explicit GenerateGround(QWidget *parent = 0); + +signals: + +public slots: + +private slots: + void retranslate(); + +private: + QTabWidget *m_tabManager; + GroundEditor *m_groundEditor; + BarracksEditor *m_barracksEditor; + QPushButton *m_okay, *m_cancel; +}; + +#endif // GENERATEGROUND_H diff --git a/generategroundbase.cpp b/generategroundbase.cpp new file mode 100644 index 0000000..a4c401b --- /dev/null +++ b/generategroundbase.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "generategroundbase.h" + +GenerateGroundBase::GenerateGroundBase(QWidget *parent) : + QDialog(parent) +{ +} diff --git a/generategroundbase.h b/generategroundbase.h new file mode 100644 index 0000000..1949875 --- /dev/null +++ b/generategroundbase.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef GENERATEGROUNDBASE_H +#define GENERATEGROUNDBASE_H + +#include + +/*! + * \brief The GenerateGround class is a widget which can help user to generate + * the border and barracks. + */ +class GenerateGroundBase : public QDialog +{ + Q_OBJECT +public: + /*! + * \brief Construct a GenerateGroundBase dialog. + * \param parent Set the parent widget. + */ + explicit GenerateGroundBase(QWidget *parent = 0); + +signals: + +public slots: + +}; + +#endif // GENERATEGROUNDBASE_H diff --git a/ground.cpp b/ground.cpp new file mode 100644 index 0000000..98c50ad --- /dev/null +++ b/ground.cpp @@ -0,0 +1,744 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "robot.h" +#include "menubar.h" +#include "generategroundbase.h" + +#include "ground.h" + +#include + +Ground::Ground(QWidget *parent) : + GroundBase(parent), + m_border(QPolygonF()), + m_barracks(QPolygonF()), + m_borderColor(QColor(0,0,255)), + m_barracksColor(QColor(255,127,0)), + m_referenceLineColor(QColor(200,200,200)), + m_filePath(QString()), + m_fileName(QString()), + m_changed(false), + m_timeline(new QTimer(this)), + m_generator(nullptr) +{ + setContentsMargins(0,0,0,0); + //Configure the timer. + m_timeline->setInterval(16); //This will update the image for 60fps. + connect(m_timeline, &QTimer::timeout, + this, &Ground::onActionUpdateRobot); + + //Initial the actions. + for(int i=0; isetShortcut(QKeySequence(Qt::CTRL+Qt::Key_N)); + m_actions[Open]->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_O)); + m_actions[Save]->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_S)); + m_actions[SaveAs]->setShortcut(QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_S)); + m_actions[Close]->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_W)); + + connect(m_actions[New], static_cast(&QAction::triggered), + [=]{onActionNew();}); + connect(m_actions[Open], static_cast(&QAction::triggered), + [=]{onActionOpen();}); + connect(m_actions[Save], static_cast(&QAction::triggered), + [=]{onActionSave();}); + connect(m_actions[SaveAs], static_cast(&QAction::triggered), + [=]{onActionSaveAs();}); + connect(m_actions[Close], static_cast(&QAction::triggered), + [=]{onActionClose();}); + + retranslate(); + + //-----Example----- +// QPolygonF debugBorder, debugBarracks; +// //Set a default border. +// debugBorder << QPointF(30, 60) << QPointF(120, 20) +// << QPointF(400, 45) << QPointF(415, 280) +// << QPointF(180, 340) << QPointF(15, 210); +// setBorder(debugBorder); + +// //Set a default barracks. +// debugBarracks << QPointF(200, 200) << QPointF(200, 275) +// << QPointF(275, 275) << QPointF(275, 200); +// setBarracks(debugBarracks); + +// //Set some robots. +// addRobot(new Robot(203, 203)); +// addRobot(new Robot(210, 210)); +// addRobot(new Robot(210, 220)); +// addRobot(new Robot(203, 210)); +// addRobot(new Robot(210, 203)); +// addRobot(new Robot(203, 250)); +// addRobot(new Robot(209, 250)); +// addRobot(new Robot(250, 210)); +// addRobot(new Robot(203, 207)); +// addRobot(new Robot(204, 207)); +} + +Ground::~Ground() +{ + //Recover all the memory of the robot. + qDeleteAll(m_robotList); +} + +QPolygonF Ground::border() const +{ + return m_border; +} + +void Ground::setBorder(const QPolygonF &border) +{ + //The border should be at least a triangle, if it's only a line or nothing, + //ignore the request. + if(border.size()<3) + { + return; + } + //Save the border, and clear the barracks. + m_border = border; + m_barracks = QPolygonF(); + //Set the changed flag. + m_changed=true; + //Update the border lines. + m_borderLines.clear(); + for(int i=0; ipaintRobot(&painter); + } +} + +void Ground::retranslate() +{ + m_actions[New]->setText(tr("New")); + m_actions[Open]->setText(tr("Open")); + m_actions[Save]->setText(tr("Save")); + m_actions[SaveAs]->setText(tr("Save As")); + m_actions[Close]->setText(tr("Close")); +} + +void Ground::onActionUpdateRobot() +{ + QList::iterator beforeLastRobot=m_robotList.end()-1; + //Give all the robot the detect information. + for(QList::iterator robot=m_robotList.begin(); + robot!=beforeLastRobot; + ++robot) + { + for(QList::iterator target=robot+1; + target!=m_robotList.end(); + ++target) + { + //Ignore the current robot. + if(robot==target) + { + continue; + } + //If we have detected one of another robot, add them into the both + //detect list. + if(inDetectRange(*robot, *target)) + { + (*robot)->addToDetectList(*target); + (*target)->addToDetectList(*robot); + } + else + { + //Or else remove them from each other's detect list. + (*robot)->removeFromDetectList(*target); + (*target)->removeFromDetectList(*robot); + } + } + } + + //Update all the robot. + for(Robot *robot : m_robotList) + { + //If the robot is still don't have a line to guard, + if(!robot->hasGuardianLine()) + { + //Detect if the robot is in the border, if the robot is out of the + //border. + if(!m_border.containsPoint(robot->nextStep(), + Qt::OddEvenFill)) + { + //Find the line of the robot should guard, the robot should + //guard the most recent line. + //Appoint the robot to guard that line. + appointGuardianLine(robot); + } + } + //Update the direction of the robot. + robot->updateDirection(); + } + //Ask all the robot to move one step. + for(Robot *robot : m_robotList) + { + //Move the robot. + robot->moveOneStep(); + } + //Update the image. + update(); +} + +void Ground::onActionNew() +{ + //Stop the time line. + m_timeline->stop(); + //Close the current file. + if(!onActionClose()) + { + return; + } + //Should call generate ground widget here, and then judge it's success or + //failed. If success, set the ground information, or else abandon. + if(m_generator) + { + m_generator->exec(); + } +} + +bool Ground::onActionOpen() +{ + //Stop the time line. + m_timeline->stop(); + + //Close the current file. + if(!onActionClose()) + { + return false; + } + //Get the session file path. + QString sessionFilePath=QFileDialog::getOpenFileName(this, + tr("Open session")); + if(sessionFilePath.isEmpty()) + { + return false; + } + //Read the session file. + return readGroundData(sessionFilePath); +} + +bool Ground::onActionSave() +{ + //If the file don't need to save, then return false. + if(!m_changed) + { + return false; + } + //Check the file path is empty or not, if it's empty, call the save as. + if(m_filePath.isEmpty()) + { + return onActionSaveAs(); + } + //Or else, just write the data to the file. + m_changed=!writeGroundData(); + return !m_changed; +} + +bool Ground::onActionSaveAs() +{ + //Get the new file path. + QString preferFilePath=QFileDialog::getSaveFileName(this, + tr("Save session")); + if(preferFilePath.isEmpty()) + { + return false; + } + //Set session file information. + m_filePath=preferFilePath; + QFileInfo sessionFileInfo(m_filePath); + m_fileName=sessionFileInfo.fileName(); + //Save the data to session file. + m_changed=!writeGroundData(); + return !m_changed; +} + +bool Ground::onActionClose() +{ + //Stop the time line. + m_timeline->stop(); + + //Check if the current state is already close. + if(m_filePath.isEmpty() && !m_changed) + { + //Treat this as close successful. + return true; + } + + //Check the current session has been saved or not. + const int buttonSave=0, buttonCancel=1, buttonAbandon=2; + if(m_changed) + { + //There's a session which is modified but not save. + int result=QMessageBox::question(this, + tr("Close unsaved session"), + tr("Do you want to save the changes you made in the document \"%1\"?").arg( + m_fileName.isEmpty()?tr("Untitled"):m_fileName), + tr("Save"), + tr("Cancel"), + tr("Don't Save"), + buttonSave, + buttonCancel); + switch(result) + { + case buttonSave: + //If we saved fail, then we can't close the document. + if(!onActionSave()) + { + return false; + } + case buttonCancel: + //If user cancel close, then stop to close. + return false; + case buttonAbandon: + //Continue close the file. + break; + default: + //You must kidding me if goes here. + return false; + } + } + //Clear the ground data. + clearGroundData(); + //Reset the file status data. + m_filePath=QString(); + m_fileName=QString(); + m_changed=false; + //Update the panel. + update(); + return true; +} + +void Ground::clearGroundData() +{ + //Clear the border, border information, and barracks. + m_border=QPolygon(); + m_borderLines.clear(); + m_barracks=QPolygon(); + //Remove all the robot datas. + qDeleteAll(m_robotList); + m_robotList.clear(); + m_robotInitialAngle.clear(); + m_robotInitialPosition.clear(); + //Resize ground. + setFixedSize(0,0); +} + +bool Ground::readGroundData(const QString &filePath) +{ + //Try to open the file. + QFile sessionFile(filePath); + if(sessionFile.open(QIODevice::ReadOnly)) + { + //Read the data from the file. + QTextStream sessionStream(&sessionFile); + sessionStream.setCodec("UTF-8"); + //Read and parse the json. + QJsonObject sessionObject= + QJsonDocument::fromJson(sessionStream.readAll().toUtf8()).object(); + sessionFile.close(); + + //Generate the border. + QJsonArray borderData=sessionObject.value("Border").toArray(); + //Check if the border is vaild or not. + if(borderData.size()<3) //Simplified than a triangle. + { + return false; + } + QPolygonF border; + for(QJsonArray::iterator i=borderData.begin(); + i!=borderData.end(); + ++i) + { + QJsonArray pointData=(*i).toArray(); + //The array must contains only x() and y() data of the point. + if(pointData.size()!=2) + { + return false; + } + border.append(QPointF(pointData.at(0).toDouble(), + pointData.at(1).toDouble())); + } + + //Generate the barracks. + QJsonArray barracksData=sessionObject.value("Barracks").toArray(); + //Check if the barracks is vaild or not. + if(barracksData.size()<3) //Simlified than a triangle. + { + return false; + } + QPolygonF barracks; + for(QJsonArray::iterator i=barracksData.begin(); + i!=barracksData.end(); + ++i) + { + QJsonArray pointData=(*i).toArray(); + //The array must contains only x() and y() data of the point. + if(pointData.size()!=2) + { + return false; + } + //Check the point is vaild or not. + QPointF barracksPoint=QPointF(pointData.at(0).toDouble(), + pointData.at(1).toDouble()); + if(!border.containsPoint(barracksPoint, Qt::OddEvenFill)) + { + return false; + } + barracks.append(barracksPoint); + } + + //Generate the robot list. + QList robotList; + QJsonArray robotsData=sessionObject.value("Robots").toArray(); + for(QJsonArray::iterator i=robotsData.begin(); + i!=robotsData.end(); + ++i) + { + //Generate the robot. + QJsonObject robotData=(*i).toObject(); + QJsonArray robotPosition=robotData.value("Position").toArray(); + if(robotPosition.size()!=2) + { + //Clear the robots that has been genereated. + qDeleteAll(robotList); + return false; + } + Robot *robot=new Robot(robotPosition.at(0).toDouble(), + robotPosition.at(1).toDouble()); + robot->setAngle(robotData.value("Angle").toDouble()); + + robotList.append(robot); + } + //If we can go here, then all the data should be ok. + //Set the border, barracks and robots. + setBorder(border); + setBarracks(barracks); + addRobots(robotList); + //Change the file information and flags. + QFileInfo sessionFileInfo(sessionFile); + m_filePath=sessionFileInfo.absoluteFilePath(); + m_fileName=sessionFileInfo.fileName(); + m_changed=false; + //Update the image. + update(); + return true; + } + return false; +} + +bool Ground::writeGroundData() +{ + QFile sessionFile(m_filePath); + if(sessionFile.open(QIODevice::WriteOnly)) + { + //Generate the json object. + QJsonObject sessionObject; + QJsonArray border, barracks, robots; + //Write the border data to session object. + for(QPointF borderPoint : m_border) + { + QJsonArray point; + point.append(borderPoint.x()); + point.append(borderPoint.y()); + border.append(point); + } + sessionObject.insert("Border", border); + //Write barracks data to session object. + for(QPointF barracksPoint : m_barracks) + { + QJsonArray point; + point.append(barracksPoint.x()); + point.append(barracksPoint.y()); + barracks.append(point); + } + sessionObject.insert("Barracks", barracks); + //Write robot initial data to session object. + for(int i=0; ipos(), to->pos()).length()pos(), line, currentFoot); + //Check the distance. + if(minimalDistance<0.0 || currentDistancesetGuardianLine(guardianLine, footPoint); +} + +inline qreal Ground::getDistance(const QPointF &point, + const QLineF &line, + QPointF &footPoint) +{ + //The line whose angle is 90.0 or 270.0 has no gradient. + //The distance will be the absolute of the difference of x. + if(line.angle()==90.0 || line.angle()==270.0) + { + footPoint=QPointF(line.p1().x(), point.y()); + return qAbs(line.p1().x()-point.x()); + } + //Calculate the gradient. + qreal k=(line.p2().y()-line.p1().y())/(line.p2().x()-line.p1().x()); + //Get the foot point. + qreal footX=(k*k*line.p1().x()+k*(point.y()-line.p1().y())+point.x())/ + (k*k+1); + footPoint=QPointF(footX, k*(footX-line.p1().x())+line.p1().y()); + //Get the distance. + return QLineF(point, footPoint).length(); +} + +QPolygonF Ground::barracks() const +{ + return m_barracks; +} + +QColor Ground::barracksColor() const +{ + return m_barracksColor; +} + +bool Ground::addRobot(Robot *robot) +{ + //Check the robot. + //If the position of the robot is outside barracks, or there's already have + //a robot, you can't add this robot. + if(!m_barracks.containsPoint(robot->pos(), Qt::OddEvenFill) || + m_robotInitialPosition.contains(robot->pos())) + { + //Delete the robot. + delete robot; + return false; + } + //Add the available robot to list. + m_robotList.append(robot); + //Set the changed flag. + m_changed=true; + //Add the robot to initial position. + m_robotInitialPosition.append(robot->pos()); + m_robotInitialAngle.append(robot->angle()); + return true; +} + +void Ground::addRobots(const QList &robots) +{ + //Add the robot one by one. + for(QList::const_iterator i=robots.begin(); + i!=robots.end(); + ++i) + { + addRobot(*i); + } +} + +void Ground::setMenuBar(MenuBar *menuBar) +{ + menuBar->addCategoryAction(MenuBar::File, m_actions[New]); + menuBar->addCategoryAction(MenuBar::File, m_actions[Open]); + menuBar->addCategoryAction(MenuBar::File, m_actions[Save]); + menuBar->addCategoryAction(MenuBar::File, m_actions[SaveAs]); + menuBar->addCategoryAction(MenuBar::File, m_actions[Close]); +} + +void Ground::setGenerator(GenerateGroundBase *generator) +{ + //Save the generator. + m_generator=generator; +} + +void Ground::setBarracks(const QPolygonF &barracks) +{ + //Check if the barracks is all in the border. + //If there's any point is not in the border, ignore the set request. + for(QPolygonF::const_iterator i=barracks.begin(); + i!=barracks.end(); + ++i) + { + if(!m_border.containsPoint(*i, Qt::OddEvenFill)) + { + return; + } + } + //Save the barracks. + m_barracks = barracks; + //Set the changed flag. + m_changed=true; + //Update widget. + update(); + //Emit the barracks changed signal. + emit barracksChanged(); +} + +QColor Ground::borderColor() const +{ + return m_borderColor; +} + +void Ground::setBorderColor(const QColor &borderColor) +{ + m_borderColor = borderColor; + //Update the widget. + update(); +} + +void Ground::pause() +{ + //Stop the timer. + m_timeline->stop(); +} + +void Ground::start() +{ + //Start the time line. + m_timeline->start(); +} + +void Ground::nextFrame() +{ + //When the time line is running, ignore the request. + if(m_timeline->isActive()) + { + return; + } + //Call update robot once. + onActionUpdateRobot(); +} + +void Ground::reset() +{ + //Stop the time line. + m_timeline->stop(); + //Reset all the robot. + for(int i=0; iresetGuardianLine(); + //Reset the robot position and angle. + robot->setPos(m_robotInitialPosition.at(i)); + robot->setAngle(m_robotInitialAngle.at(i)); + } + //Update the ground. + update(); +} diff --git a/ground.h b/ground.h new file mode 100644 index 0000000..8f3b9c7 --- /dev/null +++ b/ground.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef GROUND_H +#define GROUND_H + +#include "groundbase.h" + +class QTimer; +/*! + * \brief The Ground class a default realization of the GroundBase class. + */ +class Ground : public GroundBase +{ + Q_OBJECT +public: + /*! + * \brief Construct Ground class with the given parent. + * \param parent The parent widget of the Ground class. + */ + explicit Ground(QWidget *parent = 0); + ~Ground(); + + /*! + * \brief Reimplemented from GroundBase::border(). + */ + QPolygonF border() const; + + /*! + * \brief Reimplemented from GroundBase::borderColor(). + */ + QColor borderColor() const; + + /*! + * \brief Reimplemented from GroundBase::barracks(). + */ + QPolygonF barracks() const; + + /*! + * \brief Reimplemented from GroundBase::barracksColor(). + */ + QColor barracksColor() const; + + /*! + * \brief Reimplemented from GroundBase::addRobot(). + */ + bool addRobot(Robot *robot); + + /*! + * \brief Reimplemented from GroundBase::addRobots(). + */ + void addRobots(const QList &robots); + + /*! + * \brief Reimplemented from GroundBase::setMenuBar(). + */ + void setMenuBar(MenuBar *menuBar); + + /*! + * \brief Reimplemented from GroundBase::setGenerator(). + */ + void setGenerator(GenerateGroundBase *generator); +signals: + +public slots: + /*! + * \brief Reimplemented from GroundBase::setBorder(const QPolygonF &). + */ + void setBorder(const QPolygonF &border); + + /*! + * \brief Reimplemented from GroundBase::setBarracks(const QPolygonF &). + */ + void setBarracks(const QPolygonF &barracks); + + /*! + * \brief Reimplemented from GroundBase::setBorderColor(const QColor &). + */ + void setBorderColor(const QColor &borderColor); + + /*! + * \brief Reimplemented from GroundBase::pause(). + */ + void pause(); + + /*! + * \brief Reimplemented from GroundBase::start(). + */ + void start(); + + /*! + * \brief Reimplemented from GroundBase::nextFrame(). + */ + void nextFrame(); + + /*! + * \brief Reimplemented from GroundBase::reset(). + */ + void reset(); + +protected: + /*! + * \brief This event handler can be reimplemented in a subclass to receive + * paint events passed in event. \n + * Draw all the elements of the ground, included: robots, border and + * barracks.\n + * Reimplemented from QWidget::paintEvent(). + * \param event The event handle. + */ + void paintEvent(QPaintEvent *event); + +private slots: + void retranslate(); + void onActionUpdateRobot(); + + void onActionNew(); + bool onActionOpen(); + bool onActionSave(); + bool onActionSaveAs(); + bool onActionClose(); + +private: + inline void clearGroundData(); + inline bool readGroundData(const QString &filePath); + inline bool writeGroundData(); + inline bool inDetectRange(Robot *from, Robot *to); + inline void appointGuardianLine(Robot *robot); + inline qreal getDistance(const QPointF &point, + const QLineF &line, + QPointF &footPoint); + enum GroundActions + { + New, + Open, + Save, + SaveAs, + Close, + GroundActionsCount + }; + QAction *m_actions[GroundActionsCount]; + + QPolygonF m_border, m_barracks; + QColor m_borderColor, m_barracksColor, m_referenceLineColor; + QList m_robotList; + + //Project file status. + QString m_filePath, m_fileName; + bool m_changed; + + //Initial data recorder. + QList m_robotInitialPosition; + QList m_robotInitialAngle; + + QList m_borderLines; + + QTimer *m_timeline; + GenerateGroundBase *m_generator; +}; + +#endif // GROUND_H diff --git a/groundbase.h b/groundbase.h new file mode 100644 index 0000000..4ee0da9 --- /dev/null +++ b/groundbase.h @@ -0,0 +1,160 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef GROUNDBASE_H +#define GROUNDBASE_H + +#include + +#include + +class Robot; +class MenuBar; +class GenerateGroundBase; +/*! + * \brief This is the abstraction class of the ground. It contains all the + * interfaces which a ground class should be realized.\n + * A Ground class is the widget which is going to show up the robots, + * borders and barracks. It has to detected all the robots and set the + * information to all the robots. The Ground class should contains all the + * environmental information. + */ +class GroundBase : public QWidget +{ + Q_OBJECT +public: + /*! + * \brief Construct Ground class with the given parent. + * \param parent The parent widget of the Ground class. + */ + GroundBase(QWidget *parent = 0):QWidget(parent){} + + /*! + * \brief The outside border which all the robots is going to guard. + * \return The border QPolygonF class of the border. + */ + virtual QPolygonF border() const=0; + + /*! + * \brief Get the color of the border. + * \return The QColor of the border. + */ + virtual QColor borderColor() const=0; + + /*! + * \brief The barracks border which all the robots is going to be set at + * beginning. + * \return The border QPolygonF class of the barracks. + */ + virtual QPolygonF barracks() const=0; + + /*! + * \brief Get the color of the barracks border. + * \return The QColor of the barracks border. + */ + virtual QColor barracksColor() const=0; + + /*! + * \brief Add a robot to the ground. It will detect the start position of + * the robot. If the robot is out side the barracks, will delete the robot. + * \param robot The robot class which is going to be added. + * \return If add the robot sucessfully, return true, or else return false. + */ + virtual bool addRobot(Robot *robot)=0; + + /*! + * \brief Add a lots of robots to the ground. It will call addRobot() + * function for several times. + * \param robots + */ + virtual void addRobots(const QList &robots)=0; + + /*! + * \brief Set the menu bar to add control actions. + * \param menuBar The menu bar. + */ + virtual void setMenuBar(MenuBar *menuBar)=0; + + /*! + * \brief Set a ground generator. + * \param generator The ground generator. + */ + virtual void setGenerator(GenerateGroundBase *generator)=0; + +signals: + /*! + * \brief When the user change the border, this signal will be emitted. + */ + void borderChanged(); + + /*! + * \brief When the user change the barracks border, this signal will be + * emitted. + */ + void barracksChanged(); + +public slots: + /*! + * \brief Sets the border for the ground to border. \n + * The border must be at least a triangle, if it's not a more complex + * polygon than a triangle, the border will not be set.\n + * When the new border has been set, the barracks will be reset to empty. + * \param border The target border QPolygonF. + */ + virtual void setBorder(const QPolygonF &border)=0; + + /*! + * \brief Sets the border for the barracks of robots.\n + * If there's any point which is not in the sets border, this barracks will + * not be set. + * \param barracks The target barracks QPolygonF. + */ + virtual void setBarracks(const QPolygonF &barracks)=0; + + /*! + * \brief Sets the color of the border. + * \param borderColor The prefer color of the border. + */ + virtual void setBorderColor(const QColor &borderColor)=0; + + /*! + * \brief Pause the main time line. + */ + virtual void pause()=0; + + /*! + * \brief Continue running the main time line. + */ + virtual void start()=0; + + /*! + * \brief Reset all the robot at the start position.\n + * All the robot's guardian line will be removed, and the position and + * direction will be also reset. + */ + virtual void reset()=0; + + /*! + * \brief Ask all the robot move only once.\n + * Notice that this function only available when the main time line is + * paused. + */ + virtual void nextFrame()=0; +}; + +#endif // GROUNDBASE_H diff --git a/groundeditor.cpp b/groundeditor.cpp new file mode 100644 index 0000000..3fe17a1 --- /dev/null +++ b/groundeditor.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include + +#include "groundeditor.h" + +GroundEditor::GroundEditor(QWidget *parent) : + QWidget(parent), + m_groundPoints(new QTableWidget(this)) +{ + //Configure the ground points editor. + m_groundPoints->setColumnCount(2); + + //Initial the layout. + QBoxLayout *mainLayout=new QBoxLayout(QBoxLayout::TopToBottom, + this); + mainLayout->setSpacing(0); + setLayout(mainLayout); + + //Initial the actions. + QBoxLayout *actionLayout=new QBoxLayout(QBoxLayout::LeftToRight, + mainLayout->widget()); + for(int i=0; iaddWidget(m_actions[i]); + } + //Set key sequence. + m_actions[AddPoint]->setShortcut(QKeySequence(Qt::Key_Plus)); + actionLayout->addStretch(); + + mainLayout->addWidget(m_groundPoints, 1); + mainLayout->addLayout(actionLayout); + + retranslate(); +} + +void GroundEditor::retranslate() +{ + //Update ground points header. + QStringList groundHeader; + groundHeader << tr("X") << tr("Y"); + m_groundPoints->setHorizontalHeaderLabels(groundHeader); + + //Set the text. + m_actions[AddPoint]->setText("+"); + m_actions[RemovePoint]->setText("-"); +} diff --git a/groundeditor.h b/groundeditor.h new file mode 100644 index 0000000..33f6692 --- /dev/null +++ b/groundeditor.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef GROUNDEDITOR_H +#define GROUNDEDITOR_H + +#include + +class QToolButton; +class QTableWidget; +/*! + * \brief The GroundEditor class can edit a ground-guard-bordor, and set the new + * border to that ground. + */ +class GroundEditor : public QWidget +{ + Q_OBJECT +public: + /*! + * \brief Construct Ground Editor. + * \param parent The parent widget. + */ + explicit GroundEditor(QWidget *parent = 0); + +signals: + +public slots: + +private slots: + void retranslate(); + +private: + enum GroundEditActions + { + AddPoint, + RemovePoint, + GroundEditActionsCount + }; + QToolButton *m_actions[GroundEditActionsCount]; + + QTableWidget *m_groundPoints; +}; + +#endif // GROUNDEDITOR_H diff --git a/groundpreviewwidget.cpp b/groundpreviewwidget.cpp new file mode 100644 index 0000000..892f7a3 --- /dev/null +++ b/groundpreviewwidget.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include + +#include "groundbase.h" +#include "robot.h" + +#include "groundpreviewwidget.h" + +#include + +GroundPreviewWidget::GroundPreviewWidget(QWidget *parent) : + QWidget(parent), + m_ground(nullptr), + m_previewGround(QPolygonF()), + m_previewBarracks(QPolygonF()), + m_xOffset(0), + m_yOffset(0), + m_groundParameter(1.0), + m_showPreviewPoint(false), + m_previewRobot(new Robot) +{ + setFixedSize(200,200); +} + +GroundPreviewWidget::~GroundPreviewWidget() +{ + delete m_previewRobot; +} + +void GroundPreviewWidget::setGround(GroundBase *ground) +{ + //Save the ground. + m_ground=ground; + //Link the ground. + connect(m_ground, &GroundBase::borderChanged, + this, &GroundPreviewWidget::onActionBorderChanged); + connect(m_ground, &GroundBase::barracksChanged, + this, &GroundPreviewWidget::onActionBarracksChanged); +} + +void GroundPreviewWidget::previewRobot(QPointF position, qreal angle) +{ + //Save the preview data. + m_previewRobot->setPos(pointFromGround(position)); + m_previewRobot->setAngle(angle); + //Update the preivew. + update(); +} + +void GroundPreviewWidget::paintEvent(QPaintEvent *event) +{ + QWidget::paintEvent(event); + //Check if we have a ground. + if(m_ground==nullptr) + { + return; + } + //Initial the painter. + QPainter painter(this); + painter.setRenderHints(QPainter::Antialiasing | + QPainter::TextAntialiasing | + QPainter::SmoothPixmapTransform, true); + //Paint the border. + painter.setPen(m_ground->borderColor()); + painter.drawPolygon(m_previewGround); + //Paint the barracks. + painter.setPen(m_ground->barracksColor()); + painter.drawPolygon(m_previewBarracks); + //If display the preview robot. + if(m_showPreviewPoint) + { + //Paint the preview robot. + m_previewRobot->paintRobot(&painter); + } +} + +void GroundPreviewWidget::onActionBorderChanged() +{ + //Check if the ground is available. + if(m_ground==nullptr) + { + return; + } + QPolygonF groundBorder=m_ground->border(), + previewGroundBorder; + //Update the ground height and width. + qreal groundHeight=m_ground->size().height(), + groundWidth=m_ground->size().width(); + //Update the offset. + if(groundHeightbarracks(), + previewBarracksBorder; + //Gernerate the preview border, will zoom the original ground. + for(QPointF borderPoint : barracksBorder) + { + previewBarracksBorder.append(pointFromGround(borderPoint)); + } + //Save the preview border. + m_previewBarracks=previewBarracksBorder; + //Update the widget. + update(); +} + +inline QPointF GroundPreviewWidget::pointFromGround(const QPointF &groundPoint) +{ + return QPointF((groundPoint.x()+m_xOffset)/m_groundParameter*width(), + (groundPoint.y()+m_yOffset)/m_groundParameter*height()); +} +bool GroundPreviewWidget::showPreviewPoint() const +{ + return m_showPreviewPoint; +} + +void GroundPreviewWidget::setShowPreviewPoint(bool showPreviewPoint) +{ + m_showPreviewPoint = showPreviewPoint; +} + diff --git a/groundpreviewwidget.h b/groundpreviewwidget.h new file mode 100644 index 0000000..46db57c --- /dev/null +++ b/groundpreviewwidget.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef GROUNDPREVIEWWIDGET_H +#define GROUNDPREVIEWWIDGET_H + +#include + +class GroundBase; +class Robot; +/*! + * \brief The GroundPreviewWidget class provides the basic information of a + * ground. It will display the border and barracks, automatically zoom it to + * specific size. + */ +class GroundPreviewWidget : public QWidget +{ + Q_OBJECT +public: + /*! + * \brief Construct a Ground preview widget. + * \param parent The parent widget. + */ + explicit GroundPreviewWidget(QWidget *parent = 0); + ~GroundPreviewWidget(); + + /*! + * \brief The widget will display or hide the preview robot. + * \return If display the preview robot, will return true, or else false. + */ + bool showPreviewPoint() const; + +signals: + +public slots: + /*! + * \brief Set the rendering Ground class. + * \param ground The render ground. + */ + void setGround(GroundBase *ground); + + /*! + * \brief Make the preview widget to display the preview robot or not. + * \param showPreviewPoint The preview enabled value. + */ + void setShowPreviewPoint(bool showPreviewPoint); + + /*! + * \brief Will display a robot on the preview map. + * \param position + * \param angle + */ + void previewRobot(QPointF position, qreal angle); + +protected: + void paintEvent(QPaintEvent *event); + +private slots: + void onActionBorderChanged(); + void onActionBarracksChanged(); + +private: + inline QPointF pointFromGround(const QPointF &groundPoint); + GroundBase *m_ground; + QPolygonF m_previewGround, m_previewBarracks; + + qreal m_xOffset, m_yOffset, m_groundParameter; + bool m_showPreviewPoint; + Robot *m_previewRobot; +}; + +#endif // GROUNDPREVIEWWIDGET_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..6fea83b --- /dev/null +++ b/main.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "mainwindow.h" + +#include + +/*! + * \brief Initial the main window of the application. + * \param argc Argument count. + * \param argv Argument values. + * \return + */ +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + //Set application information. + QApplication::setApplicationName("Robot Emulator"); + QApplication::setApplicationDisplayName("Robot Emulator"); + //Conrtruct main window. + MainWindow mainWindow; + mainWindow.show(); + //Expand the event loop. + return app.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..4dec181 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include + +#include "ground.h" +#include "paneldock.h" +#include "menubar.h" +#include "robotmanagement.h" +#include "generateground.h" + +#include "mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + m_ground(new Ground(this)), + m_panel(new PanelDock(this)), + m_menuBar(new MenuBar(this)), + m_robotManagement(new RobotManagement(this)), + m_groundGenerator(new GenerateGround(this)) +{ + //A hack, using box layout to make the ground the center. + QWidget *container=new QWidget(this); + //Set the central widget. + setCentralWidget(container); + QBoxLayout *mainLayout=new QBoxLayout(QBoxLayout::LeftToRight, + container); + container->setLayout(mainLayout); + //Add ground and panel to layout. + mainLayout->addWidget(m_ground, 1, Qt::AlignCenter); + mainLayout->addWidget(m_panel); + + //Set the ground generator. + m_ground->setGenerator(m_groundGenerator); + + //Give the ground to elements. + m_panel->setGround(m_ground); + m_robotManagement->setGround(m_ground); + + //Give the menu bar to elements. + m_ground->setMenuBar(m_menuBar); + m_panel->setMenuBar(m_menuBar); + m_robotManagement->setMenuBar(m_menuBar); + + //Add panel to bottom dock area. + addDockWidget(Qt::RightDockWidgetArea, m_panel); + m_panel->setAllowedAreas(Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea); +#ifdef Q_OS_MACX + setWindowTitle("Robot Emulator"); +#else + setMenuBar(m_menuBar); +#endif +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..f5a59ca --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +class QScrollArea; +class Ground; +class PanelDock; +class MenuBar; +class RobotManagement; +class GenerateGround; +/*! + * \brief The MainWindow class is the top widget of all the visible widget. The + * only mission of MainWindow is going to show the Ground widget and take the + * fully management of the Ground widget. + */ +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + /*! + * \brief Constructs the MainWindow with the given parent. This class should + * only be constructed by main() function. + * \param parent The parent widget. + */ + explicit MainWindow(QWidget *parent = 0); + +signals: + +public slots: + +private: + Ground *m_ground; + PanelDock *m_panel; + MenuBar *m_menuBar; + RobotManagement *m_robotManagement; + GenerateGround *m_groundGenerator; +}; + +#endif // MAINWINDOW_H diff --git a/menubar.cpp b/menubar.cpp new file mode 100644 index 0000000..b6aba7b --- /dev/null +++ b/menubar.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include + +#include "menubar.h" + +MenuBar::MenuBar(QWidget *parent) : + QMenuBar(parent) +{ + //Initial all the menu and add to menu bar. + for(int i=0; i-1 && categoryaddAction(action); + } +} + +void MenuBar::retranslate() +{ + m_categoryMenu[File]->setTitle(tr("File")); + m_categoryMenu[View]->setTitle(tr("View")); + m_categoryMenu[Ground]->setTitle(tr("Ground")); + m_categoryMenu[Robot]->setTitle(tr("Robot")); + m_categoryMenu[TimeLine]->setTitle(tr("Time Line")); + m_categoryMenu[Help]->setTitle(tr("Help")); +} diff --git a/menubar.h b/menubar.h new file mode 100644 index 0000000..1b52c62 --- /dev/null +++ b/menubar.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MENUBAR_H +#define MENUBAR_H + +#include + +/*! + * \brief The MenuBar class contains the menu for all the categories. + */ +class MenuBar : public QMenuBar +{ + Q_OBJECT +public: + enum ActionCategories + { + File, + View, + Ground, + Robot, + TimeLine, + Help, + ActionCategoriesCount + }; + /*! + * \brief Contruct the MenuBar. + * \param parent The parent widget. + */ + explicit MenuBar(QWidget *parent = 0); + /*! + * \brief Add actions to the specific category menu. + * \param category The category menu index. + * \param action The action which is waiting to add. + */ + void addCategoryAction(int category, QAction *action); + +signals: + +public slots: + +private slots: + void retranslate(); + +private: + QMenu *m_categoryMenu[ActionCategoriesCount]; +}; + +#endif // MENUBAR_H diff --git a/panel.cpp b/panel.cpp new file mode 100644 index 0000000..811910a --- /dev/null +++ b/panel.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include + +#include "panel.h" +#include "menubar.h" +#include "groundbase.h" + +Panel::Panel(QWidget *parent) : + QWidget(parent), + m_mainLayout(new QBoxLayout(QBoxLayout::TopToBottom, this)) +{ + //Set the main layout. + m_mainLayout->setContentsMargins(0,0,0,0); + m_mainLayout->setSpacing(2); + setLayout(m_mainLayout); + + //Add the buttons and actions. + for(int i=0; iaddWidget(m_commands[i]); + //Initial the actions. + m_commandActions[i]=new QAction(this); + //Link the actions to the button. + connect(m_commandActions[i], SIGNAL(triggered()), + m_commands[i], SLOT(click())); + } + m_mainLayout->addStretch(); + + //Set shortcuts. + m_commandActions[Start]->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_R)); + m_commandActions[Pause]->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_E)); + m_commandActions[Reset]->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_T)); + m_commandActions[NextFrame]->setShortcut(QKeySequence(Qt::CTRL+ + Qt::SHIFT+ + Qt::Key_M)); + + retranslate(); +} + +void Panel::setGround(GroundBase *ground) +{ + connect(m_commands[Start], + static_cast(&QPushButton::clicked), + [=]{ground->start();}); + connect(m_commands[Pause], + static_cast(&QPushButton::clicked), + [=]{ground->pause();}); + connect(m_commands[Reset], + static_cast(&QPushButton::clicked), + [=]{ground->reset();}); + connect(m_commands[NextFrame], + static_cast(&QPushButton::clicked), + [=]{ground->nextFrame();}); + connect(m_commands[SaveScreenshot], + static_cast(&QPushButton::clicked), + [=] + { + if(ground->size().isNull() || ground->size().isEmpty()) + { + return; + } + //Get the snapshot. + QPixmap snapshot(ground->size()); + ground->render(&snapshot); + //If we get nothing, then no image will be save. + if(snapshot.isNull()) + { + return; + } + //Get the image path. + QString snapshotPath=QFileDialog::getSaveFileName(this, + tr("Save snapshot"), + QString(), + tr("Portable Network Graphic Format(*.png)")); + if(!snapshotPath.isEmpty()) + { + //Save the file. + snapshot.save(snapshotPath, "png"); + } + }); +} + +void Panel::setMenuBar(MenuBar *menuBar) +{ + //Add all the controls to timeline menu. + for(int i=0; iaddCategoryAction(MenuBar::TimeLine, m_commandActions[i]); + } +} + +void Panel::retranslate() +{ + QString actionCaptions[ControlCommandCount]; + actionCaptions[Start]=tr("Start"); + actionCaptions[Pause]=tr("Pause"); + actionCaptions[Reset]=tr("Reset"); + actionCaptions[NextFrame]=tr("Next Frame"); + actionCaptions[SaveScreenshot]=tr("Save current status"); + + //Update the command buttons and actions. + for(int i=0; isetText(actionCaptions[i]); + m_commandActions[i]->setText(actionCaptions[i]); + } +} diff --git a/panel.h b/panel.h new file mode 100644 index 0000000..711a9b3 --- /dev/null +++ b/panel.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PANEL_H +#define PANEL_H + +#include + +class QBoxLayout; +class QPushButton; +class GroundBase; +class MenuBar; +/*! + * \brief The Panel class is the control panel of the ground, it can control the + * time line of the Ground class. + */ +class Panel : public QWidget +{ + Q_OBJECT +public: + /*! + * \brief Construct a timeline control panel. + * \param parent The parent widget. + */ + explicit Panel(QWidget *parent = 0); + +signals: + +public slots: + /*! + * \brief Set the controlled GroundBase class to the panel, it will + * automatcially link the the signal and the slots. + * \param ground The controlled ground class. + */ + void setGround(GroundBase *ground); + /*! + * \brief Set the menu bar to add control actions. + * \param menuBar The menu bar. + */ + void setMenuBar(MenuBar *menuBar); + +private slots: + void retranslate(); + +private: + enum ControlCommands + { + Start, + Pause, + Reset, + NextFrame, + SaveScreenshot, + ControlCommandCount, + }; + QPushButton *m_commands[ControlCommandCount]; + QAction *m_commandActions[ControlCommandCount]; + + QBoxLayout *m_mainLayout; +}; + +#endif // PANEL_H diff --git a/paneldock.cpp b/paneldock.cpp new file mode 100644 index 0000000..9673661 --- /dev/null +++ b/paneldock.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include + +#include "panel.h" +#include "menubar.h" + +#include "paneldock.h" + +PanelDock::PanelDock(QWidget *parent) : + QDockWidget(parent), + m_panel(new Panel(this)), + m_dockVisible(new QAction(this)) +{ + //Set the widget. + setWidget(m_panel); + //Set the action. + m_dockVisible->setCheckable(true); + connect(m_dockVisible, + static_cast(&QAction::triggered), + [=]{isVisible()?hide():show();}); + + retranslate(); +} + +void PanelDock::setGround(GroundBase *ground) +{ + m_panel->setGround(ground); +} + +void PanelDock::setMenuBar(MenuBar *menuBar) +{ + m_panel->setMenuBar(menuBar); + //Add dock visible action to menu bar. + menuBar->addCategoryAction(MenuBar::View, m_dockVisible); +} + +void PanelDock::hideEvent(QHideEvent *event) +{ + //Hide the dock. + QDockWidget::hideEvent(event); + //Update the action. + m_dockVisible->setChecked(false); +} + +void PanelDock::showEvent(QShowEvent *event) +{ + //Hide the dock. + QDockWidget::showEvent(event); + //Update the action. + m_dockVisible->setChecked(true); +} + +void PanelDock::retranslate() +{ + m_dockVisible->setText(tr("Control Dock")); +} diff --git a/paneldock.h b/paneldock.h new file mode 100644 index 0000000..bcafb49 --- /dev/null +++ b/paneldock.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PANELDOCK_H +#define PANELDOCK_H + +#include + +class Panel; +class GroundBase; +class MenuBar; +class PanelDock : public QDockWidget +{ + Q_OBJECT +public: + /*! + * \brief Contruct a Panel dock widget. + * \param parent The main windows of the dock. + */ + explicit PanelDock(QWidget *parent = 0); + +signals: + +public slots: + /*! + * \brief The proxy set function of the panel widget. + * \param ground The controlled ground class. + */ + void setGround(GroundBase *ground); + /*! + * \brief The proxy set function of the panel widget. + * \param menuBar The menu bar. + */ + void setMenuBar(MenuBar *menuBar); + +protected: + void hideEvent(QHideEvent *event); + void showEvent(QShowEvent *event); + +private slots: + void retranslate(); + +private: + Panel *m_panel; + QAction *m_dockVisible; +}; + +#endif // PANELDOCK_H diff --git a/robot.cpp b/robot.cpp new file mode 100644 index 0000000..9cdd163 --- /dev/null +++ b/robot.cpp @@ -0,0 +1,448 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include + +#include "robot.h" + +#include + +Robot::Robot() : + m_angle(0.0), + m_hasGuardianLine(false), + m_guardianLine(QPointF(0,0), QPointF(0,0)), + m_toP1Distance(0.0), + m_movingSpeed(1.0) +{ + setPos(QPointF(0, 0)); +} + +Robot::Robot(QPointF pos) : + Robot() +{ + setPos(pos); +} + +Robot::Robot(qreal x, qreal y) : + Robot() +{ + setPos(x, y); +} + +QPointF Robot::pos() const +{ + return m_pos; +} + +void Robot::setPos(const QPointF &pos) +{ + m_pos = pos; +} + +void Robot::paintRobot(QPainter *painter) +{ + //Draw the direction of the robot. + QLineF directionLine(m_pos, m_pos+QPointF(m_detectRadius, 0)); + directionLine.setAngle(m_angle); + painter->setPen(m_directionLineColor); + painter->drawLine(directionLine); + + //Draw the detect radius. + painter->setPen(m_detectRadiusColor); + painter->drawEllipse(m_pos, m_detectRadius, m_detectRadius); + + //Draw the robot. + painter->setPen(m_robotColor); + painter->drawEllipse(m_pos, m_robotSize, m_robotSize); +} + +int Robot::m_robotSize=2; + +int Robot::robotSize() +{ + return m_robotSize; +} + +void Robot::setRobotSize(int robotSize) +{ + m_robotSize = robotSize; +} + +int Robot::m_detectRadius=20; + +int Robot::detectRadius() +{ + return m_detectRadius; +} + +void Robot::setDetectRadius(int detectRadius) +{ + m_detectRadius = detectRadius; +} + +QColor Robot::m_robotColor=QColor(255,0,255); + +void Robot::setRobotColor(const QColor &robotColor) +{ + m_robotColor=robotColor; +} + +QColor Robot::robotColor() +{ + return m_robotColor; +} + +QColor Robot::m_detectRadiusColor=QColor(127,0,255); + +QColor Robot::detectRadiusColor() +{ + return m_detectRadiusColor; +} + +void Robot::setDetectRadiusColor(const QColor &detectRadiusColor) +{ + m_detectRadiusColor = detectRadiusColor; +} + +qreal Robot::angle() const +{ + return m_angle; +} + +void Robot::setAngle(const qreal &angle) +{ + m_angle = angle; + //Change the angle. + while(m_angle>360.0) + { + m_angle-=360.0; + } + while(m_angle<0.0) + { + m_angle+=360.0; + } +} + +QColor Robot::m_directionLineColor=QColor(127, 127, 0); + +QColor Robot::directionLineColor() +{ + return m_directionLineColor; +} + +void Robot::setDirectionLineColor(const QColor &detectLineColor) +{ + m_directionLineColor = detectLineColor; +} + +void Robot::addToDetectList(Robot *robot) +{ + //Check the robot whether has already be in the list. + if(!m_detectedRobotList.contains(robot)) + { + m_detectedRobotList.append(robot); + } +} + +void Robot::removeFromDetectList(Robot *robot) +{ + //Remove all the robot from the list. + m_detectedRobotList.removeOne(robot); +} + +void Robot::moveOneStep() +{ + //Get the next step and set the position. + setPos(nextStep()); + //If this robot has a guardian line, change the toP1Distance. + if(m_hasGuardianLine) + { + m_toP1Distance+=m_movingSpeed; + } +} + +QPointF Robot::nextStep() const +{ + //If the robot has the guardian line, calculate the next step on the line. + if(m_hasGuardianLine) + { + //Get the next position. + qreal robotPosition= (m_toP1Distance + m_movingSpeed) / + m_guardianLine.length(); + return m_guardianLine.pointAt(robotPosition); + } + //If not have a guardian line, then move to the direction. + //Generate the direction line. + QLineF directionLine(m_pos, m_pos+QPointF(m_detectRadius, 0)); + directionLine.setAngle(m_angle); + directionLine.setLength(1.0); + //The p2 is the next step position. + return directionLine.p2(); +} + +void Robot::updateDirection() +{ + //----Magic! Don't touch!--- + //If the detected list is empty, then keep the direction. + if(m_detectedRobotList.isEmpty()) + { + //If the robot has a guardian line, + if(m_hasGuardianLine) + { + //Check if the robot reach one side of the line. + if(m_toP1Distance<=0.9) + { + //Move to the guardian line angle. + m_movingSpeed=1.0; + m_angle=m_guardianLine.angle(); + return; + } + if(m_toP1Distance>=m_guardianLine.length()) + { + //Move to the opposite angle of the guardian line. + m_movingSpeed=-1.0; + m_angle=m_oppositeGuardianLine.angle(); + return; + } + } + //Or else keep the direction. + return; + } + //Now the detected robot list cannot be empty. + //If the robot has a line to guard. + if(m_hasGuardianLine) + { + //Check if the robot reach one side of the line. + if(m_toP1Distance<=0.9 || m_toP1Distance>=m_guardianLine.length()-0.9) + { + //Move to the different direction. + if(m_movingSpeed>0) + { + m_movingSpeed=-1.0; + m_angle=m_oppositeGuardianLine.angle(); + } + else + { + m_movingSpeed=1.0; + m_angle=m_guardianLine.angle(); + } + return; + } + //Or else, we should have move the robot to opposite direction of the + //nearest robot. + //The nearest robot have three kind of types: + // 1. It doesn't have a guardian line. + // 2. It has a guardian line, but it's not the same as mine. + // 3. It has the same guardian line. + //For the first type, ignore it. + //For the second and third type, there's one rule: the robot should + //move to the direction which should leave that robot away. + QList statusList; + for(Robot *robot : m_detectedRobotList) + { + RobotStatus currentStatus; + currentStatus.robot=robot; + currentStatus.distance=QLineF(m_pos, robot->pos()).angle(); + statusList.append(currentStatus); + } + qSort(statusList); + //Get the nearest robot, . + RobotStatus nearestStatus=statusList.takeFirst(); + while(!nearestStatus.robot->hasGuardianLine() && !statusList.isEmpty()) + { + nearestStatus=statusList.takeFirst(); + } + //Check the nearest status. + if(!nearestStatus.robot->hasGuardianLine()) + { + //All the robot in the detect range don't has a guardian line. + //They will move away from this point. + return; + } + //So now, we get the nearest point which contains a guardian line. + Robot *nearestRobot=nearestStatus.robot; + //If these two robot has the same guardian line, and they are getting + //closer(have the different speed), move to the other direction. + //If these two robots have the different speed. + //For this kinds of type, + //p1 this + //| | + //+---*><*---------------------- + // | + // nearest + // + //Or for this kinds of type, + // + // this p2 + // | | + //-----------------*><*----+ + // | + // nearest + // + //We have to change the direction. + // + //So now, there is an ugly thing we have to met.(What the fuck!) + //The nearest point is not at the same line, but according to the + //context, this line must be the neighbouring line. Like the following: + // + // --------+ + // | + // | + // + //We have change the direction when both of these robots are moving to + //the same point, and that point is pretty interesting. It's the p1 for + //the second line and the p2 for the first line. So: + // + // this p2(for this) + // | | + // -----*>-+-p1(for nearest) + // | + // ^ + // * + // | + // + //At this time, the moving speed of this and nearest will be different + //(this is 1.0 and nearest is -1.0). + //For another case, it will be like this: + // + // p1(for this) p1 + // | | + // p2(for nearest)-+-<*------- + // | + // ^ + // * + // | + // + //At this time, the moving speed of this and nearest will be different + //as well(this is -1.0 and nearest is 1.0). + //We have to change the direction in these two cases. + + if(nearestRobot->movingSpeed()!=m_movingSpeed) + { + if(nearestRobot->guardianLine()==m_guardianLine) + { + if((m_movingSpeed>0 && + m_toP1DistancetoP1Distance()) || + (m_movingSpeed<0 && + m_toP1Distance>nearestRobot->toP1Distance())) + { + //Move to the different direction. + moveToOppositeDirection(); + //Ask the robot move to the differect direction as well. + nearestRobot->moveToOppositeDirection(); + } + } + else + { + if((m_movingSpeed>0 && + m_toP1Distance>nearestRobot->toP1Distance()) || + (m_movingSpeed<0 && + m_toP1DistancetoP1Distance())) + { + //Move to the different direction. + moveToOppositeDirection(); + //Ask the robot move to the differect direction as well. + nearestRobot->moveToOppositeDirection(); + } + } + } + //Or else, keep moving. + return; + } + //The prefer direction is to link all the detected robots, calculate the + //average angle of the robot lists. + qreal angleSum=0.0; + for(Robot *robot : m_detectedRobotList) + { + angleSum+=QLineF(m_pos, robot->pos()).angle(); + } + angleSum/=m_detectedRobotList.size(); + //Set the angle to the opposite angle. + setAngle(angleSum+180.0); +} + +bool Robot::hasGuardianLine() const +{ + return m_hasGuardianLine; +} + +void Robot::setGuardianLine(const QLineF &line, + const QPointF &footPoint) +{ + //Clear the previous data. + resetGuardianLine(); + //Check the length of the line. + if(line.length()==0.0) + { + return; + } + //Set has guardian line flag. + m_hasGuardianLine=true; + //Save the guardian line. + m_guardianLine=line; + //Get the opposite guardian line. + m_oppositeGuardianLine=QLineF(m_guardianLine.p2(), m_guardianLine.p1()); + QLineF directionAngle=QLineF(QPointF(0.0, 0.0), QPointF(10.0, 0)); + directionAngle.setAngle(m_angle); + //If the current angle is nearly to the angle, then the moving speed will be + //1.0(follow the direction of the line), or -1.0(reverse direction of the + //line) + if(m_oppositeGuardianLine.angleTo(directionAngle) < + m_guardianLine.angleTo(directionAngle)) + { + m_movingSpeed=1.0; + m_angle=m_guardianLine.angle(); + } + else + { + m_movingSpeed=-1.0; + m_angle=m_oppositeGuardianLine.angle(); + } + //Move the robot to the foot point. + setPos(footPoint); + //Save the initial distance to p1. + m_toP1Distance=pointDistance(m_guardianLine.p1(), footPoint); +} + +void Robot::resetGuardianLine() +{ + m_hasGuardianLine=false; + m_guardianLine=QLineF(); + m_oppositeGuardianLine=QLineF(); + m_toP1Distance=0.0; + m_movingSpeed=1.0; +} + +void Robot::moveToOppositeDirection() +{ + if(!m_hasGuardianLine) + { + return; + } + //If the robot is moving along the line, change the direction back. + if(m_movingSpeed>0) + { + m_movingSpeed=-1.0; + m_angle=m_oppositeGuardianLine.angle(); + } + else + { + m_movingSpeed=1.0; + m_angle=m_guardianLine.angle(); + } +} + diff --git a/robot.h b/robot.h new file mode 100644 index 0000000..3530ba2 --- /dev/null +++ b/robot.h @@ -0,0 +1,295 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef ROBOT_H +#define ROBOT_H + +#include +#include +#include +#include + +class QPainter; +/*! + * \brief The Robot class contains all the information and description of a + * robot, it contains the position, moving speed and direction of a robot. \n + * You can set the start position of a robot at any position you want. \n + * You have to recover the memory yourself. It don't have a parent. \n + * This is not a QObject for memory reduce, so there's no signal and slots. + */ +class Robot +{ +public: + /*! + * \brief Construct the robot. The start position of this type of construct + * will be QPointF(0, 0); + */ + Robot(); + + /*! + * \brief Construct the robot with the give position. + * \param pos The start position of the robot. + */ + Robot(QPointF pos); + + /*! + * \brief Construct the robot with the give position. + * \param x The start x position of the robot. + * \param y The start y position of the robot. + */ + Robot(qreal x, qreal y); + + /*! + * \brief The position of the robot. + * \return The QPointF format robot position. + */ + QPointF pos() const; + + /*! + * \brief Set the position of a robot. + * \param pos The position of the robot. + */ + void setPos(const QPointF &pos); + + /*! + * \brief This is an overloaded function.\n + * Set the position of a robot. + * \param x The x position of the robot. + * \param y The y position of the robot. + */ + inline void setPos(qreal x, qreal y) + { + setPos(QPointF(x, y)); + } + + /*! + * \brief Paint the robot with the specific painter. + * \param painter + */ + void paintRobot(QPainter *painter); + + /*! + * \brief Get the size of all the robots. + * \return The size of all robots. + */ + static int robotSize(); + + /*! + * \brief Change the size of all the robots. + * \param robotSize The new size of all robots. + */ + static void setRobotSize(int robotSize); + + /*! + * \brief Get the detect radius of all the robots. + * \return The detect radius of all robots. + */ + static int detectRadius(); + + /*! + * \brief Change all the detect radius of all the robots. + * \param detectRadius The new detect radius of all the robots. + */ + static void setDetectRadius(int detectRadius); + + /*! + * \brief Sets the color of the robot. + * \param robotColor The prefer color of all robots. + */ + static void setRobotColor(const QColor &robotColor); + + /*! + * \brief Get the color of all robots. + * \return The QColor of the robots. + */ + static QColor robotColor(); + + /*! + * \brief Get the color of the detection radius border of the robots. + * \return The QColor of the detection radius border of the robots. + */ + static QColor detectRadiusColor(); + + /*! + * \brief Change the color of the robot detection radius border. + * \param robotColor The prefer color of all the detection radius border of + * robots. + */ + static void setDetectRadiusColor(const QColor &detectRadiusColor); + + /*! + * \brief Get the moving angle of the robot. \n + * The default angle of the robot is 0 (3'o clock position). + * \return The angle of the robot. + */ + qreal angle() const; + + /*! + * \brief Change the moving angle of the robot, the value should be ranged + * from 0 degrees to 360 degrees. The program will automatically change the + * value. + * \param angle The prefer angle of the robot. + */ + void setAngle(const qreal &angle); + + /*! + * \brief Get the color the all the direction line color of the robots. + * \return The color of the direction line. + */ + static QColor directionLineColor(); + + /*! + * \brief Change the color of the direction line. + * \param directionLineColor The direction line color. + */ + static void setDirectionLineColor(const QColor &directionLineColor); + + /*! + * \brief Add a detected robot to the detection list. \n + * If the robot has been in the detect list, it won't add it twice. + * \param robot The robot which has been detected. + */ + void addToDetectList(Robot *robot); + + /*! + * \brief Remove one robot from the detect list. + * If the robot is not in the list, nothing will happened. + * \param robot The robot which should be removed. + */ + void removeFromDetectList(Robot *robot); + + /*! + * \brief Call this function will make the robot move 1 pixel length to the + * direction. + */ + void moveOneStep(); + + /*! + * \brief Get the next step of the robot is going to be. + * \return The next step position. + */ + QPointF nextStep() const; + + /*! + * \brief Update the direction of the robot according to the detected list. + */ + void updateDirection(); + + /*! + * \brief Get whether the robot has got a line to guard, each robot should + * guard one line. + * \return If the robot has a line to guard, return true, or else false. + */ + bool hasGuardianLine() const; + + /*! + * \brief Set a guardian line of to the robot. If the lenght of the line is + * 0, will remove the guardian state of the robot. + * \param line The guardian line of the robot. + */ + void setGuardianLine(const QLineF &line, const QPointF &footPoint); + + /*! + * \brief Clear the guardian line state data. + */ + void resetGuardianLine(); + + /*! + * \brief This function only available when there's a guardian line.\n + * Move to the opposite direction of the line. + */ + void moveToOppositeDirection(); + + /*! + * \brief The moving speed is only available when the robot got a guardian + * line, return the moving speed.\n + * This vale should be whether 1.0 or -1.0. + * \return The moving speed on a guardian line. + */ + qreal movingSpeed() const + { + return m_movingSpeed; + } + + /*! + * \brief This function is only available when the robot has a guardian + * line. It's a parameter for changing the direction. + * \return The robot distance to the p1 point of the guardian line. + */ + qreal toP1Distance() const + { + return m_toP1Distance; + } + + /*! + * \brief Get the guardian line of the current robot. + * \return The guardian line in QLineF format. + */ + QLineF guardianLine() const + { + return m_guardianLine; + } + + /*! + * \brief Calculate the distance of two point. + * \param p1 The first point. + * \param p2 The second point. + * \return The distance of two point. + */ + static qreal pointDistance(const QPointF p1, const QPointF p2) + { + return QLineF(p1, p2).length(); + } + + bool isDetectedListEmpty() + { + return m_detectedRobotList.isEmpty(); + } + +private: + struct RobotStatus + { + Robot *robot; + qreal distance; + RobotStatus(): + robot(nullptr), + distance(0.0) + { + ; + } + friend bool operator < (const RobotStatus &status1, + const RobotStatus &status2) + { + return status1.distance < status2.distance; + } + }; + + static int m_robotSize, m_detectRadius; + QPointF m_pos; + QList m_detectedRobotList; + + static QColor m_robotColor, m_detectRadiusColor, m_directionLineColor; + qreal m_angle; + + //Gardian line information + bool m_hasGuardianLine; + QLineF m_guardianLine, m_oppositeGuardianLine; + qreal m_toP1Distance, m_movingSpeed; +}; + +#endif // ROBOT_H diff --git a/robotaddwidget.cpp b/robotaddwidget.cpp new file mode 100644 index 0000000..6c92b5d --- /dev/null +++ b/robotaddwidget.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include + +#include "robotaddwidget.h" + +RobotAddWidget::RobotAddWidget(QWidget *parent) : + QWidget(parent), + m_okay(new QPushButton(this)), + m_cancel(new QPushButton(this)), + m_xData(new QSpinBox(this)), + m_yData(new QSpinBox(this)), + m_angleData(new QSlider(Qt::Horizontal, this)) +{ + //Intial labels. + for(int i=0; i<3; i++) + { + m_labels[i]=new QLabel(this); + } + //Initial the angle data. + m_angleData->setRange(0, 360); + m_xData->setRange(0, 0); + m_yData->setRange(0, 0); + + //Link edit widget. + connect(m_xData, SIGNAL(valueChanged(int)), + this, SLOT(onActionParameterChange())); + connect(m_yData, SIGNAL(valueChanged(int)), + this, SLOT(onActionParameterChange())); + connect(m_angleData, SIGNAL(valueChanged(int)), + this, SLOT(onActionParameterChange())); + + //Initial layouts. + QBoxLayout *mainLayout=new QBoxLayout(QBoxLayout::LeftToRight, + this); + mainLayout->setContentsMargins(0,0,0,0); + setLayout(mainLayout); + + //Generate the control layout. + QBoxLayout *controlLayout=new QBoxLayout(QBoxLayout::TopToBottom, + mainLayout->widget()); + controlLayout->setSpacing(2); + mainLayout->addLayout(controlLayout); + + QBoxLayout *positionLayout=new QBoxLayout(QBoxLayout::LeftToRight, + mainLayout->widget()); + positionLayout->setSpacing(5); + positionLayout->addWidget(m_labels[0]); + positionLayout->addWidget(m_xData, 1); + positionLayout->addSpacing(10); + positionLayout->addWidget(m_labels[1]); + positionLayout->addWidget(m_yData, 1); + controlLayout->addLayout(positionLayout); + QBoxLayout *angleLayout=new QBoxLayout(QBoxLayout::LeftToRight, + mainLayout->widget()); + angleLayout->addWidget(m_labels[2]); + angleLayout->addWidget(m_angleData, 1); + controlLayout->addLayout(angleLayout); + controlLayout->addStretch(); + + //Generate the button layout. + QBoxLayout *buttonLayout=new QBoxLayout(QBoxLayout::TopToBottom, + mainLayout->widget()); + buttonLayout->setSpacing(2); + buttonLayout->addWidget(m_okay); + buttonLayout->addWidget(m_cancel); + buttonLayout->addStretch(); + mainLayout->addLayout(buttonLayout); + + connect(m_okay, + static_cast(&QPushButton::clicked), + [=]{emit requireAddRobot(QPointF(m_xData->text().toDouble(), + m_yData->text().toDouble()), + m_angleData->value());}); + connect(m_cancel, + static_cast(&QPushButton::clicked), + [=]{emit requireClose();}); + + retranslate(); +} + +void RobotAddWidget::updateXAndYRange(const int &minX, const int &minY, + const int &maxX, const int &maxY) +{ + m_xData->setRange(minX, maxX); + m_yData->setRange(minY, maxY); +} + +void RobotAddWidget::showEvent(QShowEvent *event) +{ + QWidget::showEvent(event); + //Reset the data. + m_xData->setValue(m_xData->minimum()); + m_yData->setValue(m_yData->minimum()); + m_angleData->setValue(0); + //Update the preview. + onActionParameterChange(); +} + +void RobotAddWidget::retranslate() +{ + m_okay->setText(tr("Ok")); + m_cancel->setText(tr("Cancel")); + + m_labels[0]->setText(tr("X:")); + m_labels[1]->setText(tr("Y:")); + m_labels[2]->setText(tr("Angle:")); +} + +void RobotAddWidget::onActionParameterChange() +{ + emit requirePreviewRobot(QPointF(m_xData->text().toDouble(), + m_yData->text().toDouble()), + m_angleData->value()); +} diff --git a/robotaddwidget.h b/robotaddwidget.h new file mode 100644 index 0000000..8c84e13 --- /dev/null +++ b/robotaddwidget.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef ROBOTADDWIDGET_H +#define ROBOTADDWIDGET_H + +#include + +class QPushButton; +class QSpinBox; +class QSlider; +class QLabel; +class GroundBase; +/*! + * \brief The RobotAddWidget class is a widget for user to generate a robot in a + * user friend way. The user can set the initial position and the initial angle + * of the robot. The user can preview the robot state on the map. + */ +class RobotAddWidget : public QWidget +{ + Q_OBJECT +public: + /*! + * \brief Construct the RobotAddWidget class. + * \param parent The parent widget class. + */ + explicit RobotAddWidget(QWidget *parent = 0); + + /*! + * \brief Update the X position And Y position range. + * \param minX The minimal X coordinate value. + * \param minY The minimal Y coordinate value. + * \param maxX The maximum X coordinate value. + * \param maxY The maximum Y coordinate value. + */ + void updateXAndYRange(const int &minX, const int &minY, + const int &maxX, const int &maxY); + +signals: + /*! + * \brief When this signal is emitted, the robot management dialog will be + * closed. + */ + void requireClose(); + + /*! + * \brief When this signal is emitted, will ask the preview widget to draw a + * preview robot on the widget. + * \param position The preview robot position. + * \param angle The preview robot angle. + */ + void requirePreviewRobot(QPointF position, + qreal angle); + + /*! + * \brief This signal will ask the parent to try to add robot. + * \param position The prefer robot position. + * \param angle The prefer robot angle. + */ + void requireAddRobot(QPointF position, + qreal angle); + +public slots: + +protected: + /*! + * \brief Reimplemented from QWidget::showEvent(). + */ + void showEvent(QShowEvent *event); + +private slots: + void retranslate(); + void onActionParameterChange(); + +private: + QPushButton *m_okay, *m_cancel; + QLabel *m_labels[3]; + QSpinBox *m_xData, *m_yData; + QSlider *m_angleData; +}; + +#endif // ROBOTADDWIDGET_H diff --git a/robotmanagement.cpp b/robotmanagement.cpp new file mode 100644 index 0000000..a6fb09c --- /dev/null +++ b/robotmanagement.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include + +#include "ground.h" +#include "robot.h" +#include "menubar.h" +#include "robotaddwidget.h" +#include "groundpreviewwidget.h" + +#include "robotmanagement.h" + +#include + +RobotManagement::RobotManagement(QWidget *parent) : + QWidget(parent), + m_ground(nullptr), + m_groundPreview(new GroundPreviewWidget(this)), + m_stackLayout(new QStackedLayout), + m_robotAdd(new RobotAddWidget(this)) +{ + QBoxLayout *mainLayout=new QBoxLayout(QBoxLayout::LeftToRight, + this); + setLayout(mainLayout); + mainLayout->addWidget(m_groundPreview); + mainLayout->addLayout(m_stackLayout, 1); + //If we are using Mac OS X, using the sheet window flag. +#ifdef Q_OS_MACX + setWindowFlags(Qt::Sheet); +#else + setWindowFlags(Qt::Dialog); +#endif + + //Initial the actions. + for(int i=0; isetShortcut(QKeySequence(Qt::CTRL+Qt::Key_D)); + m_actions[ManageRobot]->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_A)); + + //Link the slots. + connect(m_actions[AddRobot], + static_cast(&QAction::triggered), + [=]{addRobot();}); + connect(m_actions[ManageRobot], + static_cast(&QAction::triggered), + [=]{manageRobot();}); + + //Generate the add robot widget. + connect(m_robotAdd, &RobotAddWidget::requireClose, + this, &RobotManagement::close); + connect(m_robotAdd, &RobotAddWidget::requirePreviewRobot, + m_groundPreview, &GroundPreviewWidget::previewRobot); + connect(m_robotAdd, &RobotAddWidget::requireAddRobot, + this, &RobotManagement::onActionAddRobot); + m_stackLayout->addWidget(m_robotAdd); + + //Retranslate. + retranslate(); +} + +GroundBase *RobotManagement::ground() +{ + return m_ground; +} + +void RobotManagement::addRobot() +{ + //Show the add robot widget. + m_stackLayout->setCurrentWidget(m_robotAdd); + //Make the preview show the preview robot. + m_groundPreview->setShowPreviewPoint(true); + //Update the range. + QRectF barracksBoundingRect=m_ground->barracks().boundingRect(); + m_robotAdd->updateXAndYRange(barracksBoundingRect.left(), + barracksBoundingRect.top(), + barracksBoundingRect.right(), + barracksBoundingRect.bottom()); + //Show the dialog. + show(); +} + +void RobotManagement::manageRobot() +{ + //Hide the preview robot. + m_groundPreview->setShowPreviewPoint(false); + //Show the dialog. + show(); +} + +void RobotManagement::setGround(GroundBase *ground) +{ + //Save the ground. + m_ground = ground; + //Give the ground to the preview. + m_groundPreview->setGround(m_ground); +} + +void RobotManagement::setMenuBar(MenuBar *menuBar) +{ + menuBar->addCategoryAction(MenuBar::Robot, m_actions[AddRobot]); + menuBar->addCategoryAction(MenuBar::Robot, m_actions[ManageRobot]); +} + +void RobotManagement::retranslate() +{ + m_actions[AddRobot]->setText(tr("Add robot")); + m_actions[ManageRobot]->setText(tr("Manage robots")); +} + +void RobotManagement::onActionAddRobot(const QPointF &position, + const qreal &angle) +{ + //Generate a robot. + Robot *robot=new Robot(position); + robot->setAngle(angle); + //Try to add the robot, if sucessful, close the dialog. + if(m_ground->addRobot(robot)) + { + close(); + return; + } + //Or else, display an error information. + QMessageBox::warning(this, + tr("Add Robot Failed"), + tr("The robot is not in the barracks, you cannot add this robot")); +} diff --git a/robotmanagement.h b/robotmanagement.h new file mode 100644 index 0000000..d0c0332 --- /dev/null +++ b/robotmanagement.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) Kreogist Dev Team + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef ROBOTMANAGEMENT_H +#define ROBOTMANAGEMENT_H + +#include + +class QStackedLayout; +class GroundBase; +class MenuBar; +class RobotAddWidget; +class GroundPreviewWidget; +/*! + * \brief The RobotManagement class is the dialog for robot add, modify and + * multi-robot remove. + */ +class RobotManagement : public QWidget +{ + Q_OBJECT +public: + /*! + * \brief Construct a robot management dialog. + * \param parent The parent widget. + */ + explicit RobotManagement(QWidget *parent = 0); + + /*! + * \brief Get the managing Ground class. + * \return The managing Ground class. + */ + GroundBase *ground(); + +signals: + +public slots: + /*! + * \brief Show add robot dialog. + */ + void addRobot(); + + /*! + * \brief Show the robots management dialog. + */ + void manageRobot(); + + /*! + * \brief Set the Ground class for signal robot management. + * \param ground The Ground class. + */ + void setGround(GroundBase *ground); + + /*! + * \brief Set the menu bar for action adding. + * \param menuBar The menu bar. + */ + void setMenuBar(MenuBar *menuBar); + +private slots: + void retranslate(); + void onActionAddRobot(const QPointF &position, + const qreal &angle); + +private: + enum RobotManagementActions + { + AddRobot, + ManageRobot, + RobotManagementActionsCount + }; + QAction *m_actions[RobotManagementActionsCount]; + + GroundBase *m_ground; + GroundPreviewWidget *m_groundPreview; + QStackedLayout *m_stackLayout; + RobotAddWidget *m_robotAdd; +}; + +#endif // ROBOTMANAGEMENT_H