1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-02-26 04:00:49 +01:00

Preserve directory structure when loading the POIs

+ POI files handling optimization
This commit is contained in:
Martin Tůma 2021-03-21 20:23:20 +01:00
parent ce0d50e4aa
commit 2d329e65ee
8 changed files with 225 additions and 206 deletions

View File

@ -24,6 +24,7 @@ HEADERS += src/common/config.h \
src/GUI/marginswidget.h \ src/GUI/marginswidget.h \
src/GUI/markerinfoitem.h \ src/GUI/markerinfoitem.h \
src/GUI/planeitem.h \ src/GUI/planeitem.h \
src/GUI/poiaction.h \
src/GUI/popup.h \ src/GUI/popup.h \
src/common/garmin.h \ src/common/garmin.h \
src/common/coordinates.h \ src/common/coordinates.h \

View File

@ -10,7 +10,6 @@
#include <QPaintEngine> #include <QPaintEngine>
#include <QPaintDevice> #include <QPaintDevice>
#include <QKeyEvent> #include <QKeyEvent>
#include <QSignalMapper>
#include <QMenu> #include <QMenu>
#include <QToolBar> #include <QToolBar>
#include <QTabWidget> #include <QTabWidget>
@ -50,6 +49,7 @@
#include "pathitem.h" #include "pathitem.h"
#include "mapitem.h" #include "mapitem.h"
#include "mapaction.h" #include "mapaction.h"
#include "poiaction.h"
#include "gui.h" #include "gui.h"
@ -58,16 +58,16 @@
GUI::GUI() GUI::GUI()
{ {
TreeNode<MapAction*> mapActions; TreeNode<MapAction*> mapActions;
TreeNode<POIAction*> poiActions;
loadPOIs(); _poi = new POI(this);
createMapView(); createMapView();
createGraphTabs(); createGraphTabs();
createStatusBar(); createStatusBar();
createActions(mapActions); createActions(mapActions, poiActions);
createMenus(mapActions); createMenus(mapActions, poiActions);
createToolBars(); createToolBars();
createBrowser(); createBrowser();
_splitter = new QSplitter(); _splitter = new QSplitter();
@ -105,21 +105,27 @@ GUI::GUI()
updateStatusBarInfo(); updateStatusBarInfo();
} }
void GUI::loadPOIs()
{
_poi = new POI(this);
QString poiDir(ProgramPaths::poiDir());
if (!poiDir.isNull())
_poi->loadDir(poiDir);
}
void GUI::createBrowser() void GUI::createBrowser()
{ {
_browser = new FileBrowser(this); _browser = new FileBrowser(this);
_browser->setFilter(Data::filter()); _browser->setFilter(Data::filter());
} }
TreeNode<MapAction*> GUI::createMapActions()
{
_mapsActionGroup = new QActionGroup(this);
_mapsActionGroup->setExclusive(true);
connect(_mapsActionGroup, SIGNAL(triggered(QAction*)), this,
SLOT(mapChanged(QAction*)));
QString mapDir(ProgramPaths::mapDir());
if (mapDir.isNull())
return TreeNode<MapAction*>();
TreeNode<Map*> maps(MapList::loadMaps(mapDir));
return createMapActionsNode(maps);
}
TreeNode<MapAction*> GUI::createMapActionsNode(const TreeNode<Map*> &node) TreeNode<MapAction*> GUI::createMapActionsNode(const TreeNode<Map*> &node)
{ {
TreeNode<MapAction*> tree(node.name()); TreeNode<MapAction*> tree(node.name());
@ -130,7 +136,7 @@ TreeNode<MapAction*> GUI::createMapActionsNode(const TreeNode<Map*> &node)
for (int i = 0; i < node.items().size(); i++) { for (int i = 0; i < node.items().size(); i++) {
Map *map = node.items().at(i); Map *map = node.items().at(i);
if (map->isValid()) { if (map->isValid()) {
MapAction *a = createMapAction(map); MapAction *a = new MapAction(map, _mapsActionGroup);
connect(a, SIGNAL(loaded()), this, SLOT(mapInitialized())); connect(a, SIGNAL(loaded()), this, SLOT(mapInitialized()));
tree.addItem(a); tree.addItem(a);
} else { } else {
@ -143,29 +149,6 @@ TreeNode<MapAction*> GUI::createMapActionsNode(const TreeNode<Map*> &node)
return tree; return tree;
} }
TreeNode<MapAction*> GUI::createMapActions()
{
_mapsActionGroup = new QActionGroup(this);
_mapsActionGroup->setExclusive(true);
QString mapDir(ProgramPaths::mapDir());
if (mapDir.isNull())
return TreeNode<MapAction*>();
TreeNode<Map*> maps(MapList::loadMaps(mapDir));
return createMapActionsNode(maps);
}
MapAction *GUI::createMapAction(Map *map)
{
MapAction *a = new MapAction(map, _mapsActionGroup);
a->setMenuRole(QAction::NoRole);
a->setCheckable(true);
connect(a, SIGNAL(triggered()), this, SLOT(mapChanged()));
return a;
}
void GUI::mapInitialized() void GUI::mapInitialized()
{ {
MapAction *action = static_cast<MapAction*>(QObject::sender()); MapAction *action = static_cast<MapAction*>(QObject::sender());
@ -182,35 +165,35 @@ void GUI::mapInitialized()
} }
} }
void GUI::createPOIFilesActions() TreeNode<POIAction *> GUI::createPOIActions()
{ {
_poiFilesSignalMapper = new QSignalMapper(this); _poisActionGroup = new QActionGroup(this);
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) _poisActionGroup->setExclusive(false);
connect(_poiFilesSignalMapper, SIGNAL(mapped(int)), this, connect(_poisActionGroup, SIGNAL(triggered(QAction*)), this,
SLOT(poiFileChecked(int))); SLOT(poiFileChecked(QAction*)));
#else // QT 5.15
connect(_poiFilesSignalMapper, SIGNAL(mappedInt(int)), this,
SLOT(poiFileChecked(int)));
#endif // QT 5.15
for (int i = 0; i < _poi->files().count(); i++) TreeNode<QString> poiFiles;
createPOIFileAction(_poi->files().at(i)); QString poiDir(ProgramPaths::poiDir());
if (!poiDir.isNull())
poiFiles = _poi->loadDir(poiDir);
return createPOIActionsNode(poiFiles);
} }
QAction *GUI::createPOIFileAction(const QString &fileName) TreeNode<POIAction *> GUI::createPOIActionsNode(const TreeNode<QString> &node)
{ {
QAction *a = new QAction(QFileInfo(fileName).fileName(), this); TreeNode<POIAction*> tree(node.name());
a->setMenuRole(QAction::NoRole);
a->setCheckable(true);
_poiFilesActions.append(a); for (int i = 0; i < node.childs().size(); i++)
_poiFilesSignalMapper->setMapping(a, _poiFilesActions.size() - 1); tree.addChild(createPOIActionsNode(node.childs().at(i)));
connect(a, SIGNAL(triggered()), _poiFilesSignalMapper, SLOT(map())); for (int i = 0; i < node.items().size(); i++)
tree.addItem(new POIAction(node.items().at(i), _poisActionGroup));
return a; return tree;
} }
void GUI::createActions(TreeNode<MapAction*> &mapActions) void GUI::createActions(TreeNode<MapAction*> &mapActions,
TreeNode<POIAction*> &poiActions)
{ {
QActionGroup *ag; QActionGroup *ag;
@ -291,10 +274,6 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions)
this); this);
_openPOIAction->setMenuRole(QAction::NoRole); _openPOIAction->setMenuRole(QAction::NoRole);
connect(_openPOIAction, SIGNAL(triggered()), this, SLOT(openPOIFile())); connect(_openPOIAction, SIGNAL(triggered()), this, SLOT(openPOIFile()));
_closePOIAction = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close POI files"),
this);
_closePOIAction->setMenuRole(QAction::NoRole);
connect(_closePOIAction, SIGNAL(triggered()), this, SLOT(closePOIFiles()));
_overlapPOIAction = new QAction(tr("Overlap POIs"), this); _overlapPOIAction = new QAction(tr("Overlap POIs"), this);
_overlapPOIAction->setMenuRole(QAction::NoRole); _overlapPOIAction->setMenuRole(QAction::NoRole);
_overlapPOIAction->setCheckable(true); _overlapPOIAction->setCheckable(true);
@ -312,7 +291,7 @@ void GUI::createActions(TreeNode<MapAction*> &mapActions)
connect(_showPOIAction, SIGNAL(triggered(bool)), _mapView, connect(_showPOIAction, SIGNAL(triggered(bool)), _mapView,
SLOT(showPOI(bool))); SLOT(showPOI(bool)));
addAction(_showPOIAction); addAction(_showPOIAction);
createPOIFilesActions(); poiActions = createPOIActions();
// Map actions // Map actions
mapActions = createMapActions(); mapActions = createMapActions();
@ -550,7 +529,20 @@ void GUI::createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu)
menu->addAction(node.items().at(i)); menu->addAction(node.items().at(i));
} }
void GUI::createMenus(const TreeNode<MapAction*> &mapActions) void GUI::createPOINodeMenu(const TreeNode<POIAction*> &node, QMenu *menu)
{
for (int i = 0; i < node.childs().size(); i++) {
QMenu *cm = new QMenu(node.childs().at(i).name(), menu);
menu->addMenu(cm);
createPOINodeMenu(node.childs().at(i), cm);
}
for (int i = 0; i < node.items().size(); i++)
menu->addAction(node.items().at(i));
}
void GUI::createMenus(const TreeNode<MapAction*> &mapActions,
const TreeNode<POIAction*> &poiActions)
{ {
QMenu *fileMenu = menuBar()->addMenu(tr("&File")); QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(_openFileAction); fileMenu->addAction(_openFileAction);
@ -588,17 +580,15 @@ void GUI::createMenus(const TreeNode<MapAction*> &mapActions)
graphMenu->addSeparator(); graphMenu->addSeparator();
graphMenu->addAction(_showGraphsAction); graphMenu->addAction(_showGraphsAction);
QMenu *poiMenu = menuBar()->addMenu(tr("&POI")); _poiMenu = menuBar()->addMenu(tr("&POI"));
_poiFilesMenu = poiMenu->addMenu(tr("POI files")); createPOINodeMenu(poiActions, _poiMenu);
_poiFilesMenu->addActions(_poiFilesActions); _poisEnd = _poiMenu->addSeparator();
poiMenu->addSeparator(); _poiMenu->addAction(_openPOIAction);
poiMenu->addAction(_openPOIAction); _poiMenu->addSeparator();
poiMenu->addAction(_closePOIAction); _poiMenu->addAction(_showPOILabelsAction);
poiMenu->addSeparator(); _poiMenu->addAction(_overlapPOIAction);
poiMenu->addAction(_showPOILabelsAction); _poiMenu->addSeparator();
poiMenu->addAction(_overlapPOIAction); _poiMenu->addAction(_showPOIAction);
poiMenu->addSeparator();
poiMenu->addAction(_showPOIAction);
QMenu *dataMenu = menuBar()->addMenu(tr("&Data")); QMenu *dataMenu = menuBar()->addMenu(tr("&Data"));
dataMenu->addAction(_showWaypointLabelsAction); dataMenu->addAction(_showWaypointLabelsAction);
@ -937,15 +927,15 @@ void GUI::openPOIFile()
bool GUI::openPOIFile(const QString &fileName) bool GUI::openPOIFile(const QString &fileName)
{ {
if (_poi->files().contains(fileName)) if (_poi->isLoaded(fileName))
return true; return true;
if (_poi->loadFile(fileName)) { if (_poi->loadFile(fileName)) {
_mapView->showPOI(true); _mapView->showPOI(true);
_showPOIAction->setChecked(true); _showPOIAction->setChecked(true);
QAction *action = createPOIFileAction(fileName); QAction *action = new POIAction(fileName, _poisActionGroup);
action->setChecked(true); action->setChecked(true);
_poiFilesMenu->addAction(action); _poiMenu->insertAction(_poisEnd, action);
return true; return true;
} else { } else {
@ -959,16 +949,6 @@ bool GUI::openPOIFile(const QString &fileName)
} }
} }
void GUI::closePOIFiles()
{
_poiFilesMenu->clear();
qDeleteAll(_poiFilesActions);
_poiFilesActions.clear();
_poi->clear();
}
void GUI::openOptions() void GUI::openOptions()
{ {
#define SET_VIEW_OPTION(option, action) \ #define SET_VIEW_OPTION(option, action) \
@ -1550,7 +1530,7 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
delete map; delete map;
} else { } else {
valid = true; valid = true;
a = createMapAction(map); a = new MapAction(map, _mapsActionGroup);
_mapMenu->insertAction(_mapsEnd, a); _mapMenu->insertAction(_mapsEnd, a);
if (map->isReady()) { if (map->isReady()) {
@ -1634,7 +1614,7 @@ void GUI::loadMapDirNode(const TreeNode<Map *> &node, QList<MapAction*> &actions
+ "\n\n" + map->path() + "\n\n" + map->errorString()); + "\n\n" + map->path() + "\n\n" + map->errorString());
delete map; delete map;
} else { } else {
a = createMapAction(map); a = new MapAction(map, _mapsActionGroup);
menu->addAction(a); menu->addAction(a);
if (map->isReady()) { if (map->isReady()) {
@ -1726,9 +1706,9 @@ void GUI::updateWindowTitle()
setWindowTitle(APP_NAME); setWindowTitle(APP_NAME);
} }
void GUI::mapChanged() void GUI::mapChanged(QAction *action)
{ {
_map = _mapsActionGroup->checkedAction()->data().value<Map*>(); _map = action->data().value<Map*>();
_mapView->setMap(_map); _mapView->setMap(_map);
} }
@ -1764,10 +1744,9 @@ void GUI::prevMap()
} }
} }
void GUI::poiFileChecked(int index) void GUI::poiFileChecked(QAction *action)
{ {
_poi->enableFile(_poi->files().at(index), _poi->enableFile(action->data().value<QString>(), action->isChecked());
_poiFilesActions.at(index)->isChecked());
} }
void GUI::graphChanged(int index) void GUI::graphChanged(int index)
@ -2069,12 +2048,14 @@ void GUI::writeSettings()
settings.setValue(OVERLAP_POI_SETTING, _overlapPOIAction->isChecked()); settings.setValue(OVERLAP_POI_SETTING, _overlapPOIAction->isChecked());
int j = 0; int j = 0;
for (int i = 0; i < _poiFilesActions.count(); i++) { QList<QAction*> poiActions(_poisActionGroup->actions());
if (!_poiFilesActions.at(i)->isChecked()) { for (int i = 0; i < poiActions.count(); i++) {
POIAction *a = static_cast<POIAction*>(poiActions.at(i));
if (!a->isChecked()) {
if (j == 0) if (j == 0)
settings.beginWriteArray(DISABLED_POI_FILE_SETTINGS_PREFIX); settings.beginWriteArray(DISABLED_POI_FILE_SETTINGS_PREFIX);
settings.setArrayIndex(j++); settings.setArrayIndex(j++);
settings.setValue(DISABLED_POI_FILE_SETTING, _poi->files().at(i)); settings.setValue(DISABLED_POI_FILE_SETTING, a->data().toString());
} }
} }
if (j != 0) if (j != 0)
@ -2351,16 +2332,17 @@ void GUI::readSettings()
_showPOIAction->setChecked(true); _showPOIAction->setChecked(true);
else else
_mapView->showPOI(false); _mapView->showPOI(false);
for (int i = 0; i < _poiFilesActions.count(); i++) QList<QAction*> poiActions(_poisActionGroup->actions());
_poiFilesActions.at(i)->setChecked(true); for (int i = 0; i < poiActions.count(); i++)
poiActions.at(i)->setChecked(true);
int size = settings.beginReadArray(DISABLED_POI_FILE_SETTINGS_PREFIX); int size = settings.beginReadArray(DISABLED_POI_FILE_SETTINGS_PREFIX);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
settings.setArrayIndex(i); settings.setArrayIndex(i);
int index = _poi->files().indexOf(settings.value( QString file(settings.value(DISABLED_POI_FILE_SETTING).toString());
DISABLED_POI_FILE_SETTING).toString()); if (_poi->enableFile(file, false)) {
if (index >= 0) { for (int j = 0; j < poiActions.size(); j++)
_poi->enableFile(_poi->files().at(index), false); if (poiActions.at(j)->data().toString() == file)
_poiFilesActions.at(index)->setChecked(false); poiActions.at(j)->setChecked(false);
} }
} }
settings.endArray(); settings.endArray();

