Merge branch 'master' into new_panels
authorPekka Nissinen <pekka.nissinen@ixonos.com>
Wed, 11 Aug 2010 11:49:16 +0000 (14:49 +0300)
committerPekka Nissinen <pekka.nissinen@ixonos.com>
Wed, 11 Aug 2010 11:49:16 +0000 (14:49 +0300)
Conflicts:
src/src.pro
src/ui/indicatorbutton.cpp
src/ui/mainwindow.cpp
src/ui/panelcommon.h

1  2 
src/src.pro
src/ui/indicatorbutton.cpp
src/ui/indicatorbutton.h
src/ui/mainwindow.cpp
src/ui/mainwindow.h
src/ui/panelcommon.h

diff --combined src/src.pro
@@@ -10,10 -10,7 +10,10 @@@ RESOURCES += ../images.qrc 
  TRANSLATIONS += ../res/languages/situare_fi.ts
  SOURCES += main.cpp \
      application.cpp \
 +    coordinates/geocoordinate.cpp \
 +    coordinates/scenecoordinate.cpp \
      engine/engine.cpp \
 +    engine/mce.cpp \
      facebookservice/facebookauthentication.cpp \
      facebookservice/facebookcredentials.cpp \
      gps/gpsposition.cpp \
@@@ -24,7 -21,6 +24,7 @@@
      map/gpslocationitem.cpp \
      map/mapengine.cpp \
      map/mapfetcher.cpp \
 +    map/maprouteitem.cpp \
      map/mapscene.cpp \
      map/mapscroller.cpp \
      map/maptile.cpp \
      network/networkcookiejar.cpp \
      network/networkhandler.cpp \
      network/networkreply.cpp \
 +    routing/geocodingservice.cpp \
 +    routing/location.cpp \
 +    routing/route.cpp \
 +    routing/routesegment.cpp \
 +    routing/routingservice.cpp \
      situareservice/imagefetcher.cpp \
      situareservice/situareservice.cpp \
      ui/updatelocation/texteditautoresizer.cpp \
      ui/avatarimage.cpp \
      ui/friendlistitem.cpp \
      ui/friendlistpanel.cpp \
 +    ui/fullscreenbutton.cpp \
      ui/imagebutton.cpp \
 +    ui/indicatorbutton.cpp \
++    ui/indicatorbuttonpanel.cpp \
      ui/logindialog.cpp \
      ui/mainwindow.cpp \
      ui/mapscale.cpp \
 -    ui/panelsidebar.cpp \
 -    ui/panelsliderbar.cpp \
      ui/settingsdialog.cpp \
 -    ui/sidepanel.cpp \
 -    ui/sidepanelbase.cpp \
      ui/userinfo.cpp \
      ui/userinfopanel.cpp \
      ui/zoombutton.cpp \
      ui/zoombuttonpanel.cpp \
 -    user/user.cpp \
 -    ui/fullscreenbutton.cpp \
 -    engine/mce.cpp \
 -    ui/indicatorbutton.cpp \
 -    routing/routingservice.cpp \
 -    routing/routesegment.cpp \
 -    routing/route.cpp \
 -    routing/location.cpp \
 -    map/maprouteitem.cpp \
 -    coordinates/scenecoordinate.cpp \
 -    coordinates/geocoordinate.cpp \
      ui/listview.cpp \
      ui/listitem.cpp \
      ui/listitemdelegate.cpp \
      ui/friendlistitemdelegate.cpp \
      ui/searchdialog.cpp \
 -    ui/indicatorbuttonpanel.cpp\
 -    routing/geocodingservice.cpp
 +    ui/paneltab.cpp \
 +    ui/tabbedpanel.cpp \
 +    ui/panelbar.cpp \
 +    ui/panelcontent.cpp \
 +    ui/panelbase.cpp \
 +    user/user.cpp
  HEADERS += application.h \
      common.h \
      engine/engine.h \
 +    error.h \
      facebookservice/facebookauthentication.h \
      facebookservice/facebookcommon.h \
      facebookservice/facebookcredentials.h \
      ui/mainwindow.h \
      ui/mapscale.h \
      ui/panelcommon.h \
      ui/settingsdialog.h \
      ui/userinfo.h \
      ui/userinfopanel.h \
 -    ui/sidepanel.h \
 -    ui/sidepanelbase.h \
      ui/zoombutton.h \
      ui/zoombuttonpanel.h \
      user/user.h \
      ui/fullscreenbutton.h \
      engine/mce.h \
      ui/indicatorbutton.h \
