diff --git a/src/graph/model/linegraphscene.cpp b/src/graph/model/linegraphscene.cpp index 42693a0b..8426e865 100644 --- a/src/graph/model/linegraphscene.cpp +++ b/src/graph/model/linegraphscene.cpp @@ -15,6 +15,18 @@ static inline qreal timeToHourFraction(const QTime &t) return ret; } +static inline double stationPlatformPosition(const StationGraphObject& st, const db_id platfId, const double platfOffset) +{ + double x = st.xPos; + for(const StationGraphObject::PlatformGraph& platf : st.platforms) + { + if(platf.platformId == platfId) + return x; + x += platfOffset; + } + return -1; +} + LineGraphScene::LineGraphScene(sqlite3pp::database &db, QObject *parent) : QObject(parent), mDb(db), @@ -97,7 +109,7 @@ bool LineGraphScene::loadGraph(db_id objectId, LineGraphType type, bool force) //Register a single station at start position st.xPos = curPos; stations.insert(st.stationId, st); - stationPositions = {{st.stationId, 0, st.xPos}}; + stationPositions = {{st.stationId, 0, st.xPos, {}}}; graphObjectName = st.stationName; } else if(type == LineGraphType::RailwaySegment) @@ -141,8 +153,8 @@ bool LineGraphScene::loadGraph(db_id objectId, LineGraphType type, bool force) stations.insert(stA.stationId, stA); stations.insert(stB.stationId, stB); - stationPositions = {{stA.stationId, objectId, stA.xPos}, - {stB.stationId, 0, stB.xPos}}; + stationPositions = {{stA.stationId, objectId, stA.xPos, {}}, + {stB.stationId, 0, stB.xPos, {}}}; } else if(type == LineGraphType::RailwayLine) { @@ -173,7 +185,6 @@ bool LineGraphScene::reloadJobs() return false; //TODO: maybe only load visible - //FIXME: also load job graph lines between stations for(StationGraphObject& st : stations) { @@ -181,6 +192,9 @@ bool LineGraphScene::reloadJobs() return false; } + //Save last station from previous iteration + auto lastSt = stations.constEnd(); + for(int i = 0; i < stationPositions.size(); i++) { StationPosEntry& stPos = stationPositions[i]; @@ -195,15 +209,25 @@ bool LineGraphScene::reloadJobs() if(!toStId) break; //No next station - auto fromSt = stations.constFind(fromStId); - if(fromSt == stations.constEnd()) - continue; + auto fromSt = lastSt; + if(fromSt == stations.constEnd() || fromSt->stationId != fromStId) + { + fromSt = stations.constFind(fromStId); + if(fromSt == stations.constEnd()) + { + continue; + } + } auto toSt = stations.constFind(toStId); if(toSt == stations.constEnd()) continue; + if(!loadSegmentJobs(stPos, fromSt.value(), toSt.value())) + return false; + //Store last station + lastSt = toSt; } return true; @@ -223,7 +247,7 @@ JobEntry LineGraphScene::getJobAt(const QPointF &pos, const double tolerance) db_id prevStId = 0; db_id nextStId = 0; - for(const StationPosEntry& stPos : stationPositions) + for(const StationPosEntry& stPos : qAsConst(stationPositions)) { if(stPos.xPos <= pos.x()) prevStId = stPos.stationId; @@ -435,7 +459,7 @@ bool LineGraphScene::loadFullLine(db_id lineId) st.xPos = curPos; stations.insert(st.stationId, st); - stationPositions.append({st.stationId, railwaySegmentId, st.xPos}); + stationPositions.append({st.stationId, railwaySegmentId, st.xPos, {}}); curPos += st.platforms.count() * Session->platformOffset + Session->stationOffset; } else if(fromStationId != lastStationId) @@ -454,7 +478,7 @@ bool LineGraphScene::loadFullLine(db_id lineId) stations.insert(stB.stationId, stB); stationPositions.last().segmentId = railwaySegmentId; - stationPositions.append({stB.stationId, 0, stB.xPos}); + stationPositions.append({stB.stationId, 0, stB.xPos, {}}); curPos += stB.platforms.count() * Session->platformOffset + Session->stationOffset; lastStationId = stB.stationId; @@ -540,10 +564,18 @@ bool LineGraphScene::loadStationJobStops(StationGraphObject &st) return true; } -bool LineGraphScene::loadSegmentJobs(LineGraphScene::StationPosEntry& stPos, const StationGraphObject& fromStm, const StationGraphObject& toSt) +bool LineGraphScene::loadSegmentJobs(LineGraphScene::StationPosEntry& stPos, const StationGraphObject& fromSt, const StationGraphObject& toSt) { + //Reset previous job segment graph + stPos.nextSegmentJobGraphs.clear(); + + const double vertOffset = Session->vertOffset; + const double hourOffset = Session->hourOffset; + const double platfOffset = Session->platformOffset; + sqlite3pp::query q(mDb, "SELECT sub.*, jobs.category, g_out.track_id, g_in.track_id FROM (" - " SELECT stops.id AS cur_stop_id, lead(stops.id, 1) OVER win AS next_stop_id, stops.station_id," + " SELECT stops.id AS cur_stop_id, lead(stops.id, 1) OVER win AS next_stop_id," + " stops.station_id," " stops.job_id," " stops.departure, lead(stops.arrival, 1) OVER win AS next_stop_arrival," " stops.out_gate_conn," @@ -562,6 +594,39 @@ bool LineGraphScene::loadSegmentJobs(LineGraphScene::StationPosEntry& stPos, con for(auto stop : q) { //TODO: store line in stPos + JobSegmentGraph job; + job.fromStopId = stop.get(0); + job.toStopId = stop.get(1); + db_id stId = stop.get(2); + job.jobId = stop.get(3); + QTime departure = stop.get(4); + QTime arrival = stop.get(5); + //6 - out gate connection + //7 - in gate connection + //8 - segment_id + job.category = JobCategory(stop.get(9)); + job.fromPlatfId = stop.get(11); + job.toPlatfId = stop.get(12); + + if(toSt.stationId == stId) + { + //Job goes in opposite direction, reverse stops + qSwap(job.fromStopId, job.toStopId); + qSwap(job.fromPlatfId, job.toPlatfId); + qSwap(departure, arrival); + } + + //Calculate coordinates + job.fromDeparture.rx() = stationPlatformPosition(fromSt, job.fromPlatfId, platfOffset); + job.fromDeparture.ry() = vertOffset + timeToHourFraction(departure) * hourOffset; + + job.toArrival.rx() = stationPlatformPosition(toSt, job.toPlatfId, platfOffset); + job.toArrival.ry() = vertOffset + timeToHourFraction(arrival) * hourOffset; + + if(job.fromDeparture.x() < 0 || job.toArrival.x() < 0) + continue; //Skip, couldn't find platform + + stPos.nextSegmentJobGraphs.append(job); } return true; diff --git a/src/graph/model/linegraphscene.h b/src/graph/model/linegraphscene.h index a3807b2a..acc0f3e1 100644 --- a/src/graph/model/linegraphscene.h +++ b/src/graph/model/linegraphscene.h @@ -76,11 +76,41 @@ public slots: private: + /*! + * \brief Graph of the job while is moving + * + * Contains informations to draw job line between two adjacent stations + */ + typedef struct + { + db_id jobId; + JobCategory category; + + db_id fromStopId; + db_id fromPlatfId; + QPointF fromDeparture; + + db_id toStopId; + db_id toPlatfId; + QPointF toArrival; + } JobSegmentGraph; + + /*! + * \brief Station entry on scene + * + * Represents a station item placeholder in an ordered list of scene + */ typedef struct { db_id stationId; db_id segmentId; double xPos; + + QVector nextSegmentJobGraphs; + /*!< + * Stores job graph of the next segment + * Which means jobs departing from this staation and going to next one + */ } StationPosEntry; private: @@ -89,7 +119,7 @@ public slots: bool loadFullLine(db_id lineId); bool loadStationJobStops(StationGraphObject &st); - bool loadSegmentJobs(StationPosEntry &stPos, const StationGraphObject &fromStm, const StationGraphObject &toSt); + bool loadSegmentJobs(StationPosEntry &stPos, const StationGraphObject &fromSt, const StationGraphObject &toSt); private: friend class BackgroundHelper; diff --git a/src/graph/model/stationgraphobject.h b/src/graph/model/stationgraphobject.h index 97cdd193..c5354990 100644 --- a/src/graph/model/stationgraphobject.h +++ b/src/graph/model/stationgraphobject.h @@ -12,6 +12,7 @@ * \brief Graph of a railway station * * Contains informations to draw station name, platforms and jobs + * * \sa PlatformGraph */ class StationGraphObject @@ -38,31 +39,11 @@ class StationGraphObject double departureY; } JobStopGraph; - /*! - * \brief Graph of the job while is moving - * - * Contains informations to draw job line between two adjacent stations - */ - typedef struct - { - db_id jobId; - JobCategory category; - - db_id fromStopId; - db_id fromPlatfId; - double fromDepartureY; - - db_id toStopId; - db_id toPlatfId; - double toArrivalY; - } JobLineGraph; - /*! * \brief Graph of a station track (platform) * * Contains informations to draw platform line and header name * \sa JobStopGraph - * \sa JobLineGraph */ typedef struct { diff --git a/src/graph/view/backgroundhelper.cpp b/src/graph/view/backgroundhelper.cpp index 9be8b0aa..3b0430b8 100644 --- a/src/graph/view/backgroundhelper.cpp +++ b/src/graph/view/backgroundhelper.cpp @@ -220,6 +220,7 @@ void BackgroundHelper::drawJobStops(QPainter *painter, LineGraphScene *scene, co { for(const StationGraphObject::JobStopGraph& jobStop : platf.jobStops) { + //NOTE: departure comes AFTER arrival in time, opposite than job segment if(jobStop.arrivalY > rect.bottom() || jobStop.departureY < rect.top()) continue; //Skip, job not visible @@ -237,3 +238,46 @@ void BackgroundHelper::drawJobStops(QPainter *painter, LineGraphScene *scene, co } } } + +void BackgroundHelper::drawJobSegments(QPainter *painter, LineGraphScene *scene, const QRectF &rect) +{ + const double stationOffset = Session->stationOffset; + + QPen jobPen; + jobPen.setWidth(AppSettings.getJobLineWidth()); + + //Iterate until one but last + //This way we can always acces next station + for(int i = 0; i < scene->stationPositions.size() - 1; i++) + { + const LineGraphScene::StationPosEntry& stPos = scene->stationPositions.at(i); + + const double left = stPos.xPos; + double right = 0; + + if(i < scene->stationPositions.size() - 2) + { + const LineGraphScene::StationPosEntry& afterNextPos = scene->stationPositions.at(i + 2); + right = afterNextPos.xPos - stationOffset; + } + else + { + right = rect.right(); //Last station, use all space on right side + } + + if(left > rect.right() || right < rect.left()) + continue; //Skip station, it's not visible + + for(const LineGraphScene::JobSegmentGraph& job : stPos.nextSegmentJobGraphs) + { + //NOTE: departure comes BEFORE arrival in time, opposite than job stop + if(job.fromDeparture.y() > rect.bottom() || job.toArrival.y() < rect.top()) + continue; //Skip, job not visible + + jobPen.setColor(Session->colorForCat(job.category)); + painter->setPen(jobPen); + + painter->drawLine(job.fromDeparture, job.toArrival); + } + } +} diff --git a/src/graph/view/backgroundhelper.h b/src/graph/view/backgroundhelper.h index fad1686e..b9f043fb 100644 --- a/src/graph/view/backgroundhelper.h +++ b/src/graph/view/backgroundhelper.h @@ -28,6 +28,8 @@ class BackgroundHelper static void drawStations(QPainter *painter, LineGraphScene *scene, const QRectF& rect); static void drawJobStops(QPainter *painter, LineGraphScene *scene, const QRectF& rect); + + static void drawJobSegments(QPainter *painter, LineGraphScene *scene, const QRectF &rect); }; #endif // BACKGROUNDHELPER_H diff --git a/src/graph/view/linegraphview.cpp b/src/graph/view/linegraphview.cpp index 3ca85888..27e26e58 100644 --- a/src/graph/view/linegraphview.cpp +++ b/src/graph/view/linegraphview.cpp @@ -142,6 +142,7 @@ void LineGraphView::paintEvent(QPaintEvent *e) BackgroundHelper::drawStations(&painter, m_scene, exposedRect); BackgroundHelper::drawJobStops(&painter, m_scene, exposedRect); + BackgroundHelper::drawJobSegments(&painter, m_scene, exposedRect); } void LineGraphView::resizeEvent(QResizeEvent *)