View File

@ -22,7 +22,6 @@ class QActionGroup;
class QAction; class QAction;
class QLabel; class QLabel;
class QSplitter; class QSplitter;
class QSignalMapper;
class QPrinter; class QPrinter;
class FileBrowser; class FileBrowser;
class GraphTab; class GraphTab;
@ -31,6 +30,7 @@ class Map;
class POI; class POI;
class QScreen; class QScreen;
class MapAction; class MapAction;
class POIAction;
class Data; class Data;
class GUI : public QMainWindow class GUI : public QMainWindow
@ -57,7 +57,6 @@ private slots:
void reloadFiles(); void reloadFiles();
void statistics(); void statistics();
void openPOIFile(); void openPOIFile();
void closePOIFiles();
void showGraphs(bool show); void showGraphs(bool show);
void showGraphGrids(bool show); void showGraphGrids(bool show);
void showGraphSliderInfo(bool show); void showGraphSliderInfo(bool show);
@ -73,9 +72,9 @@ private slots:
void openOptions(); void openOptions();
void clearMapCache(); void clearMapCache();
void mapChanged(); void mapChanged(QAction *action);
void graphChanged(int); void graphChanged(int);
void poiFileChecked(int); void poiFileChecked(QAction *action);
void next(); void next();
void prev(); void prev();
@ -103,7 +102,6 @@ private slots:
private: private:
typedef QPair<QDateTime, QDateTime> DateTimeRange; typedef QPair<QDateTime, QDateTime> DateTimeRange;
void loadPOIs();
void closeFiles(); void closeFiles();
void plot(QPrinter *printer); void plot(QPrinter *printer);
void plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio, void plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio,
@ -111,14 +109,16 @@ private:
void plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio); void plotGraphsPage(QPainter *painter, const QRectF &rect, qreal ratio);
qreal graphPlotHeight(const QRectF &rect, qreal ratio); qreal graphPlotHeight(const QRectF &rect, qreal ratio);
QAction *createPOIFileAction(const QString &fileName); TreeNode<POIAction*> createPOIActions();
MapAction *createMapAction(Map *map); TreeNode<POIAction*> createPOIActionsNode(const TreeNode<QString> &node);
void createPOIFilesActions();
TreeNode<MapAction*> createMapActionsNode(const TreeNode<Map*> &node);
TreeNode<MapAction*> createMapActions(); TreeNode<MapAction*> createMapActions();
void createActions(TreeNode<MapAction *> &mapActions); TreeNode<MapAction*> createMapActionsNode(const TreeNode<Map*> &node);
void createActions(TreeNode<MapAction*> &mapActions,
TreeNode<POIAction*> &poiActions);
void createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu); void createMapNodeMenu(const TreeNode<MapAction*> &node, QMenu *menu);
void createMenus(const TreeNode<MapAction *> &mapActions); void createPOINodeMenu(const TreeNode<POIAction*> &node, QMenu *menu);
void createMenus(const TreeNode<MapAction*> &mapActions,
const TreeNode<POIAction*> &poiActions);
void createToolBars(); void createToolBars();
void createStatusBar(); void createStatusBar();
void createMapView(); void createMapView();
@ -159,12 +159,13 @@ private:
QToolBar *_fileToolBar; QToolBar *_fileToolBar;
QToolBar *_showToolBar; QToolBar *_showToolBar;
QToolBar *_navigationToolBar; QToolBar *_navigationToolBar;
QMenu *_poiFilesMenu; QMenu *_poiMenu;
QMenu *_mapMenu; QMenu *_mapMenu;
QActionGroup *_fileActionGroup; QActionGroup *_fileActionGroup;
QActionGroup *_navigationActionGroup; QActionGroup *_navigationActionGroup;
QActionGroup *_mapsActionGroup; QActionGroup *_mapsActionGroup;
QActionGroup *_poisActionGroup;
QAction *_exitAction; QAction *_exitAction;
QAction *_keysAction; QAction *_keysAction;
QAction *_pathsAction; QAction *_pathsAction;
@ -178,7 +179,6 @@ private:
QAction *_reloadFileAction; QAction *_reloadFileAction;
QAction *_statisticsAction; QAction *_statisticsAction;
QAction *_openPOIAction; QAction *_openPOIAction;
QAction *_closePOIAction;
QAction *_showPOIAction; QAction *_showPOIAction;
QAction *_overlapPOIAction; QAction *_overlapPOIAction;
QAction *_showPOILabelsAction; QAction *_showPOILabelsAction;
@ -221,9 +221,7 @@ private:
QAction *_showCoordinatesAction; QAction *_showCoordinatesAction;
QAction *_openOptionsAction; QAction *_openOptionsAction;
QAction *_mapsEnd; QAction *_mapsEnd;
QAction *_poisEnd;
QList<QAction*> _poiFilesActions;
QSignalMapper *_poiFilesSignalMapper;
QLabel *_fileNameLabel; QLabel *_fileNameLabel;
QLabel *_distanceLabel; QLabel *_distanceLabel;