++    ui/indicatorbuttonpanel.h \
 +    routing/geocodingservice.h \
      routing/routingservice.h \
      routing/routingcommon.h \
      routing/routesegment.h \
      ui/friendlistitemdelegate.h \
      ui/listcommon.h \
      ui/searchdialog.h \
 -    ui/indicatorbuttonpanel.h\
 -    error.h \
 -    routing/geocodingservice.h
 +    ui/paneltab.h \
 +    ui/tabbedpanel.h \
 +    ui/panelbar.h \
 +    ui/panelcontent.h \
 +    ui/panelbase.h
  QT += network \
      webkit
  
@@@ -1,69 -1,59 +1,59 @@@
  /*
 -   Situare - A location system for Facebook
 -   Copyright (C) 2010  Ixonos Plc. Authors:
 -
 -       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
 -   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.
 +    Situare - A location system for Facebook
 +    Copyright (C) 2010  Ixonos Plc. Authors:
 +
 +        Kaj Wallin - kaj.wallin@ixonos.com
 +        Katri Kaikkonen - katri.kaikkonen@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
 +    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 "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));
  
      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);
  }
  
@@@ -102,173 -75,113 +75,113 @@@ IndicatorButton::~IndicatorButton(
      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;
-             if (newLocation.x() < 0)
-                 newLocation.rx() = 0;
-             else if (newLocation.x() > m_screenSize.width() - width() - PANEL_BAR_WIDTH)
-                 newLocation.rx() =  m_screenSize.width() - width() - PANEL_BAR_WIDTH;
-             if (newLocation.y() < 0)
-                 newLocation.ry() = 0;
-             else if (newLocation.y() > m_screenSize.height() - height())
-                 newLocation.ry() = m_screenSize.height() - height();
+     QToolButton::mouseMoveEvent(event);
  
-             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;
+     const int ROUNDING_RADIUS = 9;
  
-     if(m_screenSize.height() < 0)
-         oldHeight = DEFAULT_NON_FULLSCREEN_HEIGHT;
-     else
-         oldHeight = m_screenSize.height();
+     Q_UNUSED(event);
  
-     if(m_screenSize.width() < 0)
-         oldWidth = DEFAULT_SCREEN_WIDTH;
+     QPainterPath backgroundPath;
+     backgroundPath.addRoundedRect(this->rect(), ROUNDING_RADIUS, ROUNDING_RADIUS);
+     QPainter painter(this);
+     painter.setRenderHint(QPainter::Antialiasing);
+     if (isDown())
+         painter.fillPath(backgroundPath, QBrush(*m_selectedGradient));
      else
-         oldWidth = m_screenSize.width();
+         painter.fillPath(backgroundPath, QBrush(*m_normalColor));
  
-     m_screenSize = newSize;
+     const QPointF CENTER = QPointF(this->width(), this->height()) / 2;
  
-     QPoint resizedPosition = pos();
+     if (isChecked()) {
+         const QPointF offset = QPointF(m_indicatorLeds[ON].width(),
+                                        m_indicatorLeds[ON].height()) / 2;
  
-     if (resizedPosition.x() < 0)
-         resizedPosition.rx() = 0;
-     else if(resizedPosition.x() > (newSize.width() - rect().width()))
-         resizedPosition.rx() = newSize.width() - rect().width();
+         painter.drawPixmap(CENTER - offset, m_indicatorLeds[ON]);
+     } else {
+         const QPointF offset = QPointF(m_indicatorLeds[OFF].width(),
+                                        m_indicatorLeds[OFF].height()) / 2;
  
-     if (resizedPosition.y() < 0)
-         resizedPosition.ry() = 0;
-     else if(resizedPosition.y() > (newSize.height() - rect().height()))
-         resizedPosition.ry() = newSize.height() - rect().height();
+         painter.drawPixmap(CENTER - offset, m_indicatorLeds[OFF]);
+     }
  
-     if((pos().y() + rect().center().y()) > (oldHeight/2))
-         resizedPosition.ry() = newSize.height() - (oldHeight - pos().y());
+     // 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;
  
-     if((pos().x() + rect().center().x()) > (oldWidth/2))
-         resizedPosition.rx() = newSize.width() - (oldWidth - pos().x());
+         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)
+         };
  
-     move(resizedPosition);
- }
+         // base triangle is facing up, and needs to be rotated to the required direction
+         QTransform rotationTransform;
+         rotationTransform.rotate(m_direction);
  
- const QPoint& IndicatorButton::eventPosition()
- {
-     qDebug() << __PRETTY_FUNCTION__;
+         // 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());
  
-     return m_eventPosition;
- }
+         painter.setTransform(rotationTransform * translateTransform);
  
- void IndicatorButton::forceMouseRelease()
- {
-     qDebug() << __PRETTY_FUNCTION__;
+         // setting the look of the triangle
+         painter.setBrush(Qt::red);
+         painter.setPen(Qt::red);
  
-     releaseMouse();
-     setDraggable(false);
+         painter.drawPolygon(points, POINTS);
+     }
  }
  
- void IndicatorButton::paintEvent(QPaintEvent *event)
+ void IndicatorButton::setDirection(qreal direction, bool draw)
  {
      qDebug() << __PRETTY_FUNCTION__;
  
-     Q_UNUSED(event);
-     QPainterPath backgroundPath;
-     backgroundPath.addRoundedRect(this->rect(), ROUNDING_RADIUS, ROUNDING_RADIUS);
-     QPainter painter(this);
-     painter.setRenderHint(QPainter::Antialiasing);
-     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));
+     m_direction = direction;
+     m_drawTriangle = draw;
  
-     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]);
+     update();
  }
  
- void IndicatorButton::timerExpired()
- {
-     qDebug() << __PRETTY_FUNCTION__;
-     setDraggable(true, m_dragPosition);
- }
diff --combined src/ui/indicatorbutton.h
@@@ -2,8 -2,9 +2,9 @@@
      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 <QMouseEvent>
  #include <QTimer>
  #include <QToolButton>
 -#include <QWidget>
  
  /**
   * @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
  {
@@@ -56,14 -57,14 +56,14 @@@ public
   ******************************************************************************/
  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
       */
