372 lines
9.7 KiB
C++
372 lines
9.7 KiB
C++
/*
|
|
* ModelRailroadTimetablePlanner
|
|
* Copyright 2016-2023, Filippo Gentile
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#ifndef LINEGRAPHSCENE_H
|
|
#define LINEGRAPHSCENE_H
|
|
|
|
#include "utils/scene/igraphscene.h"
|
|
|
|
#include <QVector>
|
|
#include <QHash>
|
|
|
|
#include <QPointF>
|
|
|
|
#include "utils/types.h"
|
|
|
|
#include "graph/linegraphtypes.h"
|
|
|
|
#include "stationgraphobject.h"
|
|
|
|
namespace sqlite3pp {
|
|
class database;
|
|
}
|
|
|
|
/*!
|
|
* \brief Class to store line information
|
|
*
|
|
* Reimplement IGraphScene for railway line graph
|
|
* Stores information to draw railway contents in a LineGraphView
|
|
*
|
|
* \sa LineGraphManager
|
|
* \sa LineGraphView
|
|
*/
|
|
class LineGraphScene : public IGraphScene
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
/*!
|
|
* \brief Enum to describe pending update needed
|
|
*
|
|
* FIXME: allow to specify segments to update
|
|
*/
|
|
enum class PendingUpdate
|
|
{
|
|
NothingToDo = 0x0, //!< No content needs updating
|
|
ReloadJobs = 0x1, //!< Only Jobs need to be reloaded
|
|
ReloadStationNames = 0x2, //!< Only Station Names but not Station Plan has changed
|
|
FullReload = 0x4 //!< Do a full reload
|
|
};
|
|
Q_DECLARE_FLAGS(PendingUpdateFlags, PendingUpdate)
|
|
|
|
LineGraphScene(sqlite3pp::database &db, QObject *parent = nullptr);
|
|
|
|
void renderContents(QPainter *painter, const QRectF &sceneRect) override;
|
|
void renderHeader(QPainter *painter, const QRectF &sceneRect, Qt::Orientation orient,
|
|
double scroll) override;
|
|
|
|
/*!
|
|
* \brief Load graph contents
|
|
*
|
|
* Loads stations and jobs
|
|
*
|
|
* \param objectId Graph object ID
|
|
* \param type Graph type
|
|
* \param force Force reloading if objectId and type are the same as current
|
|
*
|
|
* \sa loadStation()
|
|
* \sa loadFullLine()
|
|
* \sa reloadJobs()
|
|
*/
|
|
bool loadGraph(db_id objectId, LineGraphType type, bool force = false);
|
|
|
|
/*!
|
|
* \brief Load graph jobs
|
|
*
|
|
* Reloads only jobs but not stations
|
|
* It also updates current job selection
|
|
* \sa loadGraph()
|
|
* \sa updateJobSelection()
|
|
*/
|
|
bool reloadJobs();
|
|
|
|
/*!
|
|
* \brief update header size
|
|
*
|
|
* Updates header size from settings valuse.
|
|
* \sa MRTPSettings
|
|
*/
|
|
void updateHeaderSize();
|
|
|
|
/*!
|
|
* \brief Get job at graph position
|
|
*
|
|
* \param pos Point in scene coordinates
|
|
* \param tolerance A tolerance if mouse doesn't exactly click on job item
|
|
*/
|
|
JobStopEntry getJobAt(const QPointF &pos, const double tolerance);
|
|
|
|
inline LineGraphType getGraphType() const
|
|
{
|
|
return graphType;
|
|
}
|
|
|
|
inline db_id getGraphObjectId() const
|
|
{
|
|
return graphObjectId;
|
|
}
|
|
|
|
inline QString getGraphObjectName() const
|
|
{
|
|
return graphObjectName;
|
|
}
|
|
|
|
/*!
|
|
* \brief get selected job
|
|
*
|
|
* Get selected job info
|
|
* \sa setSelectedJob()
|
|
*/
|
|
JobStopEntry getSelectedJob() const;
|
|
|
|
/*!
|
|
* \brief setSelectedJob
|
|
* \param stop a specific stop or just a job ID and its category
|
|
* \param sendChange emit redrawGraph() and jobSelected() signals if true
|
|
*
|
|
* Set job selection and schedule graph redraw
|
|
* \sa jobSelected()
|
|
* \sa getSelectedJob()
|
|
*/
|
|
void setSelectedJob(JobStopEntry stop, bool sendChange = true);
|
|
|
|
/*!
|
|
* \brief getDrawSelection
|
|
* \return true if selection is drawn
|
|
*
|
|
* When true and a Job is selected, it gets a semi transparent aurea
|
|
* around it's line to make it more visible
|
|
*
|
|
* \sa setDrawSelection()
|
|
*/
|
|
inline bool getDrawSelection()
|
|
{
|
|
return m_drawSelection;
|
|
}
|
|
|
|
/*!
|
|
* \brief setDrawSelection
|
|
* \param val true if needs to draw selection
|
|
*
|
|
* Sets scene option. You must manually redraw graph
|
|
* by calling \ref renderContents() or emitting \ref redrawGraph()
|
|
*
|
|
* \sa getDrawSelection()
|
|
*/
|
|
inline void setDrawSelection(bool val)
|
|
{
|
|
m_drawSelection = val;
|
|
}
|
|
|
|
/*!
|
|
* \brief requestShowZone
|
|
* \param stationId null if you want to select segment
|
|
* \param segmentId null if you want to select station
|
|
* \param from top of the zone
|
|
* \param to bottom of the zone
|
|
*
|
|
* Calculates a zone in the scene which show the selected station or entire segment
|
|
* (It depends on which is non-null)
|
|
* The y values are calculated from the QTime arguments
|
|
* Then it requests the view to show the area.
|
|
*
|
|
* \sa requestShowRect()
|
|
*/
|
|
bool requestShowZone(db_id stationId, db_id segmentId, QTime from, QTime to);
|
|
|
|
signals:
|
|
void graphChanged(int type, db_id objectId, LineGraphScene *self);
|
|
|
|
/*!
|
|
* \brief job selected
|
|
* \param jobId ID of the job on 0 if selection cleared.
|
|
* \param category job's category casted to int
|
|
* \param stopId possible stop ID hint to select a specific section
|
|
*
|
|
* Selection changed: either user clicked on a job
|
|
* or on an empty zone to clear selection
|
|
* \sa setSelectedJob()
|
|
*/
|
|
void jobSelected(db_id jobId, int category, db_id stopId);
|
|
|
|
public slots:
|
|
/*!
|
|
* \brief Reload everything
|
|
*
|
|
* Reload entire contents
|
|
* \sa loadSegmentJobs()
|
|
*/
|
|
void reload();
|
|
|
|
private:
|
|
/*!
|
|
* \brief Graph of the job while is moving
|
|
*
|
|
* Contains informations to draw job line between two adjacent stations
|
|
*/
|
|
struct JobSegmentGraph
|
|
{
|
|
db_id jobId;
|
|
JobCategory category;
|
|
|
|
db_id fromStopId;
|
|
db_id fromPlatfId;
|
|
QPointF fromDeparture;
|
|
|
|
db_id toStopId;
|
|
db_id toPlatfId;
|
|
QPointF toArrival;
|
|
};
|
|
|
|
/*!
|
|
* \brief Station entry on scene
|
|
*
|
|
* Represents a station item placeholder in an ordered list of scene
|
|
*/
|
|
struct StationPosEntry
|
|
{
|
|
db_id stationId;
|
|
db_id segmentId;
|
|
double xPos;
|
|
|
|
QVector<JobSegmentGraph> nextSegmentJobGraphs;
|
|
/*!<
|
|
* Stores job graph of the next segment
|
|
* Which means jobs departing from this staation and going to next one
|
|
*/
|
|
};
|
|
|
|
private:
|
|
/*!
|
|
* \brief Get job stop at graph position
|
|
*
|
|
* \param prevSt Station at position's left
|
|
* \param nextSt Station at position's right
|
|
* \param pos Point in scene coordinates
|
|
* \param tolerance A tolerance if mouse doesn't exactly click on job item
|
|
*
|
|
* Check if a job stop in this station matches requested position
|
|
* Otherwise return null selection
|
|
*/
|
|
JobStopEntry getJobStopAt(const StationGraphObject *prevSt, const StationGraphObject *nextSt,
|
|
const QPointF &pos, const double tolerance);
|
|
|
|
/*!
|
|
* \brief Recalculate and store content size
|
|
*
|
|
* Stores cached calculated size of the graph.
|
|
* It depends on settings like station offset.
|
|
* \sa MRTPSettings
|
|
*/
|
|
void recalcContentSize();
|
|
|
|
/*!
|
|
* \brief Load station details
|
|
*
|
|
* Loads station name and tracks (color, attributes, names)
|
|
* It does NOT load jobs, only tracks
|
|
*/
|
|
bool loadStation(StationGraphObject &st, QString &outFullName);
|
|
|
|
/*!
|
|
* \brief updateStationNames
|
|
*
|
|
* Update names of already loaded stations
|
|
* If graph type is SingleStation, graph name will be update too
|
|
*/
|
|
bool updateStationNames();
|
|
|
|
/*!
|
|
* \brief Load all stations in a railway line
|
|
*
|
|
* Loads stations of all railway line segments
|
|
* \sa loadStation()
|
|
*/
|
|
bool loadFullLine(db_id lineId);
|
|
|
|
/*!
|
|
* \brief Load job stops in station
|
|
*
|
|
* Load jobs stops, only the part on station's track
|
|
* \sa loadSegmentJobs()
|
|
*/
|
|
bool loadStationJobStops(StationGraphObject &st);
|
|
|
|
/*!
|
|
* \brief Load job segments between 2 stations
|
|
*
|
|
* Load job segments and stores them in 'from' station
|
|
* \sa loadStationJobStops()
|
|
*/
|
|
bool loadSegmentJobs(StationPosEntry &stPos, const StationGraphObject &fromSt,
|
|
const StationGraphObject &toSt);
|
|
|
|
/*!
|
|
* \brief Update job selection category
|
|
*
|
|
* Updates current selection.
|
|
* If selected job got removed or changed ID (Number) selection is cleared
|
|
* If selected stop got removed or doesn't belong to selected job it's cleared
|
|
* Category of selected job gets updated if changed in the meantime
|
|
*/
|
|
static void updateJobSelection(sqlite3pp::database &db, JobStopEntry &job);
|
|
|
|
private:
|
|
friend class BackgroundHelper;
|
|
friend class LineGraphManager;
|
|
|
|
sqlite3pp::database &mDb;
|
|
|
|
/*!
|
|
* \brief Graph Object ID
|
|
*
|
|
* Can be station, segment, line ID
|
|
* Depending on graph type
|
|
*/
|
|
db_id graphObjectId;
|
|
|
|
/*!
|
|
* \brief Type of Graph displayed by Scene
|
|
*/
|
|
LineGraphType graphType;
|
|
|
|
/*!
|
|
* \brief Graph Object Name
|
|
*
|
|
* Can be station, segment, line name
|
|
* Depending on graph type
|
|
*/
|
|
QString graphObjectName;
|
|
|
|
QVector<StationPosEntry> stationPositions;
|
|
QHash<db_id, StationGraphObject> stations;
|
|
|
|
/*!
|
|
* \brief Job selection
|
|
*
|
|
* Caches selected job item ID
|
|
*/
|
|
JobStopEntry selectedJob;
|
|
|
|
bool m_drawSelection;
|
|
|
|
PendingUpdateFlags pendingUpdate;
|
|
};
|
|
|
|
#endif // LINEGRAPHSCENE_H
|