View File

@ -12,8 +12,12 @@ public:
MapAction(Map *map, QObject *parent = 0) : QAction(map->name(), parent) MapAction(Map *map, QObject *parent = 0) : QAction(map->name(), parent)
{ {
map->setParent(this); map->setParent(this);
setData(QVariant::fromValue(map)); setData(QVariant::fromValue(map));
setEnabled(map->isReady()); setEnabled(map->isReady());
setMenuRole(QAction::NoRole);
setCheckable(true);
connect(map, SIGNAL(mapLoaded()), this, SLOT(mapLoaded())); connect(map, SIGNAL(mapLoaded()), this, SLOT(mapLoaded()));
} }

21
src/GUI/poiaction.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef POIACTION_H
#define POIACTION_H
#include <QAction>
#include "common/util.h"
class POIAction : public QAction
{
Q_OBJECT
public:
POIAction(const QString &path, QObject *parent = 0)
: QAction(Util::file2name(path), parent)
{
setMenuRole(QAction::NoRole);
setCheckable(true);
setData(path);
}
};
#endif // POIACTION_H

View File

@ -12,17 +12,25 @@ public:
TreeNode(const QString &name) : _name(name) {} TreeNode(const QString &name) : _name(name) {}
const QString &name() const {return _name;} const QString &name() const {return _name;}
const QList<TreeNode> &childs() const {return _childs;} const QList<TreeNode<T> > &childs() const {return _childs;}
const QList<T> &items() const {return _items;} const QList<T> &items() const {return _items;}
void addItem(T node) {_items.append(node);} void addItem(T node) {_items.append(node);}
void addChild(const TreeNode<T> &child) {_childs.append(child);} void addChild(const TreeNode<T> &child) {_childs.append(child);}
bool isEmpty() const {return _childs.isEmpty() && _items.isEmpty();} bool isEmpty() const {return _childs.isEmpty() && _items.isEmpty();}
void clear() {clear(*this);}
private: private:
void clear(TreeNode<T> &node)
{
for (int i = 0; i < node._childs.size(); i++)
clear(node._childs[i]);
node._items.clear();
}
QString _name; QString _name;
QList<TreeNode> _childs; QList<TreeNode<T> > _childs;
QList<T> _items; QList<T> _items;
}; };