@@@ -94,27 -95,13 +94,13 @@@ public slots
      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
@@@ -127,16 -114,13 +113,13 @@@ 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
diff --combined src/ui/mainwindow.cpp
@@@ -4,9 -4,10 +4,10 @@@
  
        Henri Lampela - henri.lampela@ixonos.com
        Kaj Wallin - kaj.wallin@ixonos.com
 -      Jussi Laitinen jussi.laitinen@ixonos.com
 +      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 "panelcommon.h"
 +#include "tabbedpanel.h"
  #include "searchdialog.h"
  #include "settingsdialog.h"
  #include "userinfopanel.h"
  #include "zoombuttonpanel.h"
+ #include "indicatorbuttonpanel.h"
  
  #include "mainwindow.h"
  
  
  MainWindow::MainWindow(QWidget *parent)
      : QMainWindow(parent),
 -    m_errorShown(false),
 -    m_loggedIn(false),
 -    m_refresh(false),
 -    m_progressIndicatorCount(0),
 -    m_ownLocationCrosshair(0),
 -    m_email(),
 -    m_password(),
 -    m_webView(0),
 -    m_fullScreenButton(0),
 -    m_indicatorButtonPanel(0),
 -    m_mapScale(0),
 -    m_cookieJar(0)
 +      m_errorShown(false),
 +      m_loggedIn(false),
 +      m_refresh(false),
 +      m_progressIndicatorCount(0),
 +      m_ownLocationCrosshair(0),
 +      m_email(),
 +      m_password(),
 +      m_webView(0),
 +      m_fullScreenButton(0),
 +      m_indicatorButton(0),
 +      m_mapScale(0),
 +      m_cookieJar(0)
  {
      qDebug() << __PRETTY_FUNCTION__;
  
      setCentralWidget(new QWidget());
      centralWidget()->setLayout(layout);
  
 -    buildFriendListPanel();
 -    buildUserInfoPanel();
 +    buildPanels();
  
      createMenus();
      setWindowTitle(tr("Situare"));
  
      // set stacking order of widgets
 -    m_zoomButtonPanel->stackUnder(m_userPanel);
 +    m_zoomButtonPanel->stackUnder(m_tabbedPanel);
      if(m_fullScreenButton) {
          m_fullScreenButton->stackUnder(m_zoomButtonPanel);
          m_osmLicense->stackUnder(m_fullScreenButton);
@@@ -96,8 -96,8 +97,8 @@@
          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);
@@@ -156,12 -156,22 +157,12 @@@ void MainWindow::buildFriendListPanel(
  
      m_friendsListPanel = new FriendListPanel(this);
  
 -    m_friendsListPanelSidebar = new PanelSideBar(this, RIGHT);
 -
 -    m_friendsListPanel->stackUnder(m_friendsListPanelSidebar);
 -
      connect(this, SIGNAL(friendsLocationsReady(QList<User*>&)),
              m_friendsListPanel, SLOT(friendInfoReceived(QList<User*>&)));
  
      connect(this, SIGNAL(locationItemClicked(QList<QString>)),
              m_friendsListPanel, SLOT(showFriendsInList(QList<QString>)));
  
 -    connect(m_mapView, SIGNAL(viewResized(QSize)),
 -            m_friendsListPanel, SLOT(resizePanel(QSize)));
 -
 -    connect(m_mapView, SIGNAL(viewResized(QSize)),
 -            m_friendsListPanelSidebar, SLOT(resizeSideBar(QSize)));
 -
      connect(m_friendsListPanel, SIGNAL(findFriend(GeoCoordinate)),
              this, SIGNAL(findFriend(GeoCoordinate)));
  
              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()));
  }
  
