const int MAP_PIXELS_Y = OSM_MAP_MAX_PIXEL_Y + 1;
- double longitude = coordinate.x() / OMS_MAP_PIXELS_X * 360.0 - 180;
+ double longitude = coordinate.x() / OSM_MAP_PIXELS_X * 360.0 - 180;
double n = M_PI - 2.0 * M_PI * coordinate.y() / MAP_PIXELS_Y;
double latitude = 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n)));
#include <cmath>
#include <QDebug>
+#include <QLineF>
#include <QPointF>
#include <QVariant>
convertFrom(coordinate);
}
+qreal SceneCoordinate::azimuthTo(const SceneCoordinate &to) const
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ // construct a line from this coordinate to target coordinate
+ QLineF line = QLineF(this->toPointF(), to.toPointF());
+
+ // get the angle from the line. Because QLineF::angle() returns positive value for a
+ // counter-clockwise direction, and we want the positive value to be in clockwise direction,
+ // the value is negated
+ qreal angle = -line.angle();
+
+ // QLineF::angle() returns value which has zero at the 3 o'clock position, and we want to have
+ // the zero pointing to the north, so we have to add 90 degrees
+ angle += 90;
+
+ // QLineF::angle() returns values from -180 to 180, an we want only positive values from 0 to
+ // 360 degrees, so full 360 degrees is added if the result would otherwise be negative
+ if (angle < 0)
+ angle += 360;
+
+ Q_ASSERT_X(angle >= 0.0 && angle <= 360, "return value", "value is out of range");
+
+ return angle;
+}
+
void SceneCoordinate::convertFrom(const GeoCoordinate &coordinate)
{
qDebug() << __PRETTY_FUNCTION__;
******************************************************************************/
public:
/**
+ * @brief Returns the azimuth from this coordinate to other coordinate
+ *
+ * Zero is pointing to north. Returned value is from 0 to 360.
+ *
+ * @param to Target coordinate
+ * @returns Azimuth in degrees
+ */
+ qreal azimuthTo(const SceneCoordinate &to) const;
+
+ /**
* @brief Check if coordinate is (0.0, 0.0)
*
* @returns True if both X and Y are 0.0, otherwise false
void SituareEngine::draggingModeTriggered()
{
+ qDebug() << __PRETTY_FUNCTION__;
+
if (m_mce)
m_mce->vibrationFeedback();
}
connect(m_mapEngine, SIGNAL(newMapResolution(qreal)),
m_ui, SIGNAL(newMapResolution(qreal)));
+
+ connect(m_mapEngine, SIGNAL(directionIndicatorValuesUpdate(qreal, qreal, bool)),
+ m_ui, SIGNAL(directionIndicatorValuesUpdate(qreal, qreal, bool)));
}
void SituareEngine::signalsFromRoutingService()
void clearUpdateLocationDialogData();
/**
+ * @brief Signal when direction and distance from current map center point to current GPS
+ * location is changed
+ *
+ * @param direction Direction in degrees
+ * @param distance Distance in meters
+ * @param draw Should the indicator triangle be drawn or not
+ */
+ void directionIndicatorValuesUpdate(qreal direction, qreal distance, bool draw);
+
+ /**
* @brief Signals when new friends data is ready
*
* @param friendList List of User instances (friends)
// normalize rect's center point to be inside the map
if (center.x() < OSM_MAP_MIN_PIXEL_X)
- rect.translate(OMS_MAP_PIXELS_X, 0);
+ rect.translate(OSM_MAP_PIXELS_X, 0);
else if (center.x() > OSM_MAP_MAX_PIXEL_X)
- rect.translate(-OMS_MAP_PIXELS_X, 0);
+ rect.translate(-OSM_MAP_PIXELS_X, 0);
return rect;
}
return true;
if (item1Rect.left() < (OSM_MAP_MIN_PIXEL_X + item1Rect.width() / 2)) {
- QRect translated = item1Rect.translated(OMS_MAP_PIXELS_X, 0);
+ QRect translated = item1Rect.translated(OSM_MAP_PIXELS_X, 0);
if (translated.intersects(item2Rect))
return true;
} else if (item1Rect.right() > (OSM_MAP_MAX_PIXEL_X - item1Rect.width() / 2)) {
- QRect translated = item1Rect.translated(-OMS_MAP_PIXELS_X, 0);
+ QRect translated = item1Rect.translated(-OSM_MAP_PIXELS_X, 0);
if (translated.intersects(item2Rect))
return true;
}
* @var MAP_SCENE_MIN_PIXEL_X
* @brief First scene horizontal pixel
*/
-const int MAP_SCENE_MIN_PIXEL_X = -OMS_MAP_PIXELS_X * MAP_SCENE_VERTICAL_OVERSIZE_FACTOR;
+const int MAP_SCENE_MIN_PIXEL_X = -OSM_MAP_PIXELS_X * MAP_SCENE_VERTICAL_OVERSIZE_FACTOR;
/**
* @var MAP_SCENE_MAX_PIXEL_X
* @brief Last scene horizontal pixel
*/
-const int MAP_SCENE_MAX_PIXEL_X = OMS_MAP_PIXELS_X * (1 + MAP_SCENE_VERTICAL_OVERSIZE_FACTOR) - 1;
+const int MAP_SCENE_MAX_PIXEL_X = OSM_MAP_PIXELS_X * (1 + MAP_SCENE_VERTICAL_OVERSIZE_FACTOR) - 1;
////////////////////////////////////////////////////////////////////////////////
// DEFAULT VALUES
const QString OSM_LICENSE = QString::fromUtf8("© OpenStreetMap contributors, CC-BY-SA");
-const int AUTO_CENTERING_DISABLE_DISTANCE = 100; ///< Distance in pixels
+const int AUTO_CENTERING_DISABLE_DISTANCE = 50; ///< Distance in pixels
//String constants for storing map settings:
const QString MAP_LAST_ZOOMLEVEL = "LAST_MAP_ZOOM_LEVEL"; ///< Maps last zoom level before logout
#include <QtAlgorithms>
#include <QDebug>
+#include <QGraphicsView>
#include <QString>
#include <QStringList>
#include <QUrl>
#include <QRect>
#include "common.h"
+#include "coordinates/geocoordinate.h"
#include "frienditemshandler.h"
#include "gpslocationitem.h"
#include "mapcommon.h"
return QPoint(x, y);
}
+QRectF MapEngine::currentViewSceneRect() const
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ const QPoint ONE_PIXEL = QPoint(1, 1);
+
+ QGraphicsView *view = m_mapScene->views().at(0);
+ QPointF sceneTopLeft = view->mapToScene(0, 0);
+ QPoint viewBottomRight = QPoint(view->size().width(), view->size().height()) - ONE_PIXEL;
+ QPointF sceneBottomRight = view->mapToScene(viewBottomRight);
+
+ return QRectF(sceneTopLeft, sceneBottomRight);
+}
+
void MapEngine::disableAutoCenteringIfRequired(SceneCoordinate coordinate)
{
if (isAutoCenteringEnabled()) {
{
qDebug() << __PRETTY_FUNCTION__;
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+ m_mapScene->spanItems(currentViewSceneRect());
}
void MapEngine::getTiles(SceneCoordinate coordinate)
{
qDebug() << __PRETTY_FUNCTION__;
+ m_gpsPosition = position;
+
// update GPS location item (but only if accuracy is a valid number)
if (!isnan(accuracy)) {
qreal resolution = MapScene::horizontalResolutionAtLatitude(position.latitude());
m_gpsLocationItem->updateItem(SceneCoordinate(position).toPointF(), accuracy, resolution);
}
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+ m_mapScene->spanItems(currentViewSceneRect());
// do automatic centering (if enabled)
if (m_autoCenteringEnabled) {
m_scrollStartedByGps = true;
scrollToPosition(m_lastAutomaticPosition);
}
+
+ updateDirectionIndicator();
}
void MapEngine::init()
m_ownLocation->hide();
}
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+ m_mapScene->spanItems(currentViewSceneRect());
}
QGraphicsScene* MapEngine::scene()
qDebug() << __PRETTY_FUNCTION__;
m_autoCenteringEnabled = enabled;
+
+ if (!m_autoCenteringEnabled && m_gpsLocationItem->isVisible())
+ updateDirectionIndicator();
}
void MapEngine::setCenterPosition(SceneCoordinate coordinate)
m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
}
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+ m_mapScene->spanItems(currentViewSceneRect());
emit newMapResolution(viewResolution());
+
+ updateDirectionIndicator();
}
void MapEngine::setGPSEnabled(bool enabled)
m_tilesGridSize.setWidth(gridWidth);
}
+void MapEngine::updateDirectionIndicator()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ qreal distance = m_gpsPosition.distanceTo(m_sceneCoordinate);
+
+ qreal direction = m_sceneCoordinate.azimuthTo(SceneCoordinate(m_gpsPosition));
+
+ // direction indicator triangle should be drawn only if the gps location item is not currently
+ // visible on the view
+ bool drawDirectionIndicatorTriangle = true;
+ if (currentViewSceneRect().contains(m_gpsLocationItem->pos()))
+ drawDirectionIndicatorTriangle = false;
+
+ emit directionIndicatorValuesUpdate(direction, distance, drawDirectionIndicatorTriangle);
+}
+
void MapEngine::updateViewTilesSceneRect()
{
qDebug() << __PRETTY_FUNCTION__;
{
qDebug() << __PRETTY_FUNCTION__;
+ updateDirectionIndicator();
+
if (m_zoomedIn) {
m_zoomedIn = false;
m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
m_mapScene->setZoomLevel(m_zoomLevel);
getTiles(m_sceneCoordinate);
m_mapScene->setSceneVerticalOverlap(m_viewSize.height(), m_zoomLevel);
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+ m_mapScene->spanItems(currentViewSceneRect());
emit newMapResolution(viewResolution());
}
void centerAndZoomTo(QRect rect);
/**
+ * @brief Returns the rect of the current scene area drawn on the view
+ *
+ * @returns Rect of the current scene area drawn on the view
+ */
+ QRectF currentViewSceneRect() const;
+
+ /**
* @brief Request disabling of auto centering if centered too far from the real location.
*
* @param coordinate scene's center coordinate
void setTilesGridSize(const QSize &viewSize);
/**
+ * @brief Updates direction and distance values to indicator button
+ *
+ * Calculate and update direction and distance values and send those to indicator button
+ */
+ void updateDirectionIndicator();
+
+ /**
* @brief Updates the current view rect including margins
*
* Calculates tiles rect in scene based on m_viewTilesGrid and
void mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image);
/**
- * @brief Called when MapScroller state is changed
- *
- * Does check if the smooth scroll effect was interrupted and should the auto centering
- * feature to be disabled.
- *
- * @param newState New state
- */
+ * @brief Called when MapScroller state is changed
+ *
+ * Does check if the smooth scroll effect was interrupted and should the auto centering
+ * feature to be disabled.
+ *
+ * @param newState New state
+ */
void scrollerStateChanged(QAbstractAnimation::State newState);
/**
- * @brief Scroll smoothly to given scene position
- *
- * @param coordinate Target position in the scene
- */
+ * @brief Scroll smoothly to given scene position
+ *
+ * @param coordinate Target position in the scene
+ */
void scrollToPosition(SceneCoordinate coordinate);
/**
******************************************************************************/
signals:
/**
+ * @brief Signal when direction and distance from current map center point to current GPS
+ * location is changed
+ *
+ * @param direction Direction in degrees
+ * @param distance Distance in meters
+ * @param draw Should the indicator triangle be drawn or not
+ */
+ void directionIndicatorValuesUpdate(qreal direction, qreal distance, bool draw);
+
+ /**
* @brief Signals error
*
* @param context error context
QSize m_viewSize; ///< Current view size
FriendItemsHandler *m_friendItemsHandler; ///< Handler for friend and group items
+ GeoCoordinate m_gpsPosition; ///< Latest GPS position
GPSLocationItem *m_gpsLocationItem; ///< Item pointing current location from GPS
MapFetcher *m_mapFetcher; ///< Fetcher for map tiles
MapRouteItem *m_mapRouteItem; ///< Map route item
- tilesGridWidthHalf
+ MAP_GRID_PADDING))) {
QRect oppositeRect = m_tilesSceneRect;
- oppositeRect.translate(-OMS_MAP_PIXELS_X, 0);
+ oppositeRect.translate(-OSM_MAP_PIXELS_X, 0);
QList<QGraphicsItem *> oppositeItems = items(oppositeRect, Qt::IntersectsItemBoundingRect);
foreach (QGraphicsItem *item, oppositeItems)
allItems.removeOne(item);
// side of the world which are removed from allTiles
if (tilesGrid.left() < (tilesGridWidthHalf - MAP_GRID_PADDING)) {
QRect oppositeRect = m_tilesSceneRect;
- oppositeRect.translate(OMS_MAP_PIXELS_X, 0);
+ oppositeRect.translate(OSM_MAP_PIXELS_X, 0);
QList<QGraphicsItem *> oppositeItems = items(oppositeRect, Qt::IntersectsItemBoundingRect);
foreach (QGraphicsItem *item, oppositeItems)
allItems.removeOne(item);
m_zoomLevel = zoomLevel;
}
-void MapScene::spanItems(int zoomLevel, SceneCoordinate coordinate, QSize viewSize)
+void MapScene::spanItems(QRectF viewSceneRect)
{
qDebug() << __PRETTY_FUNCTION__;
leftRect.setBottom(OSM_MAP_MAX_PIXEL_Y);
QRect rightRect = leftRect;
- // calculate current horizontal area shown on the view
- int viewSceneWidth = (1 << (OSM_MAX_ZOOM_LEVEL - zoomLevel)) * viewSize.width();
- int viewSceneLeft = coordinate.x() - viewSceneWidth / 2;
- int viewSceneRight = coordinate.x() + viewSceneWidth / 2;
-
// limit rects to include only area which really must be moved
- leftRect.setRight(-1 - (OMS_MAP_PIXELS_X - 1 - viewSceneRight));
- rightRect.setLeft(OMS_MAP_PIXELS_X + viewSceneLeft);
+ leftRect.setRight(-1 - (OSM_MAP_PIXELS_X - 1 - viewSceneRect.right()));
+ rightRect.setLeft(OSM_MAP_PIXELS_X + viewSceneRect.left());
- Q_ASSERT_X(leftRect.right() < viewSceneLeft, "spanning rect right value", "move rect is in the view area");
- Q_ASSERT_X(rightRect.left() > viewSceneRight, "spanning rect left value", "move rect is in the view area");
+ Q_ASSERT_X(leftRect.right() < viewSceneRect.left(), "spanning rect right value", "move rect is in the view area");
+ Q_ASSERT_X(rightRect.left() > viewSceneRect.right(), "spanning rect left value", "move rect is in the view area");
// move all items which intersects the rects
if (leftRect.left() < leftRect.right())
- moveIntersectingItemsHorizontally(leftRect, OMS_MAP_PIXELS_X);
+ moveIntersectingItemsHorizontally(leftRect, OSM_MAP_PIXELS_X);
if (rightRect.left() < rightRect.right())
- moveIntersectingItemsHorizontally(rightRect, -OMS_MAP_PIXELS_X);
+ moveIntersectingItemsHorizontally(rightRect, -OSM_MAP_PIXELS_X);
}
void MapScene::tilesSceneRectUpdated(QRect tilesSceneRect)
/**
* @brief Span items (others than MapTile) to opposite side of the scene
*
- * @param zoomLevel Current zoom level
- * @param coordinate Scene coordinates of the current center point
- * @param viewSize Current size of the view
+ * @param viewSceneRect Scene area which is currently drawn on the view
*/
- void spanItems(int zoomLevel, SceneCoordinate coordinate, QSize viewSize);
+ void spanItems(QRectF viewSceneRect);
/**
* @brief Save new tiles scene rect
// MAP PIXELS
/**
-* @var OMS_MAP_PIXELS_X
+* @var OSM_MAP_PIXELS_X
* @brief Amount of horizontal pixels in map
*/
-const int OMS_MAP_PIXELS_X = OSM_TILES_PER_SIDE * OSM_TILE_SIZE_X;
+const int OSM_MAP_PIXELS_X = OSM_TILES_PER_SIDE * OSM_TILE_SIZE_X;
const int OSM_MAP_MIN_PIXEL_X = 0; ///< First map horizontal pixel index
const int OSM_MAP_MIN_PIXEL_Y = 0; ///< First map vertical pixel index
-const int OSM_MAP_MAX_PIXEL_X = OMS_MAP_PIXELS_X - 1; ///< Last map horizontal pixel index
+const int OSM_MAP_MAX_PIXEL_X = OSM_MAP_PIXELS_X - 1; ///< Last map horizontal pixel index
/**
* @var OSM_MAP_MAX_PIXEL_Y
* @brief Last map vertical pixel index
ui/listitemdelegate.cpp \
ui/friendlistitemdelegate.cpp \
ui/searchdialog.cpp \
+ ui/indicatorbuttonpanel.cpp\
routing/geocodingservice.cpp
HEADERS += application.h \
common.h \
ui/friendlistitemdelegate.h \
ui/listcommon.h \
ui/searchdialog.h \
+ ui/indicatorbuttonpanel.h\
error.h \
routing/geocodingservice.h
QT += network \
Situare - A location system for Facebook
Copyright (C) 2010 Ixonos Plc. Authors:
- Kaj Wallin - kaj.wallin@ixonos.com
Katri Kaikkonen - katri.kaikkonen@ixonos.com
+ Kaj Wallin - kaj.wallin@ixonos.com
+ Sami Rämö - sami.ramo@ixonos.com
Situare is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
#include <QPainter>
#include <QSettings>
-#include "math.h"
-
-#include "indicatorbutton.h"
-
#include "common.h"
+#include "math.h"
#include "panelcommon.h"
-enum State {OFF, ON}; ///< Enumerator for led state
-
-const int ROUNDING_RADIUS = 9; ///< Roundness of the rounded edge
-const int BUTTON_WIDTH = 66; ///< Button width
-const int BUTTON_HEIGHT = 66; ///< Button height
+#include "indicatorbutton.h"
-const qreal OPACITY = 0.50; ///< Opacity of the background in percents
+enum State {OFF, ON}; ///< Enumerator for led state
IndicatorButton::IndicatorButton(QWidget *parent)
: QToolButton(parent),
- m_isDraggable(false)
+ m_drawTriangle(false),
+ m_direction(0)
{
- m_indicatorLeds[OFF].load(":res/images/gps_position.png");
- m_indicatorLeds[ON].load(":res/images/gps_position_s.png");
- setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
+ qDebug() << __PRETTY_FUNCTION__;
- QSettings settings(DIRECTORY_NAME, FILE_NAME);
- QPoint savedLocation = settings.value(DIRECTION_INDICATOR_BUTTON_POSITION,
- QPoint(DIRECTION_INDICATOR_POSITION_X,
- DIRECTION_INDICATOR_POSITION_Y)).toPoint();
+ const qreal OPACITY = 0.50;
+ const int BUTTON_WIDTH = 66;
+ const int BUTTON_HEIGHT = 66;
- if(savedLocation.x() > DEFAULT_SCREEN_WIDTH || savedLocation.y() > DEFAULT_SCREEN_HEIGHT) {
- savedLocation.rx() = DIRECTION_INDICATOR_POSITION_X;
- savedLocation.ry() = DIRECTION_INDICATOR_POSITION_Y;
- }
+ m_indicatorLeds[OFF].load(":res/images/gps_position.png");
+ m_indicatorLeds[ON].load(":res/images/gps_position_s.png");
- move(savedLocation);
+ setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
// Normal background
m_normalColor = new QColor(Qt::black);
m_normalColor->setAlpha(floor(OPACITY * 255));
- // Selected bakcground
+ // Selected background
m_selectedGradient = new QLinearGradient(0, 0, 0, this->height());
m_selectedGradient->setColorAt(0.02, QColor(0, 113, 181));
m_selectedGradient->setColorAt(0.25, QColor(24, 142, 214));
m_selectedGradient->setColorAt(0.75, QColor(82, 195, 255));
m_selectedGradient->setColorAt(0.98, QColor(115, 215, 255));
- m_dragStartTimer = new QTimer(this);
- m_dragStartTimer->setSingleShot(true);
- m_dragStartTimer->setInterval(DRAG_INIT_TIME);
-
- m_forceReleaseTimer = new QTimer(this);
- m_forceReleaseTimer->setSingleShot(true);
- m_forceReleaseTimer->setInterval(FORCE_RELEASE_TIME);
-
- connect(this, SIGNAL(pressed()),
- m_dragStartTimer, SLOT(start()));
- connect(this, SIGNAL(released()),
- m_dragStartTimer, SLOT(stop()));
connect(this, SIGNAL(clicked(bool)),
this, SIGNAL(autoCenteringTriggered(bool)));
- connect(m_dragStartTimer, SIGNAL(timeout()),
- this, SLOT(timerExpired()));
- connect(m_forceReleaseTimer, SIGNAL(timeout()),
- this, SLOT(forceMouseRelease()));
-
setCheckable(true);
}
delete m_selectedGradient;
}
-void IndicatorButton::mousePressEvent(QMouseEvent *event)
+const QPoint& IndicatorButton::eventPosition()
{
qDebug() << __PRETTY_FUNCTION__;
- if (event->button() == Qt::LeftButton)
- m_dragPosition = event->pos();
-
- m_eventPosition = mapToParent(event->pos());
- m_dragStartTimer->start();
- setDown(true);
+ return m_eventPosition;
}
void IndicatorButton::mouseMoveEvent(QMouseEvent *event)
{
qDebug() << __PRETTY_FUNCTION__;
- if(m_isDraggable) {
- if (event->buttons() & Qt::LeftButton) {
- QPoint newLocation = mapToParent(event->pos()) - m_dragPosition;
+ QToolButton::mouseMoveEvent(event);
- if (newLocation.x() < SIDEBAR_WIDTH)
- newLocation.rx() = SIDEBAR_WIDTH;
- else if (newLocation.x() > m_screenSize.width() - width() - SIDEBAR_WIDTH)
- newLocation.rx() = m_screenSize.width() - width() - SIDEBAR_WIDTH;
-
- if (newLocation.y() < 0)
- newLocation.ry() = 0;
- else if (newLocation.y() > m_screenSize.height() - height())
- newLocation.ry() = m_screenSize.height() - height();
-
- move(newLocation);
- }
- } else {
- if(!rect().contains(event->pos())) {
- m_dragStartTimer->stop();
- setDown(false);
- }
- }
+ event->ignore();
}
-void IndicatorButton::mouseReleaseEvent(QMouseEvent *event)
+void IndicatorButton::mousePressEvent(QMouseEvent *event)
{
qDebug() << __PRETTY_FUNCTION__;
- m_dragStartTimer->stop();
+ QToolButton::mousePressEvent(event);
- if(m_isDraggable) {
- setDraggable(false);
- QSettings settings(DIRECTORY_NAME, FILE_NAME);
- settings.setValue(DIRECTION_INDICATOR_BUTTON_POSITION, pos());
- } else {
- if(this->rect().contains(event->pos())) {
- if(isChecked()) {
- setChecked(false);
- emit autoCenteringTriggered(false);
- } else {
- setChecked(true);
- emit autoCenteringTriggered(true);
- }
- }
- }
- setDown(false);
+ event->ignore();
}
-void IndicatorButton::setDraggable(bool mode, QPoint eventPosition)
+void IndicatorButton::mouseReleaseEvent(QMouseEvent *event)
{
qDebug() << __PRETTY_FUNCTION__;
- m_isDraggable = mode;
+ QToolButton::mouseReleaseEvent(event);
- if(mode) {
- emit draggingModeTriggered();
- m_forceReleaseTimer->start();
- m_dragPosition = eventPosition;
- } else {
- m_forceReleaseTimer->stop();
- }
- update();
+ event->ignore();
}
-void IndicatorButton::screenResized(const QSize &newSize)
+void IndicatorButton::paintEvent(QPaintEvent *event)
{
qDebug() << __PRETTY_FUNCTION__;
- int oldHeight = 0;
- int oldWidth = 0;
-
- if(m_screenSize.height() < 0)
- oldHeight = DEFAULT_NON_FULLSCREEN_HEIGHT;
- else
- oldHeight = m_screenSize.height();
-
- if(m_screenSize.width() < 0)
- oldWidth = DEFAULT_SCREEN_WIDTH;
- else
- oldWidth = m_screenSize.width();
+ const int ROUNDING_RADIUS = 9;
- m_screenSize = newSize;
+ Q_UNUSED(event);
- QPoint resizedPosition = pos();
- if(resizedPosition.x() > (newSize.width() - rect().width()))
- resizedPosition.rx() = newSize.width() - rect().width();
- else if (resizedPosition.x() < SIDEBAR_WIDTH)
- resizedPosition.rx() = SIDEBAR_WIDTH;
- if(resizedPosition.y() > (newSize.height() - rect().height()))
- resizedPosition.ry() = newSize.height() - rect().height();
- else if (resizedPosition.y() < 0)
- resizedPosition.ry() = 0;
+ QPainterPath backgroundPath;
+ backgroundPath.addRoundedRect(this->rect(), ROUNDING_RADIUS, ROUNDING_RADIUS);
- if((pos().y() + rect().center().y()) > (oldHeight/2))
- resizedPosition.ry() = newSize.height() - (oldHeight - pos().y());
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing);
- if((pos().x() + rect().center().x()) > (oldWidth/2))
- resizedPosition.rx() = newSize.width() - (oldWidth - pos().x());
+ if (isDown())
+ painter.fillPath(backgroundPath, QBrush(*m_selectedGradient));
+ else
+ painter.fillPath(backgroundPath, QBrush(*m_normalColor));
- move(resizedPosition);
-}
+ const QPointF CENTER = QPointF(this->width(), this->height()) / 2;
-const QPoint& IndicatorButton::eventPosition()
-{
- qDebug() << __PRETTY_FUNCTION__;
+ if (isChecked()) {
+ const QPointF offset = QPointF(m_indicatorLeds[ON].width(),
+ m_indicatorLeds[ON].height()) / 2;
- return m_eventPosition;
-}
+ painter.drawPixmap(CENTER - offset, m_indicatorLeds[ON]);
+ } else {
+ const QPointF offset = QPointF(m_indicatorLeds[OFF].width(),
+ m_indicatorLeds[OFF].height()) / 2;
-void IndicatorButton::forceMouseRelease()
-{
- qDebug() << __PRETTY_FUNCTION__;
+ painter.drawPixmap(CENTER - offset, m_indicatorLeds[OFF]);
+ }
- releaseMouse();
- setDraggable(false);
-}
+ // draw the direction indicator triangle only when autocentering is disabled and MapEngine
+ // doesn't deny drawing (because GPS location item is visible)
+ if (!isChecked() && m_drawTriangle) {
+ const int TRIANGLE_WIDTH = 10;
+ const int TRIANGLE_HEIGHT = 10;
+ const int TRIANGLE_DISTANCE_FROM_CENTER = 15;
-void IndicatorButton::paintEvent(QPaintEvent *event)
-{
- qDebug() << __PRETTY_FUNCTION__;
+ const int POINTS = 3;
+ const QPointF points[POINTS] = {
+ QPointF(-TRIANGLE_WIDTH / 2, -TRIANGLE_DISTANCE_FROM_CENTER),
+ QPointF(0, -(TRIANGLE_DISTANCE_FROM_CENTER + TRIANGLE_HEIGHT)),
+ QPointF(TRIANGLE_WIDTH / 2, -TRIANGLE_DISTANCE_FROM_CENTER)
+ };
- Q_UNUSED(event);
+ // base triangle is facing up, and needs to be rotated to the required direction
+ QTransform rotationTransform;
+ rotationTransform.rotate(m_direction);
- QPainterPath backgroundPath;
- backgroundPath.addRoundedRect(this->rect(), ROUNDING_RADIUS, ROUNDING_RADIUS);
+ // origin is in the top left corner of the button, and needs to be translated to the
+ // center of the button
+ QTransform translateTransform;
+ translateTransform.translate(CENTER.x(), CENTER.y());
- QPainter painter(this);
- painter.setRenderHint(QPainter::Antialiasing);
+ painter.setTransform(rotationTransform * translateTransform);
- if(m_isDraggable)
- painter.fillPath(backgroundPath, QBrush(Qt::Dense4Pattern));
- else if (isDown())
- painter.fillPath(backgroundPath, QBrush(*m_selectedGradient));
- else
- painter.fillPath(backgroundPath, QBrush(*m_normalColor));
+ // setting the look of the triangle
+ painter.setBrush(Qt::red);
+ painter.setPen(Qt::red);
- if(isChecked())
- painter.drawPixmap((this->width() / 2) - (m_indicatorLeds[ON].width() / 2),
- (this->height() / 2) - (m_indicatorLeds[ON].height() / 2),
- m_indicatorLeds[ON]);
- else
- painter.drawPixmap((this->width() / 2) - (m_indicatorLeds[OFF].width() / 2),
- (this->height() / 2) - (m_indicatorLeds[OFF].height() / 2),
- m_indicatorLeds[OFF]);
+ painter.drawPolygon(points, POINTS);
+ }
}
-void IndicatorButton::timerExpired()
+void IndicatorButton::setDirection(qreal direction, bool draw)
{
qDebug() << __PRETTY_FUNCTION__;
- setDraggable(true, m_dragPosition);
+ m_direction = direction;
+ m_drawTriangle = draw;
+
+ update();
}
+
Situare - A location system for Facebook
Copyright (C) 2010 Ixonos Plc. Authors:
- Kaj Wallin - kaj.wallin@ixonos.com
Katri Kaikkonen - katri.kaikkonen@ixonos.com
+ Kaj Wallin - kaj.wallin@ixonos.com
+ Sami Rämö - sami.ramo@ixonos.com
Situare is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
* @brief Indicator button class
*
* @author Katri Kaikkonen - katri.kaikkonen (at) ixonos.com
- *
- * @class IndicatorButton indicatorbutton.h "ui/indicatorbutton.h"
+ * @author Sami Rämö - sami.ramo (at) ixonos.com
*/
class IndicatorButton : public QToolButton
{
******************************************************************************/
protected:
/**
- * @brief Move event for the distance indicator button
+ * @brief Event handler for mouse move events
*
* @param event Mouse event
*/
void mouseMoveEvent(QMouseEvent *event);
/**
- * @brief Press event for the distance indicator button
+ * @brief Event handler for mouse press events
*
* @param event Mouse event
*/
const QPoint& eventPosition();
/**
- * @brief Slot to redraw the panel after window resize event
+ * @brief Sets direction information for the distance indicator button
*
- * @param size Size of the new screen
- */
- void screenResized(const QSize &size);
-
- /**
- * @brief Toggle distance indicator button draggability
- */
- void setDraggable(bool mode, QPoint eventPosition = QPoint(0,0));
-
-private slots:
- /**
- * @brief Safeguard slot to release mouse grab if something goes horribly wrong
- */
- void forceMouseRelease();
-
- /**
- * @brief Slot that handles drag initialization once timer has timed out
+ * Paints the button and its icon
+ * @param Direction to the GPS position (in degrees)
+ * @param Draw direction triangle
*/
- void timerExpired();
+ void setDirection(qreal direction, bool draw);
/*******************************************************************************
* SIGNALS
*/
void autoCenteringTriggered(bool enabled);
- /**
- * @brief Dragging mode triggered.
- */
- void draggingModeTriggered();
-
/*******************************************************************************
* DATA MEMBERS
******************************************************************************/
private:
- bool m_isDraggable; ///< Boolean for tracking the draggability state
+ bool m_drawTriangle; ///< Should the direction triange be drawn
+
+ qreal m_direction; ///< Direction to the GPS position (in degrees)
QColor *m_normalColor; ///< Normal background color
QPixmap m_indicatorLeds[2]; ///< Placeholder for images
- QPoint m_dragPosition; ///< Location from where the widget is grabbed
- QPoint m_eventPosition; ///< Position of mousePressEvent
-
- QSize m_screenSize; ///< Store for the screen size
-
- QTimer *m_dragStartTimer; ///< Timer to init draggability of the distance indicator button
- QTimer *m_forceReleaseTimer; ///< Timer to run forceMouseRelease
+ QPoint m_dragPosition; ///< Location from where the widget is grabbed
+ QPoint m_eventPosition; ///< Position of mousePressEvent
};
#endif // INDICATORBUTTON_H
--- /dev/null
+/*
+ Situare - A location system for Facebook
+ Copyright (C) 2010 Ixonos Plc. Authors:
+
+ Pekka Nissinen - pekka.nissinen@ixonos.com
+ Kaj Wallin - kaj.wallin@ixonos.com
+ Katri Kaikkonen - katri.kaikkonen@ixonos.com
+
+ Situare is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ Situare 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 Situare; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA.
+*/
+
+#include <QDebug>
+#include <QPainter>
+#include <QSettings>
+
+#include "common.h"
+#include "indicatorbutton.h"
+#include "panelcommon.h"
+
+#include "indicatorbuttonpanel.h"
+
+const QString DIRECTION_INDICATOR_BUTTON_POSITION = "DIRECTION_INDICATOR_POSITION";
+
+IndicatorButtonPanel::IndicatorButtonPanel(QWidget *parent)
+ : QWidget(parent),
+ m_isDraggable(false)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ const int DIRECTION_INDICATOR_POSITION_X = 10 + PANEL_PEEK_AMOUNT;
+ const int DIRECTION_INDICATOR_POSITION_Y = 290;
+
+ const int INDICATOR_BUTTON_PANEL_SPACING = 5;
+
+ const qreal OPACITY = 0.50;
+ const int MARGIN_LEFT = 0;
+ const int MARGIN_TOP = 3;
+ const int MARGIN_RIGHT = 0;
+ const int MARGIN_BOTTOM = 0;
+ const int LABEL_MARGIN_TOP = 0;
+
+ const int PANEL_WIDTH = 90;
+ const int PANEL_HEIGHT = 100;
+
+ QVBoxLayout *verticalLayout = new QVBoxLayout;
+ setLayout(verticalLayout);
+ verticalLayout->setContentsMargins(MARGIN_LEFT, MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM);
+ verticalLayout->setSpacing(INDICATOR_BUTTON_PANEL_SPACING);
+
+ m_indicatorButton = new IndicatorButton(this);
+
+ m_distanceTextLabel = new QLabel();
+ m_distanceTextLabel->setFont(QFont(NOKIA_FONT_SMALL));
+ m_distanceTextLabel->setAlignment(Qt::AlignHCenter);
+ m_distanceTextLabel->setContentsMargins(MARGIN_LEFT, LABEL_MARGIN_TOP, MARGIN_RIGHT
+ , MARGIN_BOTTOM);
+
+ m_normalColor = new QColor(Qt::black);
+ m_normalColor->setAlpha(OPACITY * 255);
+
+ verticalLayout->addWidget(m_indicatorButton, 0, Qt::AlignHCenter);
+ verticalLayout->addWidget(m_distanceTextLabel, 0, Qt::AlignHCenter);
+ verticalLayout->addStretch();
+
+ setFixedSize(PANEL_WIDTH, PANEL_HEIGHT);
+
+ QSettings settings(DIRECTORY_NAME, FILE_NAME);
+ QPoint savedLocation = settings.value(DIRECTION_INDICATOR_BUTTON_POSITION,
+ QPoint(DIRECTION_INDICATOR_POSITION_X,
+ DIRECTION_INDICATOR_POSITION_Y)).toPoint();
+
+ if((savedLocation.x() > DEFAULT_SCREEN_WIDTH) || (savedLocation.y() > DEFAULT_SCREEN_HEIGHT)) {
+ savedLocation.rx() = DIRECTION_INDICATOR_POSITION_X;
+ savedLocation.ry() = DIRECTION_INDICATOR_POSITION_Y;
+ }
+
+ move(savedLocation);
+
+ m_dragStartTimer = new QTimer(this);
+ m_dragStartTimer->setSingleShot(true);
+ m_dragStartTimer->setInterval(DRAG_INIT_TIME);
+
+ m_forceReleaseTimer = new QTimer(this);
+ m_forceReleaseTimer->setSingleShot(true);
+ m_forceReleaseTimer->setInterval(FORCE_RELEASE_TIME);
+
+ connect(m_dragStartTimer, SIGNAL(timeout()),
+ this, SLOT(timerExpired()));
+
+ connect(m_forceReleaseTimer, SIGNAL(timeout()),
+ this, SLOT(forceMouseRelease()));
+
+ connect(this, SIGNAL(directionIndicatorValuesUpdate(qreal, qreal, bool)),
+ this, SLOT(updateValues(qreal, qreal, bool)));
+
+ connect(m_indicatorButton, SIGNAL(autoCenteringTriggered(bool)),
+ this, SIGNAL(autoCenteringTriggered(bool)));
+}
+
+void IndicatorButtonPanel::forceMouseRelease()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ releaseMouse();
+ setDraggable(false);
+}
+
+void IndicatorButtonPanel::mouseMoveEvent(QMouseEvent *event)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ if(m_isDraggable) {
+ if (event->buttons() & Qt::LeftButton) {
+ QPoint newLocation = mapToParent(event->pos()) - m_dragPosition;
+
+ if (newLocation.x() < SIDEBAR_WIDTH)
+ newLocation.rx() = SIDEBAR_WIDTH;
+ else if (newLocation.x() > m_screenSize.width() - width() - SIDEBAR_WIDTH)
+ newLocation.rx() = m_screenSize.width() - width() - SIDEBAR_WIDTH;
+
+ if (newLocation.y() < 0)
+ newLocation.ry() = 0;
+ else if (newLocation.y() > m_screenSize.height() - height())
+ newLocation.ry() = m_screenSize.height() - height();
+
+ move(newLocation);
+ }
+ } else {
+ if(!rect().contains(event->pos()))
+ m_dragStartTimer->stop();
+ }
+}
+
+void IndicatorButtonPanel::mousePressEvent(QMouseEvent *event)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ m_dragPosition = event->pos();
+ m_dragStartTimer->start();
+}
+
+void IndicatorButtonPanel::mouseReleaseEvent(QMouseEvent *event)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ m_dragStartTimer->stop();
+
+ Q_UNUSED(event);
+ if(m_isDraggable) {
+ setDraggable(false);
+
+ QSettings settings(DIRECTORY_NAME, FILE_NAME);
+ settings.setValue(DIRECTION_INDICATOR_BUTTON_POSITION, pos());
+ }
+}
+
+void IndicatorButtonPanel::paintEvent(QPaintEvent *event)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ Q_UNUSED(event);
+
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing);
+
+ if (!m_indicatorButton->isChecked()) {
+ const int EXTRA_SPACE_LEFT = -5;
+ const int EXTRA_SPACE_TOP = 0;
+ const int EXTRA_SPACE_RIGHT = +5;
+ const int EXTRA_SPACE_BOTTOM = 0;
+
+ const int RADIUS_WIDTH = 5;
+ const int RADIUS_HEIGHT = 5;
+
+ QPainterPath backgroundPath;
+ QRect distanceLabelRect = m_distanceTextLabel->rect();
+
+ distanceLabelRect.translate(m_distanceTextLabel->pos());
+ distanceLabelRect.adjust(EXTRA_SPACE_LEFT, EXTRA_SPACE_TOP, EXTRA_SPACE_RIGHT
+ , EXTRA_SPACE_BOTTOM);
+ backgroundPath.addRoundedRect(distanceLabelRect, RADIUS_WIDTH, RADIUS_HEIGHT);
+ painter.fillPath(backgroundPath, QBrush(*m_normalColor));
+
+ update();
+ }
+
+ if(m_isDraggable) {
+ const int ROUNDING_RADIUS = 9;
+
+ QPainterPath backgroundPath;
+ backgroundPath.addRoundedRect(this->rect(), ROUNDING_RADIUS, ROUNDING_RADIUS);
+ painter.fillPath(backgroundPath, QBrush(Qt::Dense4Pattern));
+ painter.setPen(Qt::black);
+ }
+}
+
+void IndicatorButtonPanel::screenResized(const QSize &newSize)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ int oldHeight = 0;
+ int oldWidth = 0;
+
+ if(m_screenSize.height() < 0)
+ oldHeight = DEFAULT_NON_FULLSCREEN_HEIGHT;
+ else
+ oldHeight = m_screenSize.height();
+
+ if(m_screenSize.width() < 0)
+ oldWidth = DEFAULT_SCREEN_WIDTH;
+ else
+ oldWidth = m_screenSize.width();
+
+ m_screenSize = newSize;
+
+ QPoint resizedPosition = pos();
+ if(resizedPosition.x() > (newSize.width() - rect().width()))
+ resizedPosition.rx() = newSize.width() - rect().width();
+ else if (resizedPosition.x() < SIDEBAR_WIDTH)
+ resizedPosition.rx() = SIDEBAR_WIDTH;
+ if(resizedPosition.y() > (newSize.height() - rect().height()))
+ resizedPosition.ry() = newSize.height() - rect().height();
+ else if (resizedPosition.y() < 0)
+ resizedPosition.ry() = 0;
+
+ if((pos().y() + rect().center().y()) > (oldHeight/2))
+ resizedPosition.ry() = newSize.height() - (oldHeight - pos().y());
+
+ if((pos().x() + rect().center().x()) > (oldWidth/2))
+ resizedPosition.rx() = newSize.width() - (oldWidth - pos().x());
+
+ move(resizedPosition);
+}
+
+void IndicatorButtonPanel::setDraggable(bool mode, QPoint eventPosition)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ m_isDraggable = mode;
+
+ if(mode) {
+ emit draggingModeTriggered();
+ grabMouse();
+ m_forceReleaseTimer->start();
+ m_dragPosition = eventPosition;
+ } else {
+ releaseMouse();
+ m_forceReleaseTimer->stop();
+ m_indicatorButton->setDown(false);
+ }
+ update();
+}
+
+void IndicatorButtonPanel::setIndicatorButtonEnabled(bool enabled)
+{
+ m_indicatorButton->setChecked(enabled);
+ m_distanceTextLabel->setVisible(!enabled);
+}
+
+void IndicatorButtonPanel::timerExpired()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ setDraggable(true, m_dragPosition);
+}
+
+void IndicatorButtonPanel::updateValues(qreal direction, qreal distance, bool draw)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ const int MAX_TO_METERS = 999.5;
+ const int MAX_TO_KM_WITH_DESIMAL = 99950;
+ const int MIN_TO_METERS = 10;
+ const int M_TO_KM = 1000; ///< Meters to kilometers conversion
+
+ QString UNIT_KILOMETER = " km";
+ QString UNIT_METER = " m";
+
+ m_indicatorButton->setDirection(direction, draw);
+
+ m_distance = distance;
+
+ if(m_distance < MIN_TO_METERS)
+ {
+ m_distanceText.setNum(10);
+ m_distanceText.prepend("< ");
+ m_distanceText.append(UNIT_METER);
+ }
+ else if(m_distance < MAX_TO_METERS)
+ {
+ m_distanceText.setNum(m_distance, 0 , 0);
+ m_distanceText.append(UNIT_METER);
+ }
+ else if(m_distance < MAX_TO_KM_WITH_DESIMAL)
+ {
+ m_distanceText.setNum(m_distance / M_TO_KM, 1, 1);
+ m_distanceText.append(UNIT_KILOMETER);
+ }
+ else {
+ m_distanceText.setNum(m_distance / M_TO_KM, 0, 0);
+ m_distanceText.append(UNIT_KILOMETER);
+ }
+
+ m_distanceTextLabel->setText(m_distanceText);
+
+ update();
+}
+
--- /dev/null
+/*
+ Situare - A location system for Facebook
+ Copyright (C) 2010 Ixonos Plc. Authors:
+
+ Pekka Nissinen - pekka.nissinen@ixonos.com
+ Kaj Wallin - kaj.wallin@ixonos.com
+ Katri Kaikkonen - katri.kaikkonen@ixonos.com
+
+ Situare is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as published by the Free Software Foundation.
+
+ Situare 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 Situare; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA.
+*/
+
+#ifndef INDICATORBUTTONPANEL_H
+#define INDICATORBUTTONPANEL_H
+
+#include <QGraphicsItem>
+#include <QGridLayout>
+#include <QLabel>
+#include <QMouseEvent>
+#include <QTimer>
+#include <QWidget>
+
+#include "indicatorbutton.h"
+
+/**
+ * @brief Draggable panel for indicator button
+ *
+ * @author Katri Kaikkonen - katri.kaikkonen (at) ixonos.com
+ * @author Pekka Nissinen - pekka.nissinen (at) ixonos.com
+ * @author Kaj Wallin - kaj.wallin (at) ixonos.com
+ */
+class IndicatorButtonPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @brief Constructor
+ *
+ * @param parent Parent
+ */
+ IndicatorButtonPanel(QWidget *parent = 0);
+
+/*******************************************************************************
+ * BASE CLASS INHERITED AND REIMPLEMENTED MEMBER FUNCTIONS
+ ******************************************************************************/
+protected:
+ /**
+ * @brief Move event for the indicator button panel
+ *
+ * @param event Event
+ */
+ void mouseMoveEvent(QMouseEvent *event);
+
+ /**
+ * @brief Press event for the indicator button panel
+ *
+ * @param event Event
+ */
+ void mousePressEvent(QMouseEvent *event);
+
+ /**
+ * @brief Event handler for mouse release events
+ *
+ * @param event Mouse event
+ */
+ void mouseReleaseEvent(QMouseEvent *event);
+
+ /**
+ * @brief Event handler for paint events
+ *
+ * Paints the panel
+ * @param event Paint event
+ */
+ void paintEvent(QPaintEvent *event);
+
+/*******************************************************************************
+ * MEMBER FUNCTIONS AND SLOTS
+ ******************************************************************************/
+public slots:
+ /**
+ * @brief Called when direction and distance from current map center point to current GPS
+ * location is changed
+ *
+ * @param direction Direction in degrees
+ * @param distance Distance in meters
+ * @param draw Should the indicator triangle be drawn or not
+ */
+ void updateValues(qreal direction, qreal distance, bool draw);
+
+ /**
+ * @brief Set indicator button enabled.
+ *
+ * @param enabled true if enabled, false otherwise
+ */
+ void setIndicatorButtonEnabled(bool enabled);
+
+ /**
+ * @brief Toggle indicator button panel draggability
+ *
+ * @param mode True if draggable, otherwise false
+ * @param distance Start value for dragging
+ */
+ void setDraggable(bool mode, QPoint eventPosition = QPoint(0,0));
+
+ /**
+ * @brief Slot to redraw the panel after window resize event
+ *
+ * @param size Size of the new screen
+ */
+ void screenResized(const QSize &size);
+
+private slots:
+ /**
+ * @brief Safeguard slot to release mouse grab if something goes horribly wrong
+ */
+ void forceMouseRelease();
+
+ /**
+ * @brief Slot that handles drag initialization once timer has timed out
+ */
+ void timerExpired();
+
+/*******************************************************************************
+ * SIGNALS
+ ******************************************************************************/
+signals:
+ /**
+ * @brief Automatic centering setting changed by user
+ *
+ * @param enabled True if automatic centering is enabled, otherwise false
+ */
+ void autoCenteringTriggered(bool enabled);
+
+ /**
+ * @brief Signal when direction and distance from current map center point to current GPS
+ * location is changed
+ *
+ * @param direction Direction in degrees
+ * @param distance Distance in meters
+ * @param draw Should the indicator triangle be drawn or not
+ */
+ void directionIndicatorValuesUpdate(qreal direction, qreal distance, bool draw);
+
+ /**
+ * @brief Dragging mode triggered.
+ */
+ void draggingModeTriggered();
+
+/*******************************************************************************
+ * DATA MEMBERS
+ ******************************************************************************/
+private:
+ bool m_isDraggable; ///< Boolean for tracking the draggability state
+
+ qreal m_distance; ///< Distance to the GPS position
+
+ QColor *m_normalColor; ///< Normal background color
+
+ QLabel *m_distanceTextLabel; ///< Pointer to distanceTextLabel
+
+ QPoint m_dragPosition; ///< Location from where the widget is grabbed
+
+ QSize m_screenSize; ///< Store for the screen size
+
+ QString m_distanceText; ///< Text description of the distance
+
+ QTimer *m_dragStartTimer; ///< Timer to init draggability of the zoom panel
+ QTimer *m_forceReleaseTimer; ///< Timer to run forceMouseRelease;
+
+ IndicatorButton *m_indicatorButton; ///< Indicator button
+};
+
+#endif // INDICATORBUTTONPANEL_H
Jussi Laitinen jussi.laitinen@ixonos.com
Sami Rämö - sami.ramo@ixonos.com
Ville Tiensuu - ville.tiensuu@ixonos.com
+ Katri Kaikkonen - katri.kaikkonen@ixonos.com
Situare is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
#include "error.h"
#include "friendlistpanel.h"
#include "fullscreenbutton.h"
-#include "indicatorbutton.h"
#include "logindialog.h"
#include "mapscale.h"
#include "searchdialog.h"
#include "settingsdialog.h"
#include "userinfopanel.h"
#include "zoombuttonpanel.h"
+#include "indicatorbuttonpanel.h"
#include "mainwindow.h"
m_password(),
m_webView(0),
m_fullScreenButton(0),
- m_indicatorButton(0),
+ m_indicatorButtonPanel(0),
m_mapScale(0),
m_cookieJar(0)
{
m_osmLicense->stackUnder(m_zoomButtonPanel);
}
m_ownLocationCrosshair->stackUnder(m_osmLicense);
- m_indicatorButton->stackUnder(m_ownLocationCrosshair);
- m_mapScale->stackUnder(m_indicatorButton);
+ m_indicatorButtonPanel->stackUnder(m_ownLocationCrosshair);
+ m_mapScale->stackUnder(m_indicatorButtonPanel);
m_mapView->stackUnder(m_mapScale);
grabZoomKeys(true);
m_friendsListPanel, SLOT(friendImageReady(User*)));
}
-void MainWindow::buildIndicatorButton()
+void MainWindow::buildIndicatorButtonPanel()
{
qDebug() << __PRETTY_FUNCTION__;
- m_indicatorButton = new IndicatorButton(this);
+ m_indicatorButtonPanel = new IndicatorButtonPanel(this);
- connect(m_indicatorButton, SIGNAL(autoCenteringTriggered(bool)),
+ connect(m_indicatorButtonPanel, SIGNAL(autoCenteringTriggered(bool)),
this, SIGNAL(autoCenteringTriggered(bool)));
connect(m_mapView, SIGNAL(viewResized(QSize)),
- m_indicatorButton, SLOT(screenResized(QSize)));
+ m_indicatorButtonPanel, SLOT(screenResized(QSize)));
- connect(m_indicatorButton, SIGNAL(draggingModeTriggered()),
+ connect(this, SIGNAL(directionIndicatorValuesUpdate(qreal, qreal, bool)),
+ m_indicatorButtonPanel, SIGNAL(directionIndicatorValuesUpdate(qreal, qreal, bool)));
+
+ connect(m_indicatorButtonPanel, SIGNAL(draggingModeTriggered()),
this, SIGNAL(draggingModeTriggered()));
}
buildOsmLicense();
buildManualLocationCrosshair();
buildFullScreenButton();
- buildIndicatorButton();
+ buildIndicatorButtonPanel();
buildMapScale();
connect(m_mapView, SIGNAL(viewScrolled(SceneCoordinate)),
{
qDebug() << __PRETTY_FUNCTION__;
- m_indicatorButton->setChecked(enabled);
-
+ m_indicatorButtonPanel->setIndicatorButtonEnabled(enabled);
}
void MainWindow::setMapViewScene(QGraphicsScene *scene)
class FacebookAuthentication;
class FullScreenButton;
class FriendListPanel;
-class IndicatorButton;
+class IndicatorButtonPanel;
class GeoCoordinate;
class MapScale;
class MapScene;
public slots:
/**
- * @brief Build direction indicator button and connect slots
+ * @brief Build direction indicator button panel and connect signals
*/
- void buildIndicatorButton();
+ void buildIndicatorButtonPanel();
/**
* @brief Builds information box with message.
void centerToSceneCoordinates(const SceneCoordinate &coordinate);
/**
+ * @brief Signal when direction and distance from current map center point to current GPS
+ * location is changed
+ *
+ * @param direction Direction in degrees
+ * @param distance Distance in meters
+ * @param draw Should the indicator triangle be drawn or not
+ */
+ void directionIndicatorValuesUpdate(qreal direction, qreal distance, bool draw);
+
+ /**
* @brief Signal for enabling automatic location update.
*
* @param enabled true if enabled, false otherwise
FriendListPanel *m_friendsListPanel; ///< Instance of friends list panel
FullScreenButton *m_fullScreenButton; ///< Instance of the fullscreen toggle button
- IndicatorButton *m_indicatorButton; ///< Instance of direction indicator button
+ IndicatorButtonPanel *m_indicatorButtonPanel; ///< Instance of direction indicator button
MapScale *m_mapScale; ///< Instance of the map scale
MapView *m_mapView; ///< Instance of the map view
NetworkCookieJar *m_cookieJar; ///< Placeholder for QNetworkCookies
// Zoom button panel settings
const int ZOOM_BUTTON_PANEL_POSITION_X = 10 +
PANEL_PEEK_AMOUNT; ///< Horizontal position of zoom panel
-const int ZOOM_BUTTON_PANEL_POSITION_Y = 10; ///< Vertical position of zoom panel
-const int ZOOM_BUTTON_PANEL_BUTTON_SPACING = 4; ///< Size of a zoom button spacing
+const int ZOOM_BUTTON_PANEL_POSITION_Y = 10; ///< Vertical position of zoom panel
+const int ZOOM_BUTTON_PANEL_BUTTON_SPACING = 4; ///< Size of a zoom button spacing
const QString ZOOMPANEL_POSITION = "Zoom_Panel_Position";
-// Direction indicator button settings
-/**
- * @brief Horizontal position of direction indicator button
- *
- * @var DIRECTION_INDICATOR_POSITION_X
- */
-const int DIRECTION_INDICATOR_POSITION_X = 10 + PANEL_PEEK_AMOUNT;
-const int DIRECTION_INDICATOR_POSITION_Y = 315; ///< Vertical position of direction indicator button
-
-const QString DIRECTION_INDICATOR_BUTTON_POSITION = "Direction_Indicator_Position";
-
#endif // PANELCOMMON_H
const double X = 12.345678;
const double Y = -89.765432;
+const double ORIGIN = 1000;
+const double DELTA = 500;
+
class TestSceneCoordinate : public QObject
{
Q_OBJECT
private Q_SLOTS:
+ void azimuthTo();
+ void azimuthTo_data();
void constructors();
void conversion();
void conversion_data();
}
}
+void TestSceneCoordinate::azimuthTo()
+{
+ QFETCH(SceneCoordinate, to);
+ QFETCH(qreal, expectedAzimuth);
+
+ SceneCoordinate from(ORIGIN, ORIGIN);
+
+ QCOMPARE(from.azimuthTo(to), expectedAzimuth);
+}
+
+void TestSceneCoordinate::azimuthTo_data()
+{
+ QTest::addColumn<SceneCoordinate>("to");
+ QTest::addColumn<qreal>("expectedAzimuth");
+
+ QTest::newRow("N") << SceneCoordinate(ORIGIN, ORIGIN - DELTA) << 0.0;
+ QTest::newRow("NE") << SceneCoordinate(ORIGIN + DELTA, ORIGIN - DELTA) << 45.0;
+ QTest::newRow("E") << SceneCoordinate(ORIGIN + DELTA, ORIGIN) << 90.0;
+ QTest::newRow("SE") << SceneCoordinate(ORIGIN + DELTA, ORIGIN + DELTA) << 135.0;
+ QTest::newRow("S") << SceneCoordinate(ORIGIN, ORIGIN + DELTA) << 180.0;
+ QTest::newRow("SW") << SceneCoordinate(ORIGIN - DELTA, ORIGIN + DELTA) << 225.0;
+ QTest::newRow("W") << SceneCoordinate(ORIGIN - DELTA, ORIGIN) << 270.0;
+ QTest::newRow("NW") << SceneCoordinate(ORIGIN - DELTA, ORIGIN - DELTA) << 315.0;
+}
+
void TestSceneCoordinate::constructors()
{
SceneCoordinate coordinate;