View File

@ -10,19 +10,35 @@
#include "poi.h" #include "poi.h"
POI::File::File(int start, int end, const QVector<Waypoint> &data)
: _enabled(true)
{
qreal c[2];
for (int i = start; i <= end; i++) {
const Coordinates &p = data.at(i).coordinates();
c[0] = p.lon();
c[1] = p.lat();
_tree.Insert(c, c, i);
}
}
POI::POI(QObject *parent) : QObject(parent) POI::POI(QObject *parent) : QObject(parent)
{ {
_errorLine = 0; _errorLine = 0;
_radius = 1000; _radius = 1000;
} }
POI::~POI()
{
qDeleteAll(_files);
}
bool POI::loadFile(const QString &path) bool POI::loadFile(const QString &path)
{ {
Data data(path); Data data(path);
FileIndex index;
index.enabled = true;
index.start = _data.size();
if (!data.isValid()) { if (!data.isValid()) {
_errorString = data.errorString(); _errorString = data.errorString();
@ -30,44 +46,43 @@ bool POI::loadFile(const QString &path)
return false; return false;
} }
for (int i = 0; i < data.waypoints().size(); i++) int start = _data.size();
_data.append(data.waypoints().at(i)); _data.append(data.waypoints());
index.end = _data.size() - 1;
for (int i = index.start; i <= index.end; i++) { _files.insert(path, new File(start, _data.size() - 1, _data));
const Coordinates &p = _data.at(i).coordinates();
qreal c[2];
c[0] = p.lon();
c[1] = p.lat();
_tree.Insert(c, c, i);
}
_files.append(path);
_indexes.append(index);
emit pointsChanged(); emit pointsChanged();
return true; return true;
} }
void POI::loadDir(const QString &path) TreeNode<QString> POI::loadDir(const QString &path)
{ {
QDir md(path); QDir md(path);
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
md.setSorting(QDir::DirsFirst);
QFileInfoList fl = md.entryInfoList(); QFileInfoList fl = md.entryInfoList();
TreeNode<QString> tree(md.dirName());
for (int i = 0; i < fl.size(); i++) { for (int i = 0; i < fl.size(); i++) {
const QFileInfo &fi = fl.at(i); const QFileInfo &fi = fl.at(i);
if (fi.isDir()) if (fi.isDir()) {
loadDir(fi.absoluteFilePath()); TreeNode<QString> child(loadDir(fi.absoluteFilePath()));
if (!child.isEmpty())
tree.addChild(child);
} else {
if (loadFile(fi.absoluteFilePath()))
tree.addItem(fi.absoluteFilePath());
else else
if (!loadFile(fi.absoluteFilePath()))
qWarning("%s: %s", qPrintable(fi.absoluteFilePath()), qWarning("%s: %s", qPrintable(fi.absoluteFilePath()),
qPrintable(_errorString)); qPrintable(_errorString));
} }
} }
return tree;
}
static bool cb(size_t data, void* context) static bool cb(size_t data, void* context)
{ {
QSet<int> *set = (QSet<int>*) context; QSet<int> *set = (QSet<int>*) context;
@ -80,24 +95,30 @@ void POI::search(const RectC &rect, QSet<int> &set) const
{ {
qreal min[2], max[2]; qreal min[2], max[2];
for (ConstIterator it = _files.constBegin(); it != _files.constEnd(); ++it) {
const File *file = *it;
if (file->isEnabled()) {
if (rect.left() > rect.right()) { if (rect.left() > rect.right()) {
min[0] = rect.topLeft().lon(); min[0] = rect.topLeft().lon();
min[1] = rect.bottomRight().lat(); min[1] = rect.bottomRight().lat();
max[0] = 180.0; max[0] = 180.0;
max[1] = rect.topLeft().lat(); max[1] = rect.topLeft().lat();
_tree.Search(min, max, cb, &set); file->tree().Search(min, max, cb, &set);
min[0] = -180.0; min[0] = -180.0;
min[1] = rect.bottomRight().lat(); min[1] = rect.bottomRight().lat();
max[0] = rect.bottomRight().lon(); max[0] = rect.bottomRight().lon();
max[1] = rect.topLeft().lat(); max[1] = rect.topLeft().lat();
_tree.Search(min, max, cb, &set); file->tree().Search(min, max, cb, &set);
} else { } else {
min[0] = rect.topLeft().lon(); min[0] = rect.topLeft().lon();
min[1] = rect.bottomRight().lat(); min[1] = rect.bottomRight().lat();
max[0] = rect.bottomRight().lon(); max[0] = rect.bottomRight().lon();
max[1] = rect.topLeft().lat(); max[1] = rect.topLeft().lat();
_tree.Search(min, max, cb, &set); file->tree().Search(min, max, cb, &set);
}
}
} }
} }
@ -170,40 +191,17 @@ QList<Waypoint> POI::points(const RectC &rect) const
return ret; return ret;
} }
void POI::enableFile(const QString &fileName, bool enable) bool POI::enableFile(const QString &fileName, bool enable)
{ {
int i; Iterator it = _files.find(fileName);
if (it == _files.end())
return false;
i = _files.indexOf(fileName); (*it)->enable(enable);
Q_ASSERT(i >= 0);
_indexes[i].enabled = enable;
_tree.RemoveAll();
for (int i = 0; i < _indexes.count(); i++) {
FileIndex idx = _indexes.at(i);
if (!idx.enabled)
continue;
for (int j = idx.start; j <= idx.end; j++) {
const Coordinates &p = _data.at(j).coordinates();
qreal c[2];
c[0] = p.lon();
c[1] = p.lat();
_tree.Insert(c, c, j);
}
}
emit pointsChanged(); emit pointsChanged();
}
void POI::clear() return true;
{
_tree.RemoveAll();
_data.clear();
_files.clear();
_indexes.clear();
emit pointsChanged();
} }
void POI::setRadius(unsigned radius) void POI::setRadius(unsigned radius)