@@@ -242,7 -255,7 +246,7 @@@ void MainWindow::buildMap(
      buildOsmLicense();
      buildManualLocationCrosshair();
      buildFullScreenButton();
-     buildIndicatorButton();
+     buildIndicatorButtonPanel();
      buildMapScale();
  
      connect(m_mapView, SIGNAL(viewScrolled(SceneCoordinate)),
@@@ -296,52 -309,45 +300,52 @@@ void MainWindow::buildOsmLicense(
              this, SLOT(drawOsmLicense(QSize)));
  }
  
 -void MainWindow::buildUserInfoPanel()
 +void MainWindow::buildPanels()
  {
      qDebug() << __PRETTY_FUNCTION__;
  
 -    m_userPanel = new UserInfoPanel(this);
 +    buildUserInfoPanel();
 +    buildFriendListPanel();
  
 -    m_userPanelSidebar = new PanelSideBar(this, LEFT);
 +    m_tabbedPanel = new TabbedPanel(this);
 +    m_tabbedPanel->addTab(m_userInfoPanel, QIcon(":/res/images/user_info.png"));
 +    m_tabbedPanel->addTab(m_friendsListPanel, QIcon(":/res/images/friend_list.png"));
  
 -    m_userPanelSidebar->stackUnder(m_friendsListPanel);
 -    m_userPanel->stackUnder(m_userPanelSidebar);
 +    connect(m_tabbedPanel, SIGNAL(panelOpened()),
 +            m_friendsListPanel, SLOT(clearFriendListFilter()));
 +
 +    connect(m_mapView, SIGNAL(viewResized(QSize)),
 +            m_tabbedPanel, SLOT(resizePanel(QSize)));
 +}
 +
 +void MainWindow::buildUserInfoPanel()
 +{
 +    qDebug() << __PRETTY_FUNCTION__;
 +
 +    m_userInfoPanel = new UserInfoPanel(this);
  
      connect(this, SIGNAL(userLocationReady(User*)),
 -            m_userPanel, SLOT(userDataReceived(User*)));
 +            m_userInfoPanel, SLOT(userDataReceived(User*)));
  
      connect(this, SIGNAL(reverseGeoReady(QString)),
 -            m_userPanel, SIGNAL(reverseGeoReady(QString)));
 +            m_userInfoPanel, SIGNAL(reverseGeoReady(QString)));
  
      connect(this, SIGNAL(clearUpdateLocationDialogData()),
 -            m_userPanel, SIGNAL(clearUpdateLocationDialogData()));
 -
 -    connect(m_mapView, SIGNAL(viewResized(QSize)),
 -            m_userPanel, SLOT(resizePanel(QSize)));
 +            m_userInfoPanel, SIGNAL(clearUpdateLocationDialogData()));
  
 -    connect(m_mapView, SIGNAL(viewResized(QSize)),
 -            m_userPanelSidebar, SLOT(resizeSideBar(QSize)));
 -
 -    connect(m_userPanel, SIGNAL(findUser(GeoCoordinate)),
 +    connect(m_userInfoPanel, SIGNAL(findUser(GeoCoordinate)),
              this, SIGNAL(findUser(GeoCoordinate)));
  
 -    connect(m_userPanel, SIGNAL(requestReverseGeo()),
 +    connect(m_userInfoPanel, SIGNAL(requestReverseGeo()),
              this, SIGNAL(requestReverseGeo()));
  
 -    connect(m_userPanel, SIGNAL(statusUpdate(QString,bool)),
 +    connect(m_userInfoPanel, SIGNAL(statusUpdate(QString,bool)),
              this, SIGNAL(statusUpdate(QString,bool)));
  
 -    connect(m_userPanel, SIGNAL(refreshUserData()),
 +    connect(m_userInfoPanel, SIGNAL(refreshUserData()),
              this, SIGNAL(refreshUserData()));
  
 -    connect(m_userPanel, SIGNAL(notificateUpdateFailing(QString, bool)),
 +    connect(m_userInfoPanel, SIGNAL(notificateUpdateFailing(QString, bool)),
              this, SLOT(buildInformationBox(QString, bool)));
  }
  
@@@ -498,9 -504,16 +502,9 @@@ void MainWindow::drawFullScreenButton(c
  {
      qDebug() << __PRETTY_FUNCTION__ << size.width() << "x" << size.height();
  
 -    if(m_fullScreenButton) {
 -        if(m_loggedIn) {
 -            m_fullScreenButton->move(size.width() - m_fullScreenButton->size().width()
 -                                     - PANEL_PEEK_AMOUNT,
 -                                     size.height() - m_fullScreenButton->size().height());
 -        } else {
 -            m_fullScreenButton->move(size.width() - m_fullScreenButton->size().width(),
 -                                     size.height() - m_fullScreenButton->size().height());
 -        }
 -    }
 +    if(m_fullScreenButton)
 +        m_fullScreenButton->move(size.width() - m_fullScreenButton->size().width(),
 +                                 size.height() - m_fullScreenButton->size().height());
  }
  
  void MainWindow::drawMapScale(const QSize &size)
  
      const int LEFT_SCALE_MARGIN = 10;
      const int BOTTOM_SCALE_MARGIN = 2;
 -    qDebug() << __PRETTY_FUNCTION__ << size.width() << "x" << size.height();
 +//    qDebug() << __PRETTY_FUNCTION__ << size.width() << "x" << size.height();
  
 -    m_mapScale->move(PANEL_PEEK_AMOUNT + LEFT_SCALE_MARGIN,
 +    m_mapScale->move(LEFT_SCALE_MARGIN,
                       size.height() - m_mapScale->size().height() - BOTTOM_SCALE_MARGIN);
  }
  
@@@ -520,7 -533,7 +524,7 @@@ void MainWindow::drawOsmLicense(const Q
      qDebug() << __PRETTY_FUNCTION__ << size.width() << "x" << size.height();
  
      m_osmLicense->move(size.width() - m_osmLicense->fontMetrics().width(OSM_LICENSE)
 -                       - PANEL_PEEK_AMOUNT,
 +                       - PANEL_BAR_WIDTH,
                         size.height() - m_osmLicense->fontMetrics().height());
  }
  
@@@ -801,8 -814,7 +805,7 @@@ void MainWindow::setIndicatorButtonEnab
  {
      qDebug() << __PRETTY_FUNCTION__;
  
-     m_indicatorButton->setChecked(enabled);
+     m_indicatorButtonPanel->setIndicatorButtonEnabled(enabled);
  }
  
  void MainWindow::setMapViewScene(QGraphicsScene *scene)
@@@ -900,17 -912,17 +903,17 @@@ void MainWindow::showPanels(
  
      drawFullScreenButton(m_viewPortSize);
  
 -    if(m_loggedIn) {
 -        if(!m_friendsListPanel->isVisible()) {
 -            m_friendsListPanel->show();
 -            m_friendsListPanelSidebar->show();
 -        }
 +//    if(m_loggedIn) {
 +//        if(!m_friendsListPanel->isVisible()) {
 +//            m_friendsListPanel->show();
 +//            m_friendsListPanelSidebar->show();
 +//        }
  
 -        if(!m_userPanel->isVisible()) {
 -            m_userPanel->show();
 -            m_userPanelSidebar->show();
 -        }
 -    }
 +//        if(!m_userPanel->isVisible()) {
 +//            m_userPanel->show();
 +//            m_userPanelSidebar->show();
 +//        }
 +//    }
  }
  
  void MainWindow::startLocationSearch()
@@@ -961,15 -973,14 +964,15 @@@ void MainWindow::updateItemVisibility(
  {
      qDebug() << __PRETTY_FUNCTION__;
  
 -    if(!m_loggedIn) {
 -        m_friendsListPanel->closePanel();
 -        m_friendsListPanel->hide();
 -        m_friendsListPanelSidebar->hide();
 -        m_userPanel->closePanel();
 -        m_userPanel->hide();
 -        m_userPanelSidebar->hide();
 -    }
 +//    if(!m_loggedIn) {
 +//        m_friendsListPanel->closePanel();
 +//        m_friendsListPanel->hide();
 +//        m_friendsListPanelSidebar->hide();
 +
 +//        m_userPanel->closePanel();
 +//        m_userPanel->hide();
 +//        m_userPanelSidebar->hide();
 +//    }
  }
  
  const QString MainWindow::username()
diff --combined src/ui/mainwindow.h
@@@ -4,7 -4,6 +4,7 @@@
  
          Henri Lampela - henri.lampela@ixonos.com
          Kaj Wallin - kaj.wallin@ixonos.com
 +        Jussi Laitinen - jussi.laitinen@ixonos.com
          Sami Rämö - sami.ramo@ixonos.com
          Katri Kaikkonen - katri.kaikkonen@ixonos.com
  
@@@ -30,6 -29,7 +30,6 @@@
  #include <QUrl>
  
  #include "network/networkcookiejar.h"
 -#include "panelsidebar.h"
  
  class QGraphicsScene;
  class QLabel;
@@@ -41,12 -41,11 +41,12 @@@ class QWebView
  class FacebookAuthentication;
  class FullScreenButton;
  class FriendListPanel;
- class IndicatorButton;
+ class IndicatorButtonPanel;
  class GeoCoordinate;
  class MapScale;
  class MapScene;
  class MapView;
 +class TabbedPanel;
  class SettingsDialog;
  class SceneCoordinate;
  class SituareService;
@@@ -54,6 -53,7 +54,6 @@@ class User
  class UserInfoPanel;
  class ZoomButtonPanel;
  
 -
  /**
  * @brief Main Window Class
  */
@@@ -152,9 -152,9 +152,9 @@@ public
  
  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.
@@@ -250,11 -250,6 +250,11 @@@ private
      void buildOsmLicense();
  
      /**
 +     * @brief Build application panels
 +     */
 +    void buildPanels();
 +
 +    /**
       * @brief Build user info panel and connect slots
       */
      void buildUserInfoPanel();
@@@ -429,6 -424,16 +429,16 @@@ signals
      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
@@@ -647,12 -652,13 +657,12 @@@ private
  
      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
 -    PanelSideBar *m_userPanelSidebar;       ///< User panel side bar
 -    PanelSideBar *m_friendsListPanelSidebar;///< Friends panel side bar
 -    UserInfoPanel *m_userPanel;             ///< Instance of the user information panel
 +    TabbedPanel *m_tabbedPanel;             ///< Widget for tabbed panels
 +    UserInfoPanel *m_userInfoPanel;         ///< Instance of the user information panel
      ZoomButtonPanel *m_zoomButtonPanel;     ///< Instance of zoom button panel
  };
  
diff --combined src/ui/panelcommon.h
@@@ -1,4 -1,4 +1,4 @@@
 - /*
 +/*
      Situare - A location system for Facebook
      Copyright (C) 2010  Ixonos Plc. Authors:
  
@@@ -19,7 -19,7 +19,7 @@@
      along with Situare; if not, write to the Free Software
      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
      USA.
 - */
 +*/
  
  #ifndef PANELCOMMON_H
  #define PANELCOMMON_H
@@@ -33,56 -33,99 +33,50 @@@ const int DRAG_INIT_TIME = 1000
  const int FORCE_RELEASE_TIME = 10000;   ///< How long mouse can be grabbed
  
  // Common panel settings
 -enum Side {LEFT, RIGHT};            ///< Enumerator for panel sideness
 -
  const int MAEMO5_SCROLLBAR_WIDTH = 8; ///< Width of the Maemo scrollbar
  
  const int PANEL_TOP_PADDING = 0;    ///< Amount of padding in top of panels
  const int PANEL_BOTTOM_PADDING = 0; ///< Amount of padding in bottom of panels
  
 -const int SIDEBAR_WIDTH = 23;                       ///< Width of the sidebar
 -const int SIDEBAR_HEIGHT = DEFAULT_SCREEN_HEIGHT - PANEL_TOP_PADDING
 -                           - PANEL_BOTTOM_PADDING;  ///< Height of the sidebar
 -
 -const int SLIDER_BAR_WIDTH = 5;                     ///< Width of the slider bar
 -const int SLIDER_BUTTON_OFFSET = 19;                ///< Slider bar button extrusion width
 -const int SLIDER_WIDTH = 43;                        ///< Width of the whole slider
 -const int SLIDER_HEIGHT = DEFAULT_SCREEN_HEIGHT - PANEL_TOP_PADDING
 -                          - PANEL_BOTTOM_PADDING;   ///< Height of the slider
 +const int PANEL_BAR_WIDTH = 5;                                          ///< Width of the slider bar
 +const int PANEL_TAB_WIDTH = 74;                                         ///< Panel tab (maximum) width
 +const int PANEL_BAR_TABBED_WIDTH = PANEL_BAR_WIDTH + PANEL_TAB_WIDTH;   ///< Width of the tabbed bar
 +const int PANEL_WIDTH  = 384;                                           ///< Width of the panel
 +const int PANEL_HEIGHT = DEFAULT_SCREEN_HEIGHT - PANEL_TOP_PADDING
 +                         - PANEL_BOTTOM_PADDING;                        ///< Height of the panel
  
 -// Friend list panel settings
 -const int FRIENDPANEL_WIDTH  = 426;                     ///< Width of the friends list panel
 -const int FRIENDPANEL_HEIGHT = DEFAULT_SCREEN_HEIGHT - PANEL_TOP_PADDING
 -                               - PANEL_BOTTOM_PADDING;  ///< Height of the friends list panel
 -
 -/**
 - * @brief Friend list panel inner margin (left)
 - *
 - * @var FRIENDPANEL_MARGIN_LEFT
 - */
 -const int FRIENDPANEL_MARGIN_LEFT = SLIDER_BUTTON_OFFSET
 -                                    + MAEMO5_SCROLLBAR_WIDTH;
 -const int FRIENDPANEL_MARGIN_RIGHT = SIDEBAR_WIDTH;     ///< Friend list panel inner margin (right)
 -const int FRIENDPANEL_MARGIN_TOP = 0;                   ///< Friend list panel inner margin (top)
 -const int FRIENDPANEL_MARGIN_BOTTOM = 0;                ///< Friend list panel inner margin (bottom)
 +const int PANEL_MARGIN_LEFT = MAEMO5_SCROLLBAR_WIDTH; ///< Panel inner margin (left)
 +const int PANEL_MARGIN_RIGHT = 0;                     ///< Panel inner margin (right)
 +const int PANEL_MARGIN_TOP = 0;                       ///< Panel inner margin (top)
 +const int PANEL_MARGIN_BOTTOM = 0;                    ///< Panel inner margin (bottom)
  
  /**
   * @brief Friend list filter bar margin (left)
   *
   * @var FRIENDPANEL_FILTER_MARGIN_LEFT
   */
 -const int FRIENDPANEL_FILTER_MARGIN_LEFT = FRIENDPANEL_MARGIN_LEFT + 4;
 +const int FRIENDPANEL_FILTER_MARGIN_LEFT = PANEL_MARGIN_LEFT + 4;
  
  /**
   * @brief Friend list filter bar margin (right)
   *
   * @var FRIENDPANEL_FILTER_MARGIN_RIGHT
   */
 -const int FRIENDPANEL_FILTER_MARGIN_RIGHT = FRIENDPANEL_MARGIN_RIGHT
 -                                            + MAEMO5_SCROLLBAR_WIDTH + 4;
 +const int FRIENDPANEL_FILTER_MARGIN_RIGHT = PANEL_MARGIN_RIGHT + MAEMO5_SCROLLBAR_WIDTH + 4;
  
 -const int SHOW_ALL_BUTTON_RIGHT_MARGIN = SIDEBAR_WIDTH * 2 - 7; ///< Show all button right margin
 +const int SHOW_ALL_BUTTON_RIGHT_MARGIN = 39; ///< Show all button right margin
  
 -/**
 - * @brief Horizontal position of a closed friend list panel
 - *
 - * @var FRIENDPANEL_CLOSED_X
 - */
 -const int FRIENDPANEL_CLOSED_X = DEFAULT_SCREEN_WIDTH - SLIDER_BUTTON_OFFSET
 -                                 - PANEL_PEEK_AMOUNT;
 +const int PANEL_CLOSED_X = DEFAULT_SCREEN_WIDTH - PANEL_TAB_WIDTH
 +                                 - PANEL_BAR_WIDTH; ///< Horizontal position of a closed panel
  
 -/**
 - * @brief Horizontal position of a open friend list panel
 - *
 - * @var FRIENDPANEL_OPENED_X
 - */
 -const int FRIENDPANEL_OPENED_X = DEFAULT_SCREEN_WIDTH - SLIDER_BUTTON_OFFSET - SLIDER_BAR_WIDTH
 -                                 - FRIENDPANEL_WIDTH;
 -
 -// User info panel settings
 -const int USERPANEL_WIDTH  = 298;                       ///< Width of the user panel
 -const int USERPANEL_HEIGHT = DEFAULT_SCREEN_HEIGHT - PANEL_TOP_PADDING
 -                             - PANEL_BOTTOM_PADDING;    ///< Height of the user panel
 -
 -const int USERPANEL_MARGIN_LEFT = SIDEBAR_WIDTH
 -                                  + MAEMO5_SCROLLBAR_WIDTH; ///< User info panel inner margin (left)
 -const int USERPANEL_MARGIN_RIGHT = SLIDER_BUTTON_OFFSET;    ///< User info panel inner margin (right)
 -const int USERPANEL_MARGIN_TOP = 0;                         ///< User info panel inner margin (top)
 -const int USERPANEL_MARGIN_BOTTOM = 0;                      ///< User info panel inner margin (bottom)
 -
 -/**
 - * @brief Horizontal position of a closed user info panel
 - *
 - * @var USERPANEL_CLOSED_X
 - */
 -const int USERPANEL_CLOSED_X = - USERPANEL_WIDTH + PANEL_PEEK_AMOUNT
 -                               - SLIDER_BAR_WIDTH;
 -const int USERPANEL_OPENED_X = 0;                 ///< Horizontal position of a open user info panel
 +const int PANEL_OPENED_X = DEFAULT_SCREEN_WIDTH - PANEL_TAB_WIDTH - PANEL_BAR_WIDTH
 +                                 - PANEL_WIDTH;     ///< Horizontal position of a open panel
  
  // 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_X = 10; ///< 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 QString ZOOMPANEL_POSITION = "Zoom_Panel_Position";
  
- // Direction indicator button settings
- const int DIRECTION_INDICATOR_POSITION_X = 10; ///< Horizontal position of direction indicator button
- 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