mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-23 19:25:54 +01:00
Compare commits
5 Commits
36f8f94f15
...
037d621f50
Author | SHA1 | Date | |
---|---|---|---|
037d621f50 | |||
1a1db7f916 | |||
aae6c28c06 | |||
8180c4e755 | |||
649d972aec |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -9,8 +9,9 @@
|
||||
#include "areaitem.h"
|
||||
|
||||
|
||||
ToolTip AreaItem::info() const
|
||||
ToolTip AreaItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
ToolTip tt;
|
||||
|
||||
if (!_area.name().isEmpty())
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
void setDigitalZoom(int zoom);
|
||||
void updateStyle();
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
|
||||
protected:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||
|
@ -9,8 +9,9 @@ CadenceGraphItem::CadenceGraphItem(const Graph &graph, GraphType type,
|
||||
{
|
||||
}
|
||||
|
||||
ToolTip CadenceGraphItem::info() const
|
||||
ToolTip CadenceGraphItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
ToolTip tt;
|
||||
QLocale l(QLocale::system());
|
||||
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
CadenceGraphItem(const Graph &graph, GraphType type, int width,
|
||||
const QColor &color, QGraphicsItem *parent = 0);
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
};
|
||||
|
||||
#endif // CADENCEGRAPHITEM_H
|
||||
|
@ -26,8 +26,10 @@ ElevationGraphItem::ElevationGraphItem(const Graph &graph, GraphType type,
|
||||
}
|
||||
}
|
||||
|
||||
ToolTip ElevationGraphItem::info() const
|
||||
ToolTip ElevationGraphItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
|
||||
ToolTip tt;
|
||||
qreal scale = (_units == Metric) ? 1.0 : M2FT;
|
||||
QString su = (_units == Metric) ? tr("m") : tr("ft");
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
qreal max() const {return _max;}
|
||||
qreal min() const {return _min;}
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
|
||||
private:
|
||||
qreal _ascent, _descent, _min, _max;
|
||||
|
@ -27,8 +27,10 @@ GearRatioGraphItem::GearRatioGraphItem(const Graph &graph, GraphType type,
|
||||
_top = key;
|
||||
}
|
||||
|
||||
ToolTip GearRatioGraphItem::info() const
|
||||
ToolTip GearRatioGraphItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
|
||||
ToolTip tt;
|
||||
QLocale l(QLocale::system());
|
||||
|
||||
|
@ -15,7 +15,7 @@ public:
|
||||
qreal top() const {return _top;}
|
||||
const QMap<qreal, qreal> &map() const {return _map;}
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
|
||||
private:
|
||||
QMap<qreal, qreal> _map;
|
||||
|
@ -41,7 +41,8 @@ void GraphicsScene::helpEvent(QGraphicsSceneHelpEvent *event)
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (list.at(i)->type() == QGraphicsItem::UserType + 1) {
|
||||
GraphicsItem *mi = static_cast<GraphicsItem*>(list.at(i));
|
||||
Popup::show(event->screenPos(), mi->info(), event->widget());
|
||||
Popup::show(event->screenPos(), mi->info(_showExtendedInfo),
|
||||
event->widget());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ class GraphicsItem : public QGraphicsItem
|
||||
public:
|
||||
GraphicsItem(QGraphicsItem *parent = 0) : QGraphicsItem(parent) {}
|
||||
|
||||
virtual ToolTip info() const = 0;
|
||||
virtual ToolTip info(bool extended) const = 0;
|
||||
int type() const {return QGraphicsItem::UserType + 1;}
|
||||
|
||||
static void useStyle(bool use) {_useStyle = use;}
|
||||
@ -22,7 +22,11 @@ protected:
|
||||
class GraphicsScene : public QGraphicsScene
|
||||
{
|
||||
public:
|
||||
GraphicsScene(QObject *parent = 0) : QGraphicsScene(parent) {}
|
||||
GraphicsScene(QObject *parent = 0)
|
||||
: QGraphicsScene(parent), _showExtendedInfo(false) {}
|
||||
|
||||
bool showExtendedInfo() const {return _showExtendedInfo;}
|
||||
void showExtendedInfo(bool show) {_showExtendedInfo = show;}
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
@ -31,6 +35,8 @@ protected:
|
||||
void helpEvent(QGraphicsSceneHelpEvent *event);
|
||||
|
||||
private:
|
||||
bool _showExtendedInfo;
|
||||
|
||||
QList<QGraphicsItem *> itemsAtPosition(const QPoint &screenPos,
|
||||
const QPointF &scenePos, QWidget *widget) const;
|
||||
};
|
||||
|
@ -379,6 +379,9 @@ void GraphItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||
|
||||
void GraphItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
Popup::show(event->screenPos(), info(), event->widget());
|
||||
GraphicsScene *gs = dynamic_cast<GraphicsScene *>(scene());
|
||||
if (gs)
|
||||
Popup::show(event->screenPos(), info(gs->showExtendedInfo()),
|
||||
event->widget());
|
||||
GraphicsItem::mousePressEvent(event);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
const QColor &color, Qt::PenStyle style, QGraphicsItem *parent = 0);
|
||||
virtual ~GraphItem() {}
|
||||
|
||||
virtual ToolTip info() const = 0;
|
||||
virtual ToolTip info(bool extended) const = 0;
|
||||
|
||||
QPainterPath shape() const {return _shape;}
|
||||
QRectF boundingRect() const {return _shape.boundingRect();}
|
||||
|
@ -1069,6 +1069,8 @@ bool GUI::openFile(const QString &fileName, bool tryUnknown, int &showError)
|
||||
updateNavigationActions();
|
||||
updateStatusBarInfo();
|
||||
updateWindowTitle();
|
||||
if (_files.count() > 1)
|
||||
_mapView->showExtendedInfo(true);
|
||||
#ifndef Q_OS_ANDROID
|
||||
updateRecentFiles(canonicalFileName);
|
||||
#endif // Q_OS_ANDROID
|
||||
@ -1555,6 +1557,7 @@ void GUI::reloadFiles()
|
||||
_browser->setCurrent(_files.last());
|
||||
#endif // Q_OS_ANDROID
|
||||
updateDataDEMDownloadAction();
|
||||
_mapView->showExtendedInfo(_files.size() > 1);
|
||||
}
|
||||
|
||||
void GUI::closeFiles()
|
||||
@ -1575,6 +1578,7 @@ void GUI::closeFiles()
|
||||
_lastTab = 0;
|
||||
|
||||
_mapView->clear();
|
||||
_mapView->showExtendedInfo(false);
|
||||
|
||||
_files.clear();
|
||||
}
|
||||
|
@ -9,8 +9,10 @@ HeartRateGraphItem::HeartRateGraphItem(const Graph &graph, GraphType type,
|
||||
{
|
||||
}
|
||||
|
||||
ToolTip HeartRateGraphItem::info() const
|
||||
ToolTip HeartRateGraphItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
|
||||
ToolTip tt;
|
||||
QLocale l(QLocale::system());
|
||||
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
HeartRateGraphItem(const Graph &graph, GraphType type, int width,
|
||||
const QColor &color, QGraphicsItem *parent = 0);
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
};
|
||||
|
||||
#endif // HEARTRATEGRAPHITEM_H
|
||||
|
@ -71,8 +71,9 @@ static QRectF bbox(const RectC &rect, Map *map, int samples = 100)
|
||||
return prect;
|
||||
}
|
||||
|
||||
ToolTip MapItem::info() const
|
||||
ToolTip MapItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
ToolTip tt;
|
||||
|
||||
if (!_name.isEmpty())
|
||||
@ -212,7 +213,10 @@ void MapItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
||||
update();
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
Popup::show(event->screenPos(), info(), event->widget());
|
||||
GraphicsScene *gs = dynamic_cast<GraphicsScene *>(scene());
|
||||
if (gs)
|
||||
Popup::show(event->screenPos(), info(gs->showExtendedInfo()),
|
||||
event->widget());
|
||||
#endif // Q_OS_ANDROID
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
void setPenStyle(Qt::PenStyle style);
|
||||
void setDigitalZoom(int zoom);
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
|
||||
signals:
|
||||
void triggered();
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "coordinatesitem.h"
|
||||
#include "mapitem.h"
|
||||
#include "keys.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "mapaction.h"
|
||||
#include "markerinfoitem.h"
|
||||
#include "crosshairitem.h"
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "format.h"
|
||||
#include "markerinfoitem.h"
|
||||
#include "palette.h"
|
||||
#include "graphicsscene.h"
|
||||
|
||||
|
||||
class QGeoPositionInfoSource;
|
||||
@ -35,7 +36,6 @@ class GraphItem;
|
||||
class PlaneItem;
|
||||
class MapItem;
|
||||
class Area;
|
||||
class GraphicsScene;
|
||||
class QTimeZone;
|
||||
class MapAction;
|
||||
class CrosshairItem;
|
||||
@ -64,6 +64,7 @@ public:
|
||||
void setMap(Map *map);
|
||||
void setPositionSource(QGeoPositionInfoSource *source);
|
||||
void setGraph(int index);
|
||||
void showExtendedInfo(bool show) {_scene->showExtendedInfo(show);}
|
||||
|
||||
void plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
PlotFlags flags);
|
||||
|
@ -510,6 +510,9 @@ void PathItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||
|
||||
void PathItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
Popup::show(event->screenPos(), info(), event->widget());
|
||||
GraphicsScene *gs = dynamic_cast<GraphicsScene *>(scene());
|
||||
if (gs)
|
||||
Popup::show(event->screenPos(), info(gs->showExtendedInfo()),
|
||||
event->widget());
|
||||
GraphicsItem::mousePressEvent(event);
|
||||
}
|
||||
|
@ -76,6 +76,9 @@ QRect PathTickItem::tickRect(int value)
|
||||
void PathTickItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
const PathItem *pi = static_cast<PathItem*>(parentItem());
|
||||
Popup::show(event->screenPos(), pi->info(), event->widget());
|
||||
GraphicsScene *gs = dynamic_cast<GraphicsScene *>(scene());
|
||||
if (gs)
|
||||
Popup::show(event->screenPos(), pi->info(gs->showExtendedInfo()),
|
||||
event->widget());
|
||||
QGraphicsItem::mousePressEvent(event);
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ public:
|
||||
void setDigitalZoom(int zoom) {setScale(qPow(2, -zoom));}
|
||||
|
||||
int type() const {return parentItem()->type();}
|
||||
ToolTip info() const
|
||||
ToolTip info(bool extended) const
|
||||
{
|
||||
return static_cast<GraphicsItem*>(parentItem())->info();
|
||||
return static_cast<GraphicsItem*>(parentItem())->info(extended);
|
||||
}
|
||||
|
||||
static QRect tickRect(int value);
|
||||
|
@ -9,8 +9,9 @@ PowerGraphItem::PowerGraphItem(const Graph &graph, GraphType type, int width,
|
||||
{
|
||||
}
|
||||
|
||||
ToolTip PowerGraphItem::info() const
|
||||
ToolTip PowerGraphItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
ToolTip tt;
|
||||
QLocale l(QLocale::system());
|
||||
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
PowerGraphItem(const Graph &graph, GraphType type, int width,
|
||||
const QColor &color, QGraphicsItem *parent = 0);
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
};
|
||||
|
||||
#endif // POWERGRAPHITEM_H
|
||||
|
@ -1,14 +1,14 @@
|
||||
#include <QPainter>
|
||||
#include <QLocale>
|
||||
#include <QFileInfo>
|
||||
#include "data/waypoint.h"
|
||||
#include "data/route.h"
|
||||
#include "map/map.h"
|
||||
#include "format.h"
|
||||
#include "waypointitem.h"
|
||||
#include "tooltip.h"
|
||||
#include "routeitem.h"
|
||||
|
||||
|
||||
ToolTip RouteItem::info() const
|
||||
ToolTip RouteItem::info(bool extended) const
|
||||
{
|
||||
ToolTip tt;
|
||||
|
||||
@ -31,6 +31,13 @@ ToolTip RouteItem::info() const
|
||||
}
|
||||
tt.insert(tr("Links"), links);
|
||||
}
|
||||
#ifdef Q_OS_ANDROID
|
||||
Q_UNUSED(extended);
|
||||
#else // Q_OS_ANDROID
|
||||
if (extended && !_file.isEmpty())
|
||||
tt.insert(tr("File"), QString("<a href=\"file:%1\">%2</a>")
|
||||
.arg(_file, QFileInfo(_file).fileName()));
|
||||
#endif // Q_OS_ANDROID
|
||||
|
||||
return tt;
|
||||
}
|
||||
@ -48,6 +55,7 @@ RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)
|
||||
_desc = route.description();
|
||||
_comment = route.comment();
|
||||
_links = route.links();
|
||||
_file = route.file();
|
||||
}
|
||||
|
||||
void RouteItem::setMap(Map *map)
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
void showWaypointLabels(bool show);
|
||||
void showWaypointIcons(bool show);
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
QDateTime date() const {return QDateTime();}
|
||||
|
||||
private:
|
||||
@ -31,6 +31,7 @@ private:
|
||||
QString _comment;
|
||||
QVector<Link> _links;
|
||||
QVector<WaypointItem*> _waypoints;
|
||||
QString _file;
|
||||
};
|
||||
|
||||
#endif // ROUTEITEM_H
|
||||
|
@ -15,8 +15,10 @@ SpeedGraphItem::SpeedGraphItem(const Graph &graph, GraphType type, int width,
|
||||
_mavg = graph.last().last().s() / movingTime;
|
||||
}
|
||||
|
||||
ToolTip SpeedGraphItem::info() const
|
||||
ToolTip SpeedGraphItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
|
||||
ToolTip tt;
|
||||
qreal scale = (_units == Imperial) ? MS2MIH : (_units == Nautical)
|
||||
? MS2KN : MS2KMH;
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
qreal mavg() const {return _mavg;}
|
||||
qreal max() const {return _max;}
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
|
||||
void setTimeType(TimeType type);
|
||||
|
||||
|
@ -12,8 +12,10 @@ TemperatureGraphItem::TemperatureGraphItem(const Graph &graph, GraphType type,
|
||||
_avg = GraphItem::avg();
|
||||
}
|
||||
|
||||
ToolTip TemperatureGraphItem::info() const
|
||||
ToolTip TemperatureGraphItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
|
||||
ToolTip tt;
|
||||
qreal scale = (_units == Metric) ? 1.0 : C2FS;
|
||||
qreal offset = (_units == Metric) ? 0 : C2FO;
|
||||
|
@ -15,7 +15,7 @@ public:
|
||||
qreal min() const {return _min;}
|
||||
qreal avg() const {return _avg;}
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
|
||||
private:
|
||||
qreal _min, _max, _avg;
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include <QPainter>
|
||||
#include "map/map.h"
|
||||
#include <QLocale>
|
||||
#include "common/util.h"
|
||||
#include "data/track.h"
|
||||
#include "format.h"
|
||||
#include "tooltip.h"
|
||||
#include "trackitem.h"
|
||||
|
||||
|
||||
ToolTip TrackItem::info() const
|
||||
ToolTip TrackItem::info(bool extended) const
|
||||
{
|
||||
ToolTip tt;
|
||||
QLocale l;
|
||||
@ -39,6 +39,13 @@ ToolTip TrackItem::info() const
|
||||
}
|
||||
tt.insert(tr("Links"), links);
|
||||
}
|
||||
#ifdef Q_OS_ANDROID
|
||||
Q_UNUSED(extended);
|
||||
#else // Q_OS_ANDROID
|
||||
if (extended && !_file.isEmpty())
|
||||
tt.insert(tr("File"), QString("<a href=\"file:%1\">%2</a>")
|
||||
.arg(_file, QFileInfo(_file).fileName()));
|
||||
#endif // Q_OS_ANDROID
|
||||
|
||||
return tt;
|
||||
}
|
||||
@ -53,4 +60,5 @@ TrackItem::TrackItem(const Track &track, Map *map, QGraphicsItem *parent)
|
||||
_date = track.date();
|
||||
_time = track.time();
|
||||
_movingTime = track.movingTime();
|
||||
_file = track.file();
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class TrackItem : public PathItem
|
||||
public:
|
||||
TrackItem(const Track &track, Map *map, QGraphicsItem *parent = 0);
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
QDateTime date() const {return _date;}
|
||||
|
||||
private:
|
||||
@ -26,6 +26,7 @@ private:
|
||||
QDateTime _date;
|
||||
qreal _time;
|
||||
qreal _movingTime;
|
||||
QString _file;
|
||||
};
|
||||
|
||||
#endif // TRACKITEM_H
|
||||
|
@ -16,8 +16,9 @@ Units WaypointItem::_units = Metric;
|
||||
CoordinatesFormat WaypointItem::_format = DecimalDegrees;
|
||||
QTimeZone WaypointItem::_timeZone = QTimeZone::utc();
|
||||
|
||||
ToolTip WaypointItem::info() const
|
||||
ToolTip WaypointItem::info(bool extended) const
|
||||
{
|
||||
Q_UNUSED(extended);
|
||||
ToolTip tt;
|
||||
QLocale l;
|
||||
|
||||
@ -274,7 +275,10 @@ void WaypointItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||
|
||||
void WaypointItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
Popup::show(event->screenPos(), info(), event->widget());
|
||||
GraphicsScene *gs = dynamic_cast<GraphicsScene *>(scene());
|
||||
if (gs)
|
||||
Popup::show(event->screenPos(), info(gs->showExtendedInfo()),
|
||||
event->widget());
|
||||
/* Do not propagate the event any further as lower stacked items (path
|
||||
items) would replace the popup with their own popup */
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget);
|
||||
|
||||
ToolTip info() const;
|
||||
ToolTip info(bool extended) const;
|
||||
|
||||
static void setUnits(Units units) {_units = units;}
|
||||
static void setCoordinatesFormat(CoordinatesFormat format)
|
||||
|
@ -137,16 +137,14 @@ QString Util::displayName(const QString &path)
|
||||
QUrl url(path);
|
||||
|
||||
// Not an Android URL, return standard filename.
|
||||
if (url.scheme() != "content") {
|
||||
QFileInfo fi(path);
|
||||
return fi.fileName();
|
||||
if (url.scheme() != "content")
|
||||
return QFileInfo(path).fileName();
|
||||
// Directory browsing URLs. Those can not be translated using the Android
|
||||
// content resolver but we can get the filename from the URL path.
|
||||
} else if (url.path().startsWith("/tree/")) {
|
||||
QFileInfo fi(url.fileName());
|
||||
return fi.fileName();
|
||||
else if (url.path().startsWith("/tree/"))
|
||||
return QFileInfo(url.fileName()).fileName();
|
||||
// Translate all "regular" android URLs using the Android content resolver.
|
||||
} else
|
||||
else
|
||||
return documentName(path);
|
||||
#else
|
||||
return path;
|
||||
|
@ -86,7 +86,7 @@ bool CUPParser::waypoint(const QByteArrayList &entry,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CUPParser::task(const QByteArrayList &entry,
|
||||
bool CUPParser::task(const QString &fileName, const QByteArrayList &entry,
|
||||
const QVector<Waypoint> &waypoints, QList<RouteData> &routes)
|
||||
{
|
||||
if (entry.size() < 3) {
|
||||
@ -96,6 +96,7 @@ bool CUPParser::task(const QByteArrayList &entry,
|
||||
|
||||
RouteData r;
|
||||
r.setName(entry.at(0));
|
||||
r.setFile(fileName);
|
||||
for (int i = 1; i < entry.size(); i++) {
|
||||
if (entry.at(i) == "???")
|
||||
continue;
|
||||
@ -155,7 +156,7 @@ bool CUPParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
return false;
|
||||
} else if (segment == Tasks) {
|
||||
if (entry.at(0) != "Options" && !entry.at(0).startsWith("ObsZone=")
|
||||
&& !task(entry, waypoints, routes))
|
||||
&& !task(file->fileName(), entry, waypoints, routes))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,8 @@ public:
|
||||
|
||||
private:
|
||||
bool waypoint(const QByteArrayList &entry, QVector<Waypoint> &waypoints);
|
||||
bool task(const QByteArrayList &entry, const QVector<Waypoint> &waypoints,
|
||||
QList<RouteData> &routes);
|
||||
bool task(const QString &fileName, const QByteArrayList &entry,
|
||||
const QVector<Waypoint> &waypoints, QList<RouteData> &routes);
|
||||
|
||||
QString _errorString;
|
||||
int _errorLine;
|
||||
|
@ -481,6 +481,7 @@ bool FITParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
return false;
|
||||
|
||||
tracks.append(ctx.segment);
|
||||
tracks.last().setFile(file->fileName());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ bool GeoJSONParser::multiPoint(const QJsonObject &object,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoJSONParser::lineString(const QJsonObject &object,
|
||||
bool GeoJSONParser::lineString(const QJsonObject &object, const QString &file,
|
||||
const Projection &parent, const QJsonValue &properties,
|
||||
QList<TrackData> &tracks)
|
||||
{
|
||||
@ -367,6 +367,7 @@ bool GeoJSONParser::lineString(const QJsonObject &object,
|
||||
|
||||
setSegmentProperties(segment, -1, properties);
|
||||
TrackData track(segment);
|
||||
track.setFile(file);
|
||||
setTrackProperties(track, properties);
|
||||
tracks.append(track);
|
||||
|
||||
@ -374,7 +375,7 @@ bool GeoJSONParser::lineString(const QJsonObject &object,
|
||||
}
|
||||
|
||||
bool GeoJSONParser::multiLineString(const QJsonObject &object,
|
||||
const Projection &parent, const QJsonValue &properties,
|
||||
const QString &file, const Projection &parent, const QJsonValue &properties,
|
||||
QList<TrackData> &tracks)
|
||||
{
|
||||
if (!object.contains("coordinates")) {
|
||||
@ -421,6 +422,7 @@ bool GeoJSONParser::multiLineString(const QJsonObject &object,
|
||||
}
|
||||
}
|
||||
|
||||
track.setFile(file);
|
||||
setTrackProperties(track, properties);
|
||||
tracks.append(track);
|
||||
|
||||
@ -539,7 +541,7 @@ bool GeoJSONParser::multiPolygon(const QJsonObject &object,
|
||||
}
|
||||
|
||||
bool GeoJSONParser::geometryCollection(const QJsonObject &object,
|
||||
const Projection &parent, const QJsonValue &properties,
|
||||
const QString &file, const Projection &parent, const QJsonValue &properties,
|
||||
QList<TrackData> &tracks, QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||
{
|
||||
if (!object["geometries"].isArray()) {
|
||||
@ -567,13 +569,13 @@ bool GeoJSONParser::geometryCollection(const QJsonObject &object,
|
||||
return false;
|
||||
break;
|
||||
case LineString:
|
||||
if (!lineString(geometry, PROJ(proj, parent), properties,
|
||||
if (!lineString(geometry, file, PROJ(proj, parent), properties,
|
||||
tracks))
|
||||
return false;
|
||||
break;
|
||||
case MultiLineString:
|
||||
if (!multiLineString(geometry, PROJ(proj, parent), properties,
|
||||
tracks))
|
||||
if (!multiLineString(geometry, file, PROJ(proj, parent),
|
||||
properties, tracks))
|
||||
return false;
|
||||
break;
|
||||
case Polygon:
|
||||
@ -586,7 +588,7 @@ bool GeoJSONParser::geometryCollection(const QJsonObject &object,
|
||||
return false;
|
||||
break;
|
||||
case GeometryCollection:
|
||||
if (!geometryCollection(geometry, PROJ(proj, parent),
|
||||
if (!geometryCollection(geometry, file, PROJ(proj, parent),
|
||||
properties, tracks, areas, waypoints))
|
||||
return false;
|
||||
break;
|
||||
@ -600,8 +602,9 @@ bool GeoJSONParser::geometryCollection(const QJsonObject &object,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeoJSONParser::feature(const QJsonObject &object, const Projection &parent,
|
||||
QList<TrackData> &tracks, QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||
bool GeoJSONParser::feature(const QJsonObject &object, const QString &file,
|
||||
const Projection &parent, QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints)
|
||||
{
|
||||
if (object["geometry"].isNull())
|
||||
return true;
|
||||
@ -623,13 +626,14 @@ bool GeoJSONParser::feature(const QJsonObject &object, const Projection &parent,
|
||||
return multiPoint(geometry, PROJ(proj, parent), properties,
|
||||
waypoints);
|
||||
case LineString:
|
||||
return lineString(geometry, PROJ(proj, parent), properties, tracks);
|
||||
case MultiLineString:
|
||||
return multiLineString(geometry, PROJ(proj, parent), properties,
|
||||
return lineString(geometry, file, PROJ(proj, parent), properties,
|
||||
tracks);
|
||||
case MultiLineString:
|
||||
return multiLineString(geometry, file, PROJ(proj, parent),
|
||||
properties, tracks);
|
||||
case GeometryCollection:
|
||||
return geometryCollection(geometry, PROJ(proj, parent), properties,
|
||||
tracks, areas, waypoints);
|
||||
return geometryCollection(geometry, file, PROJ(proj, parent),
|
||||
properties, tracks, areas, waypoints);
|
||||
case Polygon:
|
||||
return polygon(geometry, PROJ(proj, parent), properties, areas);
|
||||
case MultiPolygon:
|
||||
@ -642,8 +646,8 @@ bool GeoJSONParser::feature(const QJsonObject &object, const Projection &parent,
|
||||
}
|
||||
|
||||
bool GeoJSONParser::featureCollection(const QJsonObject &object,
|
||||
const Projection &parent, QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints)
|
||||
const QString &file, const Projection &parent, QList<TrackData> &tracks,
|
||||
QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||
{
|
||||
if (!object["features"].isArray()) {
|
||||
_errorString = "Invalid/missing FeatureCollection features array";
|
||||
@ -656,8 +660,8 @@ bool GeoJSONParser::featureCollection(const QJsonObject &object,
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < features.size(); i++)
|
||||
if (!feature(features.at(i).toObject(), PROJ(proj, parent), tracks,
|
||||
areas, waypoints))
|
||||
if (!feature(features.at(i).toObject(), file, PROJ(proj, parent),
|
||||
tracks, areas, waypoints))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -686,6 +690,7 @@ bool GeoJSONParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
|
||||
QJsonObject object(doc.object());
|
||||
Projection proj(GCS::WGS84());
|
||||
QString fileName(file->fileName());
|
||||
|
||||
switch (type(object)) {
|
||||
case Point:
|
||||
@ -693,16 +698,17 @@ bool GeoJSONParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
case MultiPoint:
|
||||
return multiPoint(object, proj, QJsonValue(), waypoints);
|
||||
case LineString:
|
||||
return lineString(object, proj, QJsonValue(), tracks);
|
||||
return lineString(object, fileName, proj, QJsonValue(), tracks);
|
||||
case MultiLineString:
|
||||
return multiLineString(object, proj, QJsonValue(), tracks);
|
||||
return multiLineString(object, fileName, proj, QJsonValue(), tracks);
|
||||
case GeometryCollection:
|
||||
return geometryCollection(object, proj, QJsonValue(), tracks, areas,
|
||||
waypoints);
|
||||
return geometryCollection(object, fileName, proj, QJsonValue(),
|
||||
tracks, areas, waypoints);
|
||||
case Feature:
|
||||
return feature(object, proj, tracks, areas, waypoints);
|
||||
return feature(object, fileName, proj, tracks, areas, waypoints);
|
||||
case FeatureCollection:
|
||||
return featureCollection(object, proj, tracks, areas, waypoints);
|
||||
return featureCollection(object, fileName, proj, tracks, areas,
|
||||
waypoints);
|
||||
case Polygon:
|
||||
return polygon(object, proj, QJsonValue(), areas);
|
||||
case MultiPolygon:
|
||||
|
@ -37,22 +37,25 @@ private:
|
||||
const QJsonValue &properties, QVector<Waypoint> &waypoints);
|
||||
bool multiPoint(const QJsonObject &object, const Projection &parent,
|
||||
const QJsonValue &properties, QVector<Waypoint> &waypoints);
|
||||
bool lineString(const QJsonObject &coordinates, const Projection &parent,
|
||||
const QJsonValue &properties, QList<TrackData> &tracks);
|
||||
bool multiLineString(const QJsonObject &object, const Projection &proj,
|
||||
const QJsonValue &properties, QList<TrackData> &tracks);
|
||||
bool lineString(const QJsonObject &coordinates, const QString &file,
|
||||
const Projection &parent, const QJsonValue &properties,
|
||||
QList<TrackData> &tracks);
|
||||
bool multiLineString(const QJsonObject &object, const QString &file,
|
||||
const Projection &proj, const QJsonValue &properties,
|
||||
QList<TrackData> &tracks);
|
||||
bool polygon(const QJsonObject &object, const Projection &parent,
|
||||
const QJsonValue &properties, QList<Area> &areas);
|
||||
bool multiPolygon(const QJsonObject &object, const Projection &proj,
|
||||
const QJsonValue &properties, QList<Area> &areas);
|
||||
bool geometryCollection(const QJsonObject &json, const Projection &parent,
|
||||
const QJsonValue &properties, QList<TrackData> &tracks,
|
||||
QList<Area> &areas, QVector<Waypoint> &waypoints);
|
||||
bool feature(const QJsonObject &json, const Projection &parent,
|
||||
QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints);
|
||||
bool featureCollection(const QJsonObject &object, const Projection &parent,
|
||||
bool geometryCollection(const QJsonObject &json, const QString &file,
|
||||
const Projection &parent, const QJsonValue &properties,
|
||||
QList<TrackData> &tracks, QList<Area> &areas, QVector<Waypoint> &waypoints);
|
||||
bool feature(const QJsonObject &json, const QString &file,
|
||||
const Projection &parent, QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints);
|
||||
bool featureCollection(const QJsonObject &object, const QString &file,
|
||||
const Projection &parent, QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints);
|
||||
|
||||
QString _errorString;
|
||||
};
|
||||
|
@ -343,6 +343,10 @@ void GPXParser::track(TrackData &track)
|
||||
|
||||
if (!link10.URL().isEmpty())
|
||||
track.addLink(link10);
|
||||
|
||||
QFile *file = qobject_cast<QFile *>(_reader.device());
|
||||
if (file)
|
||||
track.setFile(file->fileName());
|
||||
}
|
||||
|
||||
void GPXParser::area(Area &area)
|
||||
@ -388,6 +392,9 @@ void GPXParser::gpx(QList<TrackData> &tracks, QList<RouteData> &routes,
|
||||
track(tracks.back());
|
||||
} else if (_reader.name() == QLatin1String("rte")) {
|
||||
routes.append(RouteData());
|
||||
QFile *file = qobject_cast<QFile *>(_reader.device());
|
||||
if (file)
|
||||
routes.back().setFile(file->fileName());
|
||||
routepoints(routes.back(), tracks);
|
||||
} else if (_reader.name() == QLatin1String("wpt")) {
|
||||
waypoints.append(Waypoint(coordinates()));
|
||||
|
@ -237,6 +237,7 @@ bool IGCParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
} else {
|
||||
route = true;
|
||||
routes.append(RouteData());
|
||||
routes.last().setFile(file->fileName());
|
||||
}
|
||||
} else if (line[0] == 'B') {
|
||||
if (ctx.date.isNull()) {
|
||||
@ -248,6 +249,7 @@ bool IGCParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
}
|
||||
if (!track) {
|
||||
tracks.append(SegmentData());
|
||||
tracks.last().setFile(file->fileName());
|
||||
ctx.time = QTime(0, 0);
|
||||
track = true;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ bool ITNParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
_errorLine++;
|
||||
}
|
||||
|
||||
rd.setFile(file->fileName());
|
||||
routes.append(rd);
|
||||
|
||||
return true;
|
||||
|
@ -594,8 +594,8 @@ void KMLParser::photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
|
||||
}
|
||||
}
|
||||
|
||||
void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints)
|
||||
void KMLParser::multiGeometry(const Ctx &ctx, QList<TrackData> &tracks,
|
||||
QList<Area> &areas, QVector<Waypoint> &waypoints)
|
||||
{
|
||||
TrackData *tp = 0;
|
||||
Area *ap = 0;
|
||||
@ -608,6 +608,7 @@ void KMLParser::multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
} else if (_reader.name() == QLatin1String("LineString")) {
|
||||
if (!tp) {
|
||||
tracks.append(TrackData());
|
||||
tracks.last().setFile(ctx.path);
|
||||
tp = &tracks.last();
|
||||
}
|
||||
tp->append(SegmentData());
|
||||
@ -651,21 +652,24 @@ void KMLParser::placemark(const Ctx &ctx, QList<TrackData> &tracks,
|
||||
} else if (_reader.name() == QLatin1String("StyleMap"))
|
||||
styleMap(map);
|
||||
else if (_reader.name() == QLatin1String("MultiGeometry"))
|
||||
multiGeometry(tracks, areas, waypoints);
|
||||
multiGeometry(ctx, tracks, areas, waypoints);
|
||||
else if (_reader.name() == QLatin1String("Point")) {
|
||||
waypoints.append(Waypoint());
|
||||
point(waypoints.last());
|
||||
} else if (_reader.name() == QLatin1String("LineString")
|
||||
|| _reader.name() == QLatin1String("LinearRing")) {
|
||||
tracks.append(TrackData());
|
||||
tracks.last().setFile(ctx.path);
|
||||
tracks.last().append(SegmentData());
|
||||
lineString(tracks.last().last());
|
||||
} else if (_reader.name() == QLatin1String("Track")) {
|
||||
tracks.append(TrackData());
|
||||
tracks.last().setFile(ctx.path);
|
||||
tracks.last().append(SegmentData());
|
||||
track(tracks.last().last());
|
||||
} else if (_reader.name() == QLatin1String("MultiTrack")) {
|
||||
tracks.append(TrackData());
|
||||
tracks.last().setFile(ctx.path);
|
||||
multiTrack(tracks.last());
|
||||
} else if (_reader.name() == QLatin1String("Polygon")) {
|
||||
areas.append(Area());
|
||||
|
@ -40,8 +40,8 @@ private:
|
||||
QVector<Waypoint> &waypoints, PointStyleMap &pointStyles,
|
||||
PolygonStyleMap &polyStyles, LineStyleMap &lineStyles,
|
||||
QMap<QString, QString> &map);
|
||||
void multiGeometry(QList<TrackData> &tracks, QList<Area> &areas,
|
||||
QVector<Waypoint> &waypoints);
|
||||
void multiGeometry(const Ctx &ctx, QList<TrackData> &tracks,
|
||||
QList<Area> &areas, QVector<Waypoint> &waypoints);
|
||||
void photoOverlay(const Ctx &ctx, QVector<Waypoint> &waypoints,
|
||||
PointStyleMap &pointStyles, QMap<QString, QString> &map);
|
||||
void track(SegmentData &segment);
|
||||
|
@ -531,6 +531,7 @@ bool NMEAParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
|
||||
if (segment.size()) {
|
||||
tracks.append(TrackData());
|
||||
tracks.last().setFile(file->fileName());
|
||||
tracks.last().append(segment);
|
||||
}
|
||||
|
||||
|
@ -276,6 +276,7 @@ bool GHPParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
}
|
||||
|
||||
tracks.append(TrackData());
|
||||
tracks.last().setFile(file->fileName());
|
||||
tracks.last().append(segment);
|
||||
|
||||
return true;
|
||||
|
@ -41,6 +41,7 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
|
||||
tracks.append(TrackData());
|
||||
TrackData &track = tracks.last();
|
||||
track.setFile(file->fileName());
|
||||
track.append(SegmentData());
|
||||
SegmentData &segment = track.last();
|
||||
|
||||
@ -159,6 +160,7 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
|
||||
if (list.at(0).trimmed() == "R") {
|
||||
routes.append(RouteData());
|
||||
routes.last().setFile(file->fileName());
|
||||
record = true;
|
||||
|
||||
if (list.size() >= 3) {
|
||||
|
@ -23,6 +23,7 @@ public:
|
||||
const QString &comment() const {return _data.comment();}
|
||||
const QVector<Link> &links() const {return _data.links();}
|
||||
const LineStyle &style() const {return _data.style();}
|
||||
const QString &file() const {return _data.file();}
|
||||
|
||||
bool isValid() const {return _data.size() >= 2;}
|
||||
|
||||
|
@ -15,17 +15,20 @@ public:
|
||||
const QString &comment() const {return _comment;}
|
||||
const QVector<Link> &links() const {return _links;}
|
||||
const LineStyle &style() const {return _style;}
|
||||
const QString &file() const {return _file;}
|
||||
|
||||
void setName(const QString &name) {_name = name;}
|
||||
void setDescription(const QString &desc) {_desc = desc;}
|
||||
void setComment(const QString &comment) {_comment = comment;}
|
||||
void addLink(const Link &link) {_links.append(link);}
|
||||
void setStyle(const LineStyle &style) {_style = style;}
|
||||
void setFile(const QString &file) {_file = file;}
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
QString _desc;
|
||||
QString _comment;
|
||||
QString _file;
|
||||
QVector<Link> _links;
|
||||
LineStyle _style;
|
||||
};
|
||||
|
@ -109,6 +109,7 @@ bool SLFParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
if (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Activity")) {
|
||||
tracks.append(TrackData());
|
||||
tracks.last().setFile(file->fileName());
|
||||
activity(tracks.last());
|
||||
} else
|
||||
_reader.raiseError("Not a SLF file");
|
||||
|
@ -136,6 +136,9 @@ void SMLParser::sml(QList<TrackData> &tracks)
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("DeviceLog")) {
|
||||
tracks.append(TrackData());
|
||||
QFile *file = qobject_cast<QFile*>(_reader.device());
|
||||
if (file)
|
||||
tracks.last().setFile(file->fileName());
|
||||
deviceLog(tracks.last());
|
||||
} else
|
||||
_reader.skipCurrentElement();
|
||||
|
@ -196,7 +196,10 @@ void TCXParser::courses(QList<TrackData> &tracks, QVector<Waypoint> &waypoints)
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Course")) {
|
||||
tracks.append(TrackData());
|
||||
course(waypoints, tracks.back());
|
||||
QFile *file = qobject_cast<QFile*>(_reader.device());
|
||||
if (file)
|
||||
tracks.last().setFile(file->fileName());
|
||||
course(waypoints, tracks.last());
|
||||
} else
|
||||
_reader.skipCurrentElement();
|
||||
}
|
||||
@ -207,6 +210,9 @@ void TCXParser::sport(QList<TrackData> &tracks)
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Activity")) {
|
||||
tracks.append(TrackData());
|
||||
QFile *file = qobject_cast<QFile*>(_reader.device());
|
||||
if (file)
|
||||
tracks.last().setFile(file->fileName());
|
||||
activity(tracks.last());
|
||||
} else
|
||||
_reader.skipCurrentElement();
|
||||
@ -229,6 +235,9 @@ void TCXParser::activities(QList<TrackData> &tracks)
|
||||
while (_reader.readNextStartElement()) {
|
||||
if (_reader.name() == QLatin1String("Activity")) {
|
||||
tracks.append(TrackData());
|
||||
QFile *file = qobject_cast<QFile*>(_reader.device());
|
||||
if (file)
|
||||
tracks.last().setFile(file->fileName());
|
||||
activity(tracks.last());
|
||||
} else if (_reader.name() == QLatin1String("MultiSportSession"))
|
||||
multiSportSession(tracks);
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
const QString &comment() const {return _data.comment();}
|
||||
const QVector<Link> &links() const {return _data.links();}
|
||||
const LineStyle &style() const {return _data.style();}
|
||||
const QString &file() const {return _data.file();}
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
|
@ -25,17 +25,20 @@ public:
|
||||
const QString &comment() const {return _comment;}
|
||||
const QVector<Link> &links() const {return _links;}
|
||||
const LineStyle &style() const {return _style;}
|
||||
const QString &file() const {return _file;}
|
||||
|
||||
void setName(const QString &name) {_name = name;}
|
||||
void setDescription(const QString &desc) {_desc = desc;}
|
||||
void setComment(const QString &comment) {_comment = comment;}
|
||||
void addLink(const Link &link) {_links.append(link);}
|
||||
void setStyle(const LineStyle &style) {_style = style;}
|
||||
void setFile(const QString &path) {_file = path;}
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
QString _desc;
|
||||
QString _comment;
|
||||
QString _file;
|
||||
QVector<Link> _links;
|
||||
LineStyle _style;
|
||||
};
|
||||
|
@ -152,6 +152,7 @@ bool TwoNavParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
|
||||
if (!track) {
|
||||
tracks.append(SegmentData());
|
||||
tracks.last().setFile(file->fileName());
|
||||
track = true;
|
||||
}
|
||||
|
||||
@ -205,6 +206,7 @@ bool TwoNavParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
case 'R':
|
||||
{QStringList list(codec.toString(line).split(','));
|
||||
routes.append(RouteData());
|
||||
routes.last().setFile(file->fileName());
|
||||
if (list.size() > 1)
|
||||
routes.last().setName(list.at(1));
|
||||
route = true;}
|
||||
|
Loading…
Reference in New Issue
Block a user