View File

@ -6,6 +6,7 @@
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include "common/rtree.h" #include "common/rtree.h"
#include "common/treenode.h"
#include "waypoint.h" #include "waypoint.h"
class Path; class Path;
@ -17,9 +18,10 @@ class POI : public QObject
public: public:
POI(QObject *parent = 0); POI(QObject *parent = 0);
~POI();
bool loadFile(const QString &path); bool loadFile(const QString &path);
void loadDir(const QString &path); TreeNode<QString> loadDir(const QString &path);
const QString &errorString() const {return _errorString;} const QString &errorString() const {return _errorString;}
int errorLine() const {return _errorLine;} int errorLine() const {return _errorLine;}
@ -30,28 +32,33 @@ public:
QList<Waypoint> points(const Waypoint &point) const; QList<Waypoint> points(const Waypoint &point) const;
QList<Waypoint> points(const RectC &rect) const; QList<Waypoint> points(const RectC &rect) const;
const QStringList &files() const {return _files;} bool isLoaded(const QString &path) const {return _files.contains(path);}
void enableFile(const QString &fileName, bool enable); bool enableFile(const QString &fileName, bool enable);
void clear();
signals: signals:
void pointsChanged(); void pointsChanged();
private: private:
typedef RTree<size_t, qreal, 2> POITree; typedef RTree<size_t, qreal, 2> POITree;
struct FileIndex { class File {
int start; public:
int end; File(int start, int end, const QVector<Waypoint> &data);
bool enabled;
}; const POITree &tree() const {return _tree;}
bool isEnabled() const {return _enabled;}
void enable(bool enable) {_enabled = enable;}
private:
bool _enabled;
POITree _tree;
};
typedef QHash<QString, File*>::const_iterator ConstIterator;
typedef QHash<QString, File*>::iterator Iterator;
bool loadFile(const QString &path, bool dir);
void search(const RectC &rect, QSet<int> &set) const; void search(const RectC &rect, QSet<int> &set) const;
POITree _tree;
QVector<Waypoint> _data; QVector<Waypoint> _data;
QStringList _files; QHash<QString, File*> _files;
QList<FileIndex> _indexes;
unsigned _radius; unsigned _radius;