Merge branch 'master' of https://vcs.maemo.org/git/situare
authorKatri Kaikkonen <katri.kaikkonen@ixonos.com>
Fri, 3 Sep 2010 13:10:19 +0000 (16:10 +0300)
committerKatri Kaikkonen <katri.kaikkonen@ixonos.com>
Fri, 3 Sep 2010 13:10:19 +0000 (16:10 +0300)
49 files changed:
debian/control
doc/testing/functionality-tests.doc
images.qrc
res/images/clear_btn.png [new file with mode: 0644]
res/images/clear_btn_d.png [new file with mode: 0644]
res/images/clear_btn_s.png [new file with mode: 0644]
res/images/contact_btn.png [new file with mode: 0644]
res/images/contact_btn_d.png [new file with mode: 0644]
res/images/contact_btn_s.png [new file with mode: 0644]
res/images/list_item_context_button_bar_left.png [new file with mode: 0644]
res/images/list_item_context_button_bar_right.png [new file with mode: 0644]
res/images/list_item_context_button_bar_tile.png [new file with mode: 0644]
res/images/search_history.png [new file with mode: 0644]
src/engine/contactmanager.cpp [new file with mode: 0644]
src/engine/contactmanager.h [new file with mode: 0644]
src/engine/contactmanagerprivate.cpp [new file with mode: 0644]
src/engine/contactmanagerprivate.h [new file with mode: 0644]
src/engine/contactmanagerprivatestub.cpp [new file with mode: 0644]
src/engine/contactmanagerprivatestub.h [new file with mode: 0644]
src/engine/engine.cpp
src/engine/engine.h
src/src.pro
src/ui/extendedlistitem.cpp
src/ui/friendlistitem.cpp
src/ui/friendlistitem.h
src/ui/friendlistpanel.cpp
src/ui/friendlistpanel.h
src/ui/listitemcontextbuttonbar.cpp [new file with mode: 0644]
src/ui/listitemcontextbuttonbar.h [new file with mode: 0644]
src/ui/listview.cpp
src/ui/listview.h
src/ui/locationsearchpanel.cpp
src/ui/locationsearchpanel.h
src/ui/mainwindow.cpp
src/ui/mainwindow.h
src/ui/ossoabookdialog.cpp [new file with mode: 0644]
src/ui/ossoabookdialog.h [new file with mode: 0644]
src/ui/panelbase.cpp
src/ui/panelbase.h
src/ui/panelcommon.h
src/ui/routingpanel.cpp
src/ui/searchhistorylistitem.cpp [new file with mode: 0644]
src/ui/searchhistorylistitem.h [new file with mode: 0644]
src/ui/searchhistorylistview.cpp [new file with mode: 0644]
src/ui/searchhistorylistview.h [new file with mode: 0644]
src/ui/tabbedpanel.cpp
src/ui/tabbedpanel.h
src/ui/userinfopanel.cpp
tests/ui/tabbedpanel/tabbedpanel.pro

index a3082b5..0c29275 100644 (file)
@@ -2,7 +2,7 @@ Source: situare
 Section: user/navigation
 Priority: optional
 Maintainer: Jussi Laitinen <jussi.laitinen@ixonos.com>
-Build-Depends: debhelper, libdbus-1-dev, icd2-dev, libx11-dev, libqt4-dev, libqjson-dev, liblocation-dev, libqtm-dev, libgconf2-dev
+Build-Depends: debhelper, libdbus-1-dev, icd2-dev, libx11-dev, libqt4-dev, libqjson-dev, liblocation-dev, libqtm-dev, libgconf2-dev, libosso-abook-dev
 Standards-Version: 3.7.2
 
 Package: situare
@@ -17,7 +17,7 @@ Description: Locate and share your position with friends.
  Check also http://www.situare.net.
 XSBC-Bugtracker: https://garage.maemo.org/tracker/?atid=5192&group_id=1420&func=browse
 XB-Maemo-Display-Name: Situare
-XB-Maemo-Upgrade-Description: Alpha release
+XB-Maemo-Upgrade-Description: Beta release
 XB-Maemo-Icon-26:
  iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAA3X
  AAAN1wFCKJt4AAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNn
index e5d9a8d..d9b00b0 100644 (file)
Binary files a/doc/testing/functionality-tests.doc and b/doc/testing/functionality-tests.doc differ
index 400684d..3dc6593 100644 (file)
         <file>res/images/zoom_in.png</file>
         <file>res/images/zoom_out.png</file>
         <file>res/images/location_search.png</file>
+        <file>res/images/list_item_context_button_bar_left.png</file>
+        <file>res/images/list_item_context_button_bar_right.png</file>
+        <file>res/images/list_item_context_button_bar_tile.png</file>
+        <file>res/images/search_history.png</file>
+        <file>res/images/clear_btn_d.png</file>
+        <file>res/images/clear_btn_s.png</file>
+        <file>res/images/clear_btn.png</file>
+        <file>res/images/contact_btn.png</file>
+        <file>res/images/contact_btn_d.png</file>
+        <file>res/images/contact_btn_s.png</file>
     </qresource>
 </RCC>
diff --git a/res/images/clear_btn.png b/res/images/clear_btn.png
new file mode 100644 (file)
index 0000000..6edb20d
Binary files /dev/null and b/res/images/clear_btn.png differ
diff --git a/res/images/clear_btn_d.png b/res/images/clear_btn_d.png
new file mode 100644 (file)
index 0000000..be1c3cd
Binary files /dev/null and b/res/images/clear_btn_d.png differ
diff --git a/res/images/clear_btn_s.png b/res/images/clear_btn_s.png
new file mode 100644 (file)
index 0000000..e237238
Binary files /dev/null and b/res/images/clear_btn_s.png differ
diff --git a/res/images/contact_btn.png b/res/images/contact_btn.png
new file mode 100644 (file)
index 0000000..026212c
Binary files /dev/null and b/res/images/contact_btn.png differ
diff --git a/res/images/contact_btn_d.png b/res/images/contact_btn_d.png
new file mode 100644 (file)
index 0000000..1ee74b2
Binary files /dev/null and b/res/images/contact_btn_d.png differ
diff --git a/res/images/contact_btn_s.png b/res/images/contact_btn_s.png
new file mode 100644 (file)
index 0000000..5738d33
Binary files /dev/null and b/res/images/contact_btn_s.png differ
diff --git a/res/images/list_item_context_button_bar_left.png b/res/images/list_item_context_button_bar_left.png
new file mode 100644 (file)
index 0000000..4eb44c1
Binary files /dev/null and b/res/images/list_item_context_button_bar_left.png differ
diff --git a/res/images/list_item_context_button_bar_right.png b/res/images/list_item_context_button_bar_right.png
new file mode 100644 (file)
index 0000000..3eb816b
Binary files /dev/null and b/res/images/list_item_context_button_bar_right.png differ
diff --git a/res/images/list_item_context_button_bar_tile.png b/res/images/list_item_context_button_bar_tile.png
new file mode 100644 (file)
index 0000000..2bf223b
Binary files /dev/null and b/res/images/list_item_context_button_bar_tile.png differ
diff --git a/res/images/search_history.png b/res/images/search_history.png
new file mode 100644 (file)
index 0000000..d96d329
Binary files /dev/null and b/res/images/search_history.png differ
diff --git a/src/engine/contactmanager.cpp b/src/engine/contactmanager.cpp
new file mode 100644 (file)
index 0000000..0e39bf3
--- /dev/null
@@ -0,0 +1,32 @@
+#include <QDebug>
+
+#if defined(Q_WS_MAEMO_5) & defined(ARMEL)
+#include "contactmanagerprivate.h"
+#else
+#include "contactmanagerprivatestub.h"
+#endif
+
+#include "contactmanager.h"
+
+ContactManager::ContactManager(QObject *parent)
+    : QObject(parent),
+      m_contactManagerPrivate(0)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_contactManagerPrivate = new ContactManagerPrivate(this);
+}
+
+QString ContactManager::contactGuid(const QString &facebookId) const
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    return m_contactManagerPrivate->contactGuid(facebookId);
+}
+
+void ContactManager::requestContactGuids()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_contactManagerPrivate->requestContactGuids();
+}
diff --git a/src/engine/contactmanager.h b/src/engine/contactmanager.h
new file mode 100644 (file)
index 0000000..97c1c96
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef CONTACTMANAGER_H
+#define CONTACTMANAGER_H
+
+#include <QObject>
+#include <QHash>
+
+class ContactManagerPrivate;
+
+/**
+* @brief Manages phone address book contacts.
+*/
+class ContactManager : public QObject
+{
+    Q_OBJECT
+public:
+    /**
+    * @brief Constructor
+    *
+    * @param parent QObject
+    */
+    ContactManager(QObject *parent = 0);
+
+/*******************************************************************************
+* MEMBER FUNCTIONS AND SLOTS
+******************************************************************************/
+    /**
+    * @brief Returns contact's guid from contact's facebook ID.
+    *
+    * @param facebookId contact's facebook ID
+    * @return contact guid
+    */
+    QString contactGuid(const QString &facebookId) const;
+
+    /**
+    * @brief Requests contact guids.
+    *
+    * Guid is a globally unique ID of a contact, which can be used with
+    * other datastores.
+    */
+    void requestContactGuids();
+
+/******************************************************************************
+* DATA MEMBERS
+******************************************************************************/
+private:
+    ContactManagerPrivate *m_contactManagerPrivate; ///< ContactManagerPrivate
+};
+
+#endif // CONTACTMANAGER_H
diff --git a/src/engine/contactmanagerprivate.cpp b/src/engine/contactmanagerprivate.cpp
new file mode 100644 (file)
index 0000000..96ac732
--- /dev/null
@@ -0,0 +1,82 @@
+#include <QContact>
+#include <QContactGuid>
+#include <QContactManager>
+#include <QContactOnlineAccount>
+#include <QDebug>
+#include <QHash>
+#include <QList>
+#include <QStringList>
+
+#include "contactmanager.h"
+
+#include "contactmanagerprivate.h"
+
+QTM_USE_NAMESPACE
+
+ContactManagerPrivate::ContactManagerPrivate(QObject *parent)
+    : QObject(parent),
+      m_manager(0)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    const QString MAEMO5_MANAGER_NAME = "maemo5";
+
+    QStringList availableManagers = QContactManager::availableManagers();
+
+    if (availableManagers.contains(MAEMO5_MANAGER_NAME)) {
+        QMap<QString, QString> params;
+        QString managerUri = QContactManager::buildUri(MAEMO5_MANAGER_NAME, params);
+        m_manager = QContactManager::fromUri(managerUri);
+    }
+}
+
+QString ContactManagerPrivate::parseFacebookId(const QString &accountUri) const
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    const QString FACEBOOK_CHAT_URL = "@chat.facebook.com";
+    int facebookChatUrlIndex = accountUri.indexOf(FACEBOOK_CHAT_URL);
+    QString facebookId;
+
+    if (facebookChatUrlIndex != -1) {
+        facebookId = accountUri.left(facebookChatUrlIndex);
+        facebookId.remove("-");
+    }
+
+    return facebookId;
+}
+
+QString ContactManagerPrivate::contactGuid(const QString &facebookId) const
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (!m_manager) {
+        qWarning() << "Manager is uninitialized";
+        return QString();
+    }
+
+    return m_contactGuids.value(facebookId);
+}
+
+void ContactManagerPrivate::requestContactGuids()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (!m_manager) {
+        qWarning() << "Manager is uninitialized";
+        return;
+    }
+
+    QHash<QString, QString> contactGuids;
+
+    foreach (QContact contact, m_manager->contacts()) {
+        QContactOnlineAccount account = contact.detail(QContactOnlineAccount::DefinitionName);
+        QString facebookId = parseFacebookId(account.accountUri());
+        QContactGuid contactGuid = contact.detail(QContactGuid::DefinitionName);
+
+        if (!facebookId.isEmpty())
+            contactGuids.insert(facebookId, contactGuid.guid());
+    }
+
+    m_contactGuids = contactGuids;
+}
diff --git a/src/engine/contactmanagerprivate.h b/src/engine/contactmanagerprivate.h
new file mode 100644 (file)
index 0000000..44f35d4
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef CONTACTMANAGERPRIVATE_H
+#define CONTACTMANAGERPRIVATE_H
+
+#include <QObject>
+
+#include <QContactManager>
+
+class ContactManager;
+
+QTM_USE_NAMESPACE
+
+/**
+* @brief Manages phone address book contacts.
+*/
+class ContactManagerPrivate : public QObject
+{
+    Q_OBJECT
+
+public:
+    /**
+    * @brief Constructor
+    *
+    * @param parent QObject
+    */
+    ContactManagerPrivate(QObject *parent = 0);
+
+/*******************************************************************************
+* MEMBER FUNCTIONS AND SLOTS
+******************************************************************************/
+public:
+    /**
+    * @brief Returns contact's guid from contact's facebook ID.
+    *
+    * @param facebookId contact's facebook ID
+    * @return contact guid
+    */
+    QString contactGuid(const QString &facebookId) const;
+
+    /**
+    * @brief Requests contact guids.
+    *
+    * Guid is a globally unique ID of a contact, which can be used with
+    * other datastores.
+    */
+    void requestContactGuids();
+
+private:
+    /**
+    * @brief Parses Facebook id from account URI.
+    *
+    * @param accountUri Accounts universal resource identifier.
+    * @return Facebook ID or empty if cannot parse the ID.
+    */
+    QString parseFacebookId(const QString &accountUri) const;
+
+/******************************************************************************
+* DATA MEMBERS
+******************************************************************************/
+private:
+    QContactManager *m_manager;             ///< Contact manager
+    QHash<QString, QString> m_contactGuids; ///< List of contact GUIDS
+};
+
+#endif // CONTACTMANAGERPRIVATE_H
diff --git a/src/engine/contactmanagerprivatestub.cpp b/src/engine/contactmanagerprivatestub.cpp
new file mode 100644 (file)
index 0000000..df142d2
--- /dev/null
@@ -0,0 +1,23 @@
+#include <QDebug>
+
+#include "contactmanagerprivatestub.h"
+
+ContactManagerPrivate::ContactManagerPrivate(QObject *parent) :
+    QObject(parent)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+}
+
+void ContactManagerPrivate::requestContactGuids()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+}
+
+QString ContactManagerPrivate::contactGuid(const QString &facebookId) const
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    Q_UNUSED(facebookId);
+
+    return QString();
+}
diff --git a/src/engine/contactmanagerprivatestub.h b/src/engine/contactmanagerprivatestub.h
new file mode 100644 (file)
index 0000000..191912c
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef CONTACTMANAGERPRIVATESTUB_H
+#define CONTACTMANAGERPRIVATESTUB_H
+
+#include <QObject>
+
+/**
+* @brief Manages phone address book contacts.
+*
+* STUB CLASS.
+*/
+class ContactManagerPrivate : public QObject
+{
+    Q_OBJECT
+public:
+    /**
+    * @brief Constructor
+    *
+    * @param parent QObject
+    */
+    ContactManagerPrivate(QObject *parent = 0);
+
+/*******************************************************************************
+* MEMBER FUNCTIONS AND SLOTS
+******************************************************************************/
+    /**
+    * @brief Returns contact's guid from contact's facebook ID.
+    *
+    * RETURNS empty QString.
+    *
+    * @param facebookId contact's facebook ID
+    * @return contact guid
+    */
+    QString contactGuid(const QString &facebookId) const;
+
+    /**
+    * @brief Requests contact guids.
+    *
+    * Guid is a globally unique ID of a contact, which can be used with
+    * other datastores.
+    *
+    * DOES NOTHING.
+    */
+    void requestContactGuids();
+};
+
+#endif // CONTACTMANAGERPRIVATESTUB_H
index 2883a50..d94ebfd 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "application.h"
 #include "common.h"
+#include "contactmanager.h"
 #include "../error.h"
 #include "facebookservice/facebookauthentication.h"
 #include "gps/gpsposition.h"
@@ -132,6 +133,9 @@ SituareEngine::SituareEngine()
 
     m_mce = new MCE(this);
     connect(m_mce, SIGNAL(displayOff(bool)), this, SLOT(setPowerSaving(bool)));
+    
+    m_contactManager = new ContactManager(this);
+    m_contactManager->requestContactGuids();
 }
 
 SituareEngine::~SituareEngine()
@@ -567,6 +571,19 @@ void SituareEngine::setPowerSaving(bool enabled)
         m_mapEngine->setAutoCentering(!enabled);
 }
 
+void SituareEngine::showContactDialog(const QString &facebookId)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    QString guid = m_contactManager->contactGuid(facebookId);
+
+    if (!guid.isEmpty())
+        m_ui->showContactDialog(guid);
+    else
+        m_ui->buildInformationBox(tr("Unable to find contact.\nYou must have Facebook "
+                                     "chat account to be able to open contact dialog."), true);
+}
+
 void SituareEngine::signalsFromFacebookAuthenticator()
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -685,6 +702,9 @@ void SituareEngine::signalsFromMainWindow()
             m_mapEngine,
             SLOT(showMapArea(const GeoCoordinate&, const GeoCoordinate&)));
 
+    connect(m_ui, SIGNAL(searchHistoryItemClicked(QString)),
+            this, SLOT(locationSearch(QString)));
+
     // signals from routing tab
     connect(m_ui, SIGNAL(clearRoute()),
             m_mapEngine, SLOT(clearRoute()));
@@ -702,6 +722,10 @@ void SituareEngine::signalsFromMainWindow()
     // signal from search location dialog
     connect(m_ui, SIGNAL(searchForLocation(QString)),
             this, SLOT(locationSearch(QString)));
+
+    // signal from friend list panel
+    connect(m_ui, SIGNAL(requestContactDialog(const QString &)),
+            this, SLOT(showContactDialog(const QString &)));
 }
 
 void SituareEngine::signalsFromMapEngine()
index 422e2f1..aacd9e5 100644 (file)
@@ -34,6 +34,7 @@
 class QTimer;
 
 class Application;
+class ContactManager;
 class FacebookAuthentication;
 class FacebookCredentials;
 class GeocodingService;
@@ -291,6 +292,14 @@ private slots:
     void setPowerSaving(bool enabled);
 
     /**
+    * @brief Shows contact dialog.
+    *
+    * Calls MainWindow showContactDialog with contact guid defined by contact's Facebook ID.
+    * @param facebookId contact's facebookId
+    */
+    void showContactDialog(const QString &facebookId);
+
+    /**
     * @brief Automatic update interval timer timeout.
     *
     * Requests update location if user has moved.
@@ -372,6 +381,7 @@ private:
 
     QTimer *m_automaticUpdateIntervalTimer; ///< Automatic update interval timer
 
+    ContactManager *m_contactManager;                ///< Instance of contact manager
     FacebookAuthentication *m_facebookAuthenticator; ///< Instance for facebook authenticator
     GeocodingService *m_geocodingService;            ///< Instance of the geocoding service
     GeoCoordinate m_lastUpdatedGPSPosition;          ///< Last updated GPS position
index 1cf0da4..8cc801c 100644 (file)
@@ -12,6 +12,7 @@ SOURCES += main.cpp \
     application.cpp \
     coordinates/geocoordinate.cpp \
     coordinates/scenecoordinate.cpp \
+    engine/contactmanager.cpp \
     engine/engine.cpp \
     engine/mce.cpp \
     facebookservice/facebookauthentication.cpp \
@@ -61,32 +62,36 @@ SOURCES += main.cpp \
     ui/locationlistitem.cpp \
     ui/locationlistview.cpp \
     ui/indicatorbuttonpanel.cpp \
+    ui/locationsearchpanel.cpp \
     ui/logindialog.cpp \
     ui/mainwindow.cpp \
     ui/mapscale.cpp \
-    ui/settingsdialog.cpp \
-    ui/userinfo.cpp \
-    ui/userinfopanel.cpp \
-    ui/zoombutton.cpp \
-    ui/zoombuttonpanel.cpp \
-    ui/searchdialog.cpp \
     ui/panelbar.cpp \
     ui/panelbase.cpp \
     ui/panelcontentstack.cpp \
     ui/panelcontextbuttonbar.cpp \
     ui/paneltab.cpp \
     ui/paneltabbar.cpp \
-    ui/tabbedpanel.cpp \
     ui/routingpanel.cpp \
     ui/routewaypointlistitem.cpp \
-    ui/routewaypointlistview.cpp \
+    ui/routewaypointlistview.cpp \    
+    ui/searchdialog.cpp \
+    ui/searchhistorylistitem.cpp \
+    ui/searchhistorylistview.cpp \
+    ui/settingsdialog.cpp \
+    ui/tabbedpanel.cpp \
+    ui/textmodifier.cpp \
+    ui/userinfo.cpp \
+    ui/userinfopanel.cpp \
+    ui/zoombutton.cpp \
+    ui/zoombuttonpanel.cpp \
     user/user.cpp \
-    ui/locationsearchpanel.cpp \
-    ui/textmodifier.cpp
+    ui/listitemcontextbuttonbar.cpp
 HEADERS += application.h \
     common.h \
     coordinates/geocoordinate.h \
     coordinates/scenecoordinate.h \
+    engine/contactmanager.h \
     engine/engine.h \
     engine/mce.h \
     error.h \
@@ -138,21 +143,16 @@ HEADERS += application.h \
     ui/imagebutton.h \
     ui/indicatorbutton.h \
     ui/indicatorbuttonpanel.h \
+    ui/listcommon.h \    
+    ui/listview.h \
+    ui/listitem.h \
+    ui/listitemdelegate.h \
     ui/logindialog.h \
     ui/locationlistitem.h \
     ui/locationlistview.h \
+    ui/locationsearchpanel.h \
     ui/mainwindow.h \
     ui/mapscale.h \
-    ui/settingsdialog.h \
-    ui/userinfo.h \
-    ui/userinfopanel.h \
-    ui/zoombutton.h \
-    ui/zoombuttonpanel.h \
-    ui/listcommon.h \    
-    ui/listview.h \
-    ui/listitem.h \
-    ui/listitemdelegate.h \
-    ui/searchdialog.h \
     ui/panelbar.h \
     ui/panelbase.h \
     ui/panelcommon.h \
@@ -160,13 +160,21 @@ HEADERS += application.h \
     ui/panelcontextbuttonbar.h \
     ui/paneltab.h \
     ui/paneltabbar.h \
-    ui/tabbedpanel.h \
     ui/routingpanel.h \
     ui/routewaypointlistitem.h \
     ui/routewaypointlistview.h \
+    ui/searchdialog.h \
+    ui/searchhistorylistitem.h \
+    ui/searchhistorylistview.h \
+    ui/settingsdialog.h \
+    ui/tabbedpanel.h \
+    ui/textmodifier.h \
+    ui/userinfo.h \
+    ui/userinfopanel.h \
+    ui/zoombutton.h \
+    ui/zoombuttonpanel.h \
     user/user.h \
-    ui/locationsearchpanel.h \
-    ui/textmodifier.h
+    ui/listitemcontextbuttonbar.h
 QT += network \
     webkit
 DEFINES += QT_NO_DEBUG_OUTPUT
@@ -196,8 +204,14 @@ simulator {
                    gps/liblocationwrapper.h \
                    gps/geopositioninfo.h
         CONFIG += link_pkgconfig
-        PKGCONFIG += glib-2.0 liblocation mce
+        PKGCONFIG += glib-2.0 liblocation mce gtk+-2.0 libosso-abook-1.0
         LIBS += -llocation
+        SOURCES += engine/contactmanagerprivate.cpp \
+                   ui/ossoabookdialog.cpp
+        HEADERS += engine/contactmanagerprivate.h \
+                   ui/ossoabookdialog.h
+        CONFIG += mobility
+        MOBILITY += contacts
     } else {
         SOURCES += gps/gpspositionprivatestub.cpp \
                    network/networkhandlerprivatestub.cpp \
@@ -205,6 +219,8 @@ simulator {
         HEADERS += gps/gpspositionprivatestub.h \
                    network/networkhandlerprivatestub.h \
                    engine/mceprivatestub.h
+        SOURCES += engine/contactmanagerprivatestub.cpp
+        HEADERS += engine/contactmanagerprivatestub.h
     }
 
     QT += maemo5
@@ -225,6 +241,8 @@ simulator {
     HEADERS += gps/gpspositionprivatestub.h \
                network/networkhandlerprivatestub.h \
                engine/mceprivatestub.h
+    SOURCES += engine/contactmanagerprivatestub.cpp
+    HEADERS += engine/contactmanagerprivatestub.h
     message(QJson built in)
     message(Make sure you have QJson development headers installed)
     message(install headers with: sudo apt-get install libqjson-dev)
index 1ecb362..79da1bd 100644 (file)
@@ -34,7 +34,7 @@ ExtendedListItem::ExtendedListItem()
     : m_selected(false),
       m_expandedHeight(ITEM_MIN_HEIGHT),
       m_normalHeight(ITEM_MIN_HEIGHT),
-      m_subItemTextWidth(0)
+      m_subItemTextWidth(SUBITEM_TEXT_MAX_WIDTH)
 
 {
     qDebug() << __PRETTY_FUNCTION__;
index 395b9c1..9a8c67a 100644 (file)
@@ -48,6 +48,11 @@ GeoCoordinate FriendListItem::coordinates() const
     return m_coordinates;
 }
 
+QString FriendListItem::facebookId() const
+{
+    return m_facebookId;
+}
+
 void FriendListItem::setAvatarImage(const QPixmap &image)
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -85,6 +90,13 @@ void FriendListItem::setDistanceIcon(double value, const QString &unit)
     setData(DISTANCE_IMAGE_INDEX, distanceImage);
 }
 
+
+void FriendListItem::setFacebookId(const QString &facebookId)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_facebookId = facebookId;
+}
 void FriendListItem::setUserData(User *user)
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -96,6 +108,8 @@ void FriendListItem::setUserData(User *user)
     setData(DISTANCE_TEXT_DISPLAY_INDEX, distanceText);
     setDistanceIcon(value, unit);
 
+    setFacebookId(user->userId());
+
     //Dummy value to get painter font metrics.
     QPixmap p = QPixmap(ICON_WIDTH, ICON_HEIGHT);
     QPainter painter(&p);
index ed16e4a..b1aa1a7 100644 (file)
@@ -60,6 +60,13 @@ public:
     GeoCoordinate coordinates() const;
 
     /**
+    * @brief Return's item's Facebook ID
+    *
+    * @return item's Facebook ID
+    */
+    QString facebookId() const;
+
+    /**
     * @brief Sets avatar image for this item.
     *
     * @param image image
@@ -91,10 +98,19 @@ private:
     */
     void setDistanceIcon(double value, const QString &unit);
 
+    /**
+    * @brief Sets item's Facebook ID
+    *
+    * @param facebookId item's Facebook ID
+    */
+    void setFacebookId(const QString &facebookId);
+
 /******************************************************************************
 * DATA MEMBERS
 ******************************************************************************/
 private:
+    QString m_facebookId;           ///< User's Facebook ID
+
     GeoCoordinate m_coordinates;    ///< User coordinates
 };
 
index 3dfd9e5..99a2585 100644 (file)
@@ -6,6 +6,7 @@
         Henri Lampela - henri.lampela@ixonos.com
         Pekka Nissinen - pekka.nissinen@ixonos.com
         Sami Rämö - sami.ramo@ixonos.com
+        Jussi Laitinen - jussi.laitinen@ixonos.com
 
     Situare is free software; you can redistribute it and/or
     modify it under the terms of the GNU General Public License
@@ -83,7 +84,7 @@ FriendListPanel::FriendListPanel(QWidget *parent)
             this, SIGNAL(findFriend(GeoCoordinate)));
 
     connect(m_friendListView, SIGNAL(listItemSelectionChanged()),
-            this, SLOT(setRouteButtonDisabled()));
+            this, SLOT(onListItemSelectionChanged()));
 
     // --- FOOTER, TEXT BASED FILTERING ---
     QHBoxLayout *footerLayout = new QHBoxLayout();
@@ -121,10 +122,15 @@ FriendListPanel::FriendListPanel(QWidget *parent)
     m_routeButton = new ImageButton(":res/images/route_to_friend.png",
                                     ":res/images/route_to_friend_s.png",
                                     ":res/images/route_to_friend_d.png", this);
-    m_routeButton->setDisabled(true);
     connect(m_routeButton, SIGNAL(clicked()),
             this, SLOT(routeToSelectedFriend()));
 
+    m_showContactButton = new ImageButton(":res/images/contact_btn.png",
+                                          ":res/images/contact_btn_s.png",
+                                          ":res/images/contact_btn_d.png", this);
+    connect(m_showContactButton, SIGNAL(clicked()),
+            this, SLOT(requestSelectedFriendContactDialog()));
+
     m_clearGroupFilteringButton = new ImageButton(":res/images/filtered.png",
                                                   ":res/images/filtered_s.png",
                                                   ":res/images/filtered_d.png", this);
@@ -133,8 +139,9 @@ FriendListPanel::FriendListPanel(QWidget *parent)
     connect(m_clearGroupFilteringButton, SIGNAL(clicked()),
             this, SLOT(clearFiltering()));
 
-    m_contextButtonLayout->addWidget(m_routeButton);
-    m_contextButtonLayout->addWidget(m_clearGroupFilteringButton);
+    m_itemButtonsLayout->addWidget(m_routeButton);
+    m_itemButtonsLayout->addWidget(m_showContactButton);
+    m_genericButtonsLayout->addWidget(m_clearGroupFilteringButton);
 }
 
 void FriendListPanel::anyPanelClosed()
@@ -147,7 +154,6 @@ void FriendListPanel::anyPanelClosed()
     clearFiltering();
 
     m_friendListView->clearItemSelection();
-    setRouteButtonDisabled();
 }
 
 void FriendListPanel::anyPanelOpened()
@@ -236,7 +242,19 @@ void FriendListPanel::hideEvent(QHideEvent *event)
     clearFiltering();
 
     m_friendListView->clearItemSelection();
-    setRouteButtonDisabled();
+}
+
+void FriendListPanel::requestSelectedFriendContactDialog()
+{
+     qDebug() << __PRETTY_FUNCTION__;
+
+     FriendListItem *item = dynamic_cast<FriendListItem *>(m_friendListView->selectedItem());
+
+     if (item) {
+         QString facebookId = item->facebookId();
+         if (!facebookId.isEmpty())
+             emit requestContactDialog(facebookId);
+     }
 }
 
 void FriendListPanel::routeToSelectedFriend()
@@ -270,13 +288,6 @@ void FriendListPanel::updateKeyboardGrabbing()
     }
 }
 
-void FriendListPanel::setRouteButtonDisabled()
-{
-    qDebug() << __PRETTY_FUNCTION__;
-
-    m_routeButton->setDisabled(m_friendListView->selectedItems().isEmpty());
-}
-
 void FriendListPanel::showEvent(QShowEvent *event)
 {
     qDebug() << __PRETTY_FUNCTION__;
index a781517..43362a1 100644 (file)
@@ -162,18 +162,16 @@ private slots:
     void filterTextChanged(const QString &text);
 
     /**
-    * @brief Routes to selected friend.
-    *
-    * Emits routeToFriend if friend is selected from list.
+    * @brief Requests selected friend's contact dialog.
     */
-    void routeToSelectedFriend();
+    void requestSelectedFriendContactDialog();
 
     /**
-    * @brief Sets route button disabled.
+    * @brief Routes to selected friend.
     *
-    * Disabled if there isn't any list item selected.
+    * Emits routeToFriend if friend is selected from list.
     */
-    void setRouteButtonDisabled();
+    void routeToSelectedFriend();
 
     /**
      * @brief Slot to show friends in list.
@@ -204,6 +202,13 @@ signals:
     void findFriend(const GeoCoordinate &coordinates);
 
     /**
+    * @brief Requests contact dialog.
+    *
+    * @param facebookId contact's facebookId
+    */
+    void requestContactDialog(const QString &facebookId);
+
+    /**
     * @brief Signal for routing to friend.
     *
     * @param coordinates friend's geo coordinates
@@ -227,6 +232,7 @@ private:
 
     FriendListView *m_friendListView;           ///< Friend list view
     ImageButton *m_clearGroupFilteringButton;   ///< Button for clearing friend group filtering
+    ImageButton *m_showContactButton;           ///< Button for showing contact dialog    
     ImageButton *m_routeButton;                 ///< Button for routing to selected friend
 };
 
diff --git a/src/ui/listitemcontextbuttonbar.cpp b/src/ui/listitemcontextbuttonbar.cpp
new file mode 100644 (file)
index 0000000..d7b6551
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+    Situare - A location system for Facebook
+    Copyright (C) 2010  Ixonos Plc. Authors:
+
+        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 <QLayout>
+#include <QPainter>
+#include <QPropertyAnimation>
+#include <QStateMachine>
+
+#include "panelcommon.h"
+
+#include "listitemcontextbuttonbar.h"
+
+ListItemContextButtonBar::ListItemContextButtonBar(QWidget *parent) :
+    QWidget(parent),
+    m_waitForOpen(false),
+    m_contextButtons(0),
+    m_newContextButtons(0),
+    m_state(StateHidden)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    // --- BAR LOOK ---
+    const int BAR_HEIGHT = 78;
+    setFixedHeight(BAR_HEIGHT);
+
+    m_backgroundLeft = new QPixmap(":/res/images/list_item_context_button_bar_left.png");
+    m_backgroundMiddle = new QPixmap(":/res/images/list_item_context_button_bar_tile.png");
+    m_backgroundRight = new QPixmap(":/res/images/list_item_context_button_bar_right.png");
+
+    // --- ANIMATION ---
+    const int ANIMATION_DURATION_MS = 150;
+
+    m_animation = new QPropertyAnimation(this, "pos", this);
+    m_animation->setDuration(ANIMATION_DURATION_MS);
+
+    connect(m_animation, SIGNAL(finished()),
+            this, SLOT(onAnimationFinished()));
+}
+
+ListItemContextButtonBar::~ListItemContextButtonBar()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (m_backgroundLeft)
+        delete m_backgroundLeft;
+
+    if (m_backgroundMiddle)
+        delete m_backgroundMiddle;
+
+    if (m_backgroundRight)
+        delete m_backgroundRight;
+}
+
+void ListItemContextButtonBar::changeButtons()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    Q_ASSERT(m_animation->state() == QAbstractAnimation::Stopped);
+
+    if (!isVisible())
+        show();
+
+    // Hide previous buttons (if any)
+    if (m_contextButtons)
+        m_contextButtons->setParent(0);
+
+    m_contextButtons = m_newContextButtons;
+    m_newContextButtons = 0;
+    m_contextButtons->setParent(this);
+    m_contextButtons->show();
+    setFixedWidth(m_contextButtons->width());
+
+    // center this widget horizontally to middle of the panel contents area and set outside of
+    // the view
+    const int FROM_PANEL_CONTENTS_LEFT = PANEL_WIDTH / 2 - m_contextButtons->width() / 2;
+    move(PANEL_TAB_BAR_WIDTH + PANEL_BAR_WIDTH + FROM_PANEL_CONTENTS_LEFT, -size().height());
+
+    // update new target values for animations
+    m_animation->setStartValue(pos());
+    const int Y = 0;
+    m_animation->setEndValue(QPoint(pos().x(), Y));
+}
+
+void ListItemContextButtonBar::hideContextButtonBar()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_state = StateClosing;
+    m_animation->setDirection(QAbstractAnimation::Backward);
+    m_animation->start();
+}
+
+void ListItemContextButtonBar::onAnimationFinished()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (m_animation->direction() == QAbstractAnimation::Backward) {
+        m_state = StateHidden;
+        if (m_newContextButtons) {
+            changeButtons();
+            if (m_waitForOpen) {
+                m_waitForOpen = false;
+                showContextButtonBar();
+            }
+        }
+    } else {
+        m_state = StateVisible;
+    }
+}
+
+void ListItemContextButtonBar::onListItemSelectionChanged(bool itemIsSelected)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (itemIsSelected) {
+        if (m_newContextButtons)
+            m_waitForOpen = true;
+        else if (m_state != StateVisible)
+            showContextButtonBar();
+    } else {
+        if (m_newContextButtons)
+            m_waitForOpen = false;
+        else if (m_state != StateHidden)
+            hideContextButtonBar();
+    }
+}
+
+void ListItemContextButtonBar::paintEvent(QPaintEvent *event)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    Q_UNUSED(event);
+
+    QPainter painter(this);
+
+    const int TOP = 0;
+    const int LEFT = 0;
+    painter.drawPixmap(TOP, LEFT, *m_backgroundLeft);
+    painter.drawTiledPixmap(m_backgroundLeft->width(), TOP,
+                            width() - m_backgroundLeft->width() - m_backgroundRight->width(),
+                            height(),
+                            *m_backgroundMiddle);
+    painter.drawPixmap(width() - m_backgroundRight->width(), TOP, *m_backgroundRight);
+}
+
+void ListItemContextButtonBar::setContextButtons(QWidget *contextButtons)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_newContextButtons = contextButtons;
+    m_waitForOpen = false;
+
+    if (m_state != StateHidden)
+        hideContextButtonBar();
+    else
+        changeButtons();
+}
+
+void ListItemContextButtonBar::showContextButtonBar()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (m_contextButtons->layout()->count() > 0) {
+        m_state = StateOpening;
+        m_animation->setDirection(QAbstractAnimation::Forward);
+        m_animation->start();
+    }
+}
diff --git a/src/ui/listitemcontextbuttonbar.h b/src/ui/listitemcontextbuttonbar.h
new file mode 100644 (file)
index 0000000..71be646
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+    Situare - A location system for Facebook
+    Copyright (C) 2010  Ixonos Plc. Authors:
+
+        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.
+*/
+
+#ifndef LISTITEMCONTEXTBUTTONBAR_H
+#define LISTITEMCONTEXTBUTTONBAR_H
+
+#include <QWidget>
+
+class QPropertyAnimation;
+
+/**
+ * @brief Button bar for list item relatex context buttons
+ *
+ * @author Sami Rämö - sami.ramo (at) ixonos.com
+ */
+class ListItemContextButtonBar : public QWidget
+{
+    Q_OBJECT
+public:
+    /**
+      * @brief Constructor
+      *
+      * @param parent Parent
+      */
+    explicit ListItemContextButtonBar(QWidget *parent = 0);
+
+    /**
+      * @brief Destructor
+      *
+      * Deletes images.
+      */
+    ~ListItemContextButtonBar();
+
+/*******************************************************************************
+ * BASE CLASS INHERITED AND REIMPLEMENTED MEMBER FUNCTIONS
+ ******************************************************************************/
+private:
+    /**
+      * @brief Paint the background of the item
+      *
+      * @param event Paint event
+      */
+    void paintEvent(QPaintEvent *event);
+
+/*******************************************************************************
+ * MEMBER FUNCTIONS AND SLOTS
+ ******************************************************************************/
+public:
+    /**
+      * @brief Start hiding animation
+      */
+    void hideContextButtonBar();
+
+    /**
+     * @brief Set new context buttons
+     *
+     * If bar is hidden, then changeButtons() is called. Otherwise pointer to new buttons is saved
+     * and hideContextButtonBar() is called.
+     *
+     * @param contextButtons Pointer to new context buttons
+     */
+    void setContextButtons(QWidget *contextButtons);
+
+    /**
+      * @brief Start showing animation
+      *
+      * Animation is started only if the bar contains buttons.
+      */
+    void showContextButtonBar();
+
+public slots:
+    /**
+      * @brief Shows and hides the bar when item selection is changed
+      *
+      * Calls showContextButtonBar() or hideContextButtonBar() if changing the state of the bar is
+      * required. If there is a pointer to new buttons, then request is remembered instead of
+      * changing the state immediately.
+      *
+      * @param itemIsSelected True is any item is selected
+      */
+    void onListItemSelectionChanged(bool itemIsSelected);
+
+private:
+    /**
+      * @brief Do the actual changing of the buttons
+      *
+      * Does also re-sizing and re-positioning of the bar and sets new values for animation.
+      */
+    void changeButtons();
+
+private slots:
+    /**
+      * @brief
+      *
+      * If bar was just hidden, then calls changeButtons() if there is a pointer to new buttons
+      * saved. If changing the buttons was done, then also checks if showing the bar was requested
+      * and calls showContextButtonBar() if needed.
+      */
+    void onAnimationFinished();
+
+/*******************************************************************************
+ * DATA MEMBERS
+ ******************************************************************************/
+private:
+    /**
+      * @brief States for the animation
+      *
+      * @enum AnimationState
+      */
+    enum AnimationState {
+        StateHidden,
+        StateOpening,
+        StateClosing,
+        StateVisible
+    };
+
+    bool m_waitForOpen;                 ///< Is showing requested while chaging buttons is not ready
+
+    QPixmap *m_backgroundLeft;          ///< Background picture, left part
+    QPixmap *m_backgroundMiddle;        ///< Background picture, center part
+    QPixmap *m_backgroundRight;         ///< Background picture, right part
+
+    QPropertyAnimation *m_animation;    ///< Sliding animation for show/hide
+
+    QWidget *m_contextButtons;          ///< Widget for context buttons
+    QWidget *m_newContextButtons;       ///< Temporary pointer for new context buttons
+
+    AnimationState m_state;             ///< Current state of the animation
+};
+
+#endif // LISTITEMCONTEXTBUTTONBAR_H
index fdcea75..c1e8617 100644 (file)
@@ -58,6 +58,8 @@ void ListView::addListItemToView(ListItem *item)
 
 void ListView::clearItemSelection()
 {
+    qDebug() << __PRETTY_FUNCTION__;
+
     clearSelection();
 
     if (m_currentItem)
@@ -206,20 +208,41 @@ ListItem *ListView::listItemAt(int index)
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    QHashIterator<QString, ListItem*> itemIterator(m_listItems);
-    ListItem *item = 0;
-    int counter = 0;
+    ListItem *listItem = 0;
 
-    while (itemIterator.hasNext()) {
-        itemIterator.next();
-        if (index == counter) {
-            item = itemIterator.value();
-            break;
-        }
-        counter++;
+    if (index < count())
+        listItem = dynamic_cast<ListItem*>(item(index));
+
+    return listItem;
+}
+
+void ListView::prependListItem(const QString &key, ListItem *item)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (!m_listItems.contains(key)) {
+        insertItem(0, item);
+        m_listItems.insert(key, item);
     }
+}
 
-    return item;
+void ListView::removeLastItem()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    ListItem *item = listItemAt(count() - 1);
+
+    if (item) {
+        if (item) {
+            QString key = m_listItems.key(item);
+            m_listItems.remove(key);
+            takeItem(row(item));
+            if (m_currentItem == item)
+                m_currentItem = 0;
+            delete item;
+            item = 0;
+        }
+    }
 }
 
 ListItem *ListView::selectedItem()
index 417c5d1..eaf32fb 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef LISTVIEW_H
 #define LISTVIEW_H
 
+#include <QHash>
 #include <QListWidget>
 
 class GeoCoordinate;
@@ -154,6 +155,19 @@ public:
     ListItem *listItemAt(int index);
 
     /**
+    * @brief Prepends item to view and item list.
+    *
+    * @param key user ID
+    * @param item item to prepend to view and list
+    */
+    void prependListItem(const QString &key, ListItem *item);
+
+    /**
+    * @brief Removes last ListItem in list.
+    */
+    void removeLastItem();
+
+    /**
     * @brief Returns selected ListItem.
     *
     * @return ListItem if there is selected, 0 otherwise
index d42353c..63449a0 100644 (file)
     USA.
 */
 
+#include <QSettings>
+
+#include "avatarimage.h"
+#include "../common.h"
+#include "extendedlistitem.h"
 #include "extendedlistitemdelegate.h"
 #include "locationlistitem.h"
 #include "locationlistview.h"
 #include "imagebutton.h"
 #include "panelcommon.h"
 #include "routing/location.h"
+#include "searchhistorylistitem.h"
+#include "searchhistorylistview.h"
 
 #include "locationsearchpanel.h"
 
+const QString SETTINGS_SEARCH_HISTORY = "SEARCH_HISTORY";
+
 LocationSearchPanel::LocationSearchPanel(QWidget *parent)
     : PanelBase(parent)
 {
@@ -50,6 +59,13 @@ LocationSearchPanel::LocationSearchPanel(QWidget *parent)
     headerLayout->addWidget(m_resultsLabel, 0, Qt::AlignCenter);
     setHeaderText(0);
 
+    // --- SEARCH HISTORY LIST VIEW ---
+    m_searchHistoryListView = new SearchHistoryListView(this);
+    m_searchHistoryListView->setItemDelegate(new ExtendedListItemDelegate(this));
+
+    connect(m_searchHistoryListView, SIGNAL(searchHistoryItemClicked(QString)),
+            this, SIGNAL(searchHistoryItemClicked(QString)));
+
     // --- SEARCH RESULTS LIST VIEW ---
     m_locationListView = new LocationListView(this);
     m_locationListView->setItemDelegate(new ExtendedListItemDelegate(this));
@@ -60,11 +76,12 @@ LocationSearchPanel::LocationSearchPanel(QWidget *parent)
             SIGNAL(locationItemClicked(const GeoCoordinate&, const GeoCoordinate&)));
 
     connect(m_locationListView, SIGNAL(listItemSelectionChanged()),
-            this, SLOT(setRouteButtonDisabled()));
+            this, SLOT(onListItemSelectionChanged()));
 
     QVBoxLayout *resultsListViewLayout = new QVBoxLayout;
     resultsListViewLayout->setContentsMargins(PANEL_MARGIN_LEFT, PANEL_MARGIN_TOP,
                                        PANEL_MARGIN_RIGHT, PANEL_MARGIN_BOTTOM);
+    resultsListViewLayout->addWidget(m_searchHistoryListView);
     resultsListViewLayout->addWidget(m_locationListView);
 
     // --- MAIN LAYOUT ---
@@ -80,18 +97,67 @@ LocationSearchPanel::LocationSearchPanel(QWidget *parent)
     panelLayout->addLayout(resultsListViewLayout);
 
     // --- CONTEXT BUTTONS ---
-    m_routeButton = new ImageButton(":res/images/compass.png", "", "", this);
-    m_routeButton->setDisabled(true);
+    m_routeButton = new ImageButton(":res/images/routing.png", "", "", this);
     connect(m_routeButton, SIGNAL(clicked()),
             this, SLOT(routeToSelectedLocation()));
 
     ImageButton *searchLocationButton = new ImageButton(":/res/images/search.png",
                                                         ":/res/images/search_s.png", "", this);
+
     connect(searchLocationButton, SIGNAL(clicked()),
             this, SIGNAL(requestSearchLocation()));
 
-    m_contextButtonLayout->addWidget(m_routeButton);
-    m_contextButtonLayout->addWidget(searchLocationButton);
+    m_clearLocationListButton = new ImageButton(":/res/images/clear_btn.png",
+                                                ":/res/images/clear_btn_s.png",
+                                                ":/res/images/clear_btn_d.png", this);
+    m_clearLocationListButton->setDisabled(true);
+
+    connect(m_clearLocationListButton, SIGNAL(clicked()),
+            this, SLOT(showSearchHistoryListView()));
+
+    m_itemButtonsLayout->addWidget(m_routeButton);
+    m_genericButtonsLayout->addWidget(searchLocationButton);
+    m_genericButtonsLayout->addWidget(m_clearLocationListButton);
+
+    readSettings();
+    showSearchHistoryListView();
+}
+
+LocationSearchPanel::~LocationSearchPanel()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    QSettings settings(DIRECTORY_NAME, FILE_NAME);
+    QList<QVariant> searchHistories;
+
+    for (int i = 0; i < m_searchHistoryListView->count(); ++i) {
+        SearchHistoryListItem *item = dynamic_cast<SearchHistoryListItem*>(
+                m_searchHistoryListView->listItemAt(i));
+
+        if (item) {
+            QList<QString> searchHistory;
+            searchHistory.append(item->title());
+            searchHistory.append(item->dateTime().toString());
+            searchHistories.append(QVariant(searchHistory));
+        }
+    }
+
+    settings.setValue(SETTINGS_SEARCH_HISTORY, searchHistories);
+}
+
+void LocationSearchPanel::prependSearchHistory(QString searchString, QDateTime dateTime)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    const int SEARCH_HISTORY_LIMIT = 10;
+    static int counter = 0;
+
+    if (m_searchHistoryListView->count() >= SEARCH_HISTORY_LIMIT)
+        m_searchHistoryListView->removeLastItem();
+
+    SearchHistoryListItem *item = new SearchHistoryListItem();
+    item->setSearchHistoryData(searchString, dateTime);
+    m_searchHistoryListView->prependListItem(QString::number(counter++), item);
 }
 
 void LocationSearchPanel::clearListsSelections()
@@ -99,8 +165,7 @@ void LocationSearchPanel::clearListsSelections()
     qDebug() << __PRETTY_FUNCTION__;
 
     m_locationListView->clearItemSelection();
-
-    setRouteButtonDisabled();
+    m_searchHistoryListView->clearItemSelection();
 }
 
 void LocationSearchPanel::hideEvent(QHideEvent *event)
@@ -116,9 +181,8 @@ void LocationSearchPanel::populateLocationListView(const QList<Location> &locati
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    setHeaderText(locations.count());
-
     m_locationListView->clearList();
+    showLocationListView(locations.count());
 
     for (int i = 0; i < locations.size(); ++i) {
         LocationListItem *item = new LocationListItem();
@@ -139,6 +203,25 @@ void LocationSearchPanel::populateLocationListView(const QList<Location> &locati
     m_locationListView->scrollToTop();
 }
 
+void LocationSearchPanel::readSettings()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    const int SEARCH_HISTORY_LIST_ITEM_COUNT = 2;
+
+    QSettings settings(DIRECTORY_NAME, FILE_NAME);
+    QList<QVariant> searchHistories = settings.value(SETTINGS_SEARCH_HISTORY).toList();
+
+    //Read from end to begin so items are prepended in correct order
+    for (int i = searchHistories.count() - 1; i >= 0; --i) {
+        QList<QVariant> searchHistory = searchHistories.at(i).toList();
+        if (searchHistory.count() == SEARCH_HISTORY_LIST_ITEM_COUNT) {
+            prependSearchHistory(searchHistory.at(0).toString(),
+                                 QDateTime::fromString(searchHistory.at(1).toString()));
+        }
+    }
+}
+
 void LocationSearchPanel::routeToSelectedLocation()
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -157,9 +240,24 @@ void LocationSearchPanel::setHeaderText(int count)
     m_resultsLabel->setText(tr("Search results: %1").arg(count));
 }
 
-void LocationSearchPanel::setRouteButtonDisabled()
+void LocationSearchPanel::showLocationListView(int locationItemsCount)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    m_searchHistoryListView->clearItemSelection();
+    m_searchHistoryListView->hide();
+    setHeaderText(locationItemsCount);
+    m_clearLocationListButton->setEnabled(true);
+    m_locationListView->show();
+}
+
+void LocationSearchPanel::showSearchHistoryListView()
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    m_routeButton->setDisabled(m_locationListView->selectedItems().isEmpty());
+    m_locationListView->clearList();
+    m_locationListView->hide();
+    m_resultsLabel->setText(tr("Search history:"));
+    m_clearLocationListButton->setDisabled(true);
+    m_searchHistoryListView->show();
 }
index fd87bf2..e939db7 100644 (file)
@@ -32,6 +32,7 @@ class GeoCoordinate;
 class ImageButton;
 class Location;
 class LocationListView;
+class SearchHistoryListView;
 
 /**
  * @brief Location search panel
@@ -51,6 +52,13 @@ public:
      */
     LocationSearchPanel(QWidget *parent = 0);
 
+    /**
+     * @brief Destructor
+     *
+     * Writes search history to settings.
+     */
+    ~LocationSearchPanel();
+
 /*******************************************************************************
  * BASE CLASS INHERITED AND REIMPLEMENTED MEMBER FUNCTIONS
  ******************************************************************************/
@@ -69,6 +77,11 @@ protected:
  ******************************************************************************/
 private:
     /**
+    * @brief Reads search history from settings.
+    */
+    void readSettings();
+
+    /**
     * @brief Set text for header
     *
     * @param count Search result count
@@ -77,6 +90,16 @@ private:
 
 private slots:
     /**
+    * @brief Prepends search history list view with search.
+    *
+    * If search history limit is reached, oldest search is removed from list view.
+    *
+    * @param searchString search string to add
+    * @param dateTime date and time of search (if empty, current date and time is added)
+    */
+    void prependSearchHistory(QString searchString, QDateTime dateTime = QDateTime());
+
+    /**
     * @brief Clears lists' selections.
     *
     * Does call setRouteButtonDisabled().
@@ -84,6 +107,18 @@ private slots:
     void clearListsSelections();
 
     /**
+    * @brief Shows location list view.
+    *
+    * @param locationItemsCount location items count
+    */
+    void showLocationListView(int locationItemsCount);
+
+    /**
+    * @brief Shows search history list view.
+    */
+    void showSearchHistoryListView();
+
+    /**
     * @brief Populates location list view.
     *
     * @param locations list of Location objects
@@ -97,13 +132,6 @@ private slots:
     */
     void routeToSelectedLocation();
 
-    /**
-    * @brief Sets route button disabled.
-    *
-    * Disabled if there isn't any list item selected.
-    */
-    void setRouteButtonDisabled();
-
 /*******************************************************************************
  * SIGNALS
  ******************************************************************************/
@@ -135,14 +163,23 @@ signals:
     */
     void routeWaypointItemClicked(const GeoCoordinate &coordinate);
 
+    /**
+    * @brief Signal is emitted when search history item is clicked.
+    *
+    * @param searchString search string used
+    */
+    void searchHistoryItemClicked(const QString &searchString);
+
 /*******************************************************************************
  * DATA MEMBERS
  ******************************************************************************/
 private:
-    QLabel *m_resultsLabel;                 ///< Location list label
+    QLabel *m_resultsLabel;                         ///< Location list label
 
-    ImageButton *m_routeButton;             ///< Route to location button
-    LocationListView *m_locationListView;   ///< Search results list view
+    ImageButton *m_clearLocationListButton;         ///< Clear location list button
+    ImageButton *m_routeButton;                     ///< Route to location button
+    SearchHistoryListView *m_searchHistoryListView; ///< Search history list view
+    LocationListView *m_locationListView;           ///< Search results list view
 };
 
 #endif // LOCATIONSEARCHPANEL_H
index 776177c..5ec1c40 100644 (file)
@@ -51,6 +51,7 @@
 #include "userinfopanel.h"
 #include "zoombuttonpanel.h"
 
+
 #include "mainwindow.h"
 
 // These MUST BE HERE, compiling for Maemo fails if moved
 #include <X11/Xlib.h>
 #endif // Q_WS_MAEMO_5
 
+#if defined(Q_WS_MAEMO_5) & defined(ARMEL)
+#include "ossoabookdialog.h"
+#endif
+
 MainWindow::MainWindow(QWidget *parent)
     : QMainWindow(parent),
       m_errorShown(false),
@@ -182,6 +187,9 @@ void MainWindow::buildFriendListPanel()
 
     connect(m_friendsListPanel, SIGNAL(routeToFriend(const GeoCoordinate&)),
             this, SIGNAL(routeTo(const GeoCoordinate&)));
+
+    connect(m_friendsListPanel, SIGNAL(requestContactDialog(const QString &)),
+            this, SIGNAL(requestContactDialog(const QString &)));
 }
 
 void MainWindow::buildFullScreenButton()
@@ -269,6 +277,12 @@ void MainWindow::buildLocationSearchPanel()
 
     connect(m_locationSearchPanel, SIGNAL(requestSearchLocation()),
             this, SLOT(startLocationSearch()));
+
+    connect(this, SIGNAL(searchForLocation(QString)),
+            m_locationSearchPanel, SLOT(prependSearchHistory(QString)));
+
+    connect(m_locationSearchPanel, SIGNAL(searchHistoryItemClicked(QString)),
+            this, SIGNAL(searchHistoryItemClicked(QString)));
 }
 
 void MainWindow::buildMap()
@@ -345,7 +359,7 @@ void MainWindow::buildPanels()
     buildRoutingPanel();
 
     m_tabbedPanel = new TabbedPanel(this);
-    
+
     //Save Situare related tab indexes so tabs can be enabled/disabled when logged in/out
     m_situareTabsIndexes.append(
             m_tabbedPanel->addTab(m_userInfoPanel, QIcon(":/res/images/user_info.png")));
@@ -384,6 +398,16 @@ void MainWindow::buildPanels()
 
     connect(m_tabbedPanel, SIGNAL(currentChanged(int)),
             m_userInfoPanel, SIGNAL(collapse()));
+
+    // signals for showing and hiding list item context buttons
+    connect(m_friendsListPanel, SIGNAL(listItemSelectionChanged(bool)),
+            m_tabbedPanel, SIGNAL(listItemSelectionChanged(bool)));
+
+    connect(m_locationSearchPanel, SIGNAL(listItemSelectionChanged(bool)),
+            m_tabbedPanel, SIGNAL(listItemSelectionChanged(bool)));
+
+    connect(m_routingPanel, SIGNAL(listItemSelectionChanged(bool)),
+            m_tabbedPanel, SIGNAL(listItemSelectionChanged(bool)));
 }
 
 void MainWindow::buildRoutingPanel()
@@ -932,6 +956,18 @@ void MainWindow::setUsername(const QString &username)
     m_email = username;
 }
 
+void MainWindow::showContactDialog(const QString &guid)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+#if defined(Q_WS_MAEMO_5) & defined(ARMEL)
+    OssoABookDialog::showContactDialog(guid);
+#else
+    Q_UNUSED(guid);
+    buildInformationBox(tr("Contact dialog works only on phone!"), true);
+#endif
+}
+
 void MainWindow::showEnableAutomaticUpdateLocationDialog(const QString &text)
 {
     qDebug() << __PRETTY_FUNCTION__;
index 06acfae..b9e5604 100644 (file)
@@ -193,6 +193,14 @@ public slots:
     void setUsername(const QString &username);
 
     /**
+    * @brief Shows contact dialog.
+    *
+    * Shows contact dialog with contact's information.
+    * @param guid globally unique ID of a contact
+    */
+    void showContactDialog(const QString &guid);
+
+    /**
      * @brief Public slot to intercept signal when old cerdentials are invalid or credentials
      *        doesn't exist yet
      */
@@ -564,6 +572,13 @@ signals:
     void refreshUserData();
 
     /**
+    * @brief Requests contact dialog.
+    *
+    * @param facebookId contact's facebookId
+    */
+    void requestContactDialog(const QString &facebookId);
+
+    /**
      * @brief Signal for requesting reverseGeo from SituareEngine
      *
      */
@@ -610,6 +625,13 @@ signals:
     void searchForLocation(QString location);
 
     /**
+    * @brief Signal is emitted when search history item is clicked.
+    *
+    * @param searchString search string used
+    */
+    void searchHistoryItemClicked(const QString &searchString);
+
+    /**
      * @brief Signal for requestLocationUpdate from SituareEngine
      *
      * @param status Status message
diff --git a/src/ui/ossoabookdialog.cpp b/src/ui/ossoabookdialog.cpp
new file mode 100644 (file)
index 0000000..3c35c39
--- /dev/null
@@ -0,0 +1,44 @@
+#include "ossoabookdialog.h"
+#include <QDebug>
+
+OssoABookDialog::OssoABookDialog(QObject *parent) :
+    QObject(parent)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+}
+
+void OssoABookDialog::showContactDialog(const QString &id)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    OssoABookContact *contact = OssoABookDialog::lookup(id);
+    if (contact) {
+        GtkWidget *contactDialog = osso_abook_touch_contact_starter_dialog_new(NULL,
+        (OssoABookTouchContactStarter*)osso_abook_touch_contact_starter_new_with_contact(NULL,
+        contact));
+
+    gtk_widget_show_all(contactDialog);
+    gtk_dialog_run(GTK_DIALOG(contactDialog));
+    gtk_widget_destroy(contactDialog);
+    }
+}
+
+OssoABookContact* OssoABookDialog::lookup(const QString& id)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    GList* l = NULL; // Do not free
+    GError *error = NULL;
+    OssoABookAggregator* aggregator = NULL; // Do not free
+
+    aggregator = (OssoABookAggregator*) osso_abook_aggregator_get_default(&error);
+    if (error) {
+        qWarning() << "error opening addressbook" << error->message;
+        g_error_free (error);
+        return NULL;
+    }
+
+    l = osso_abook_aggregator_lookup(aggregator,qPrintable(id));
+
+    return (OssoABookContact*) l->data;
+}
diff --git a/src/ui/ossoabookdialog.h b/src/ui/ossoabookdialog.h
new file mode 100644 (file)
index 0000000..c3bf793
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef OSSOABOOKDIALOG_H
+#define OSSOABOOKDIALOG_H
+
+#include <QObject>
+#include <QStringList>
+
+#undef signals // Collides with GTK symbols
+#include <libosso-abook/osso-abook.h>
+
+/**
+* @brief Shows contact dialog.
+*/
+class OssoABookDialog : public QObject
+{
+    Q_OBJECT
+public:
+    /**
+    * @brief Constructor
+    *
+    * @param parent QObject
+    */
+    OssoABookDialog(QObject *parent = 0);
+
+/*******************************************************************************
+* MEMBER FUNCTIONS AND SLOTS
+******************************************************************************/
+    /**
+    * @brief Shows contact dialog.
+    *
+    * @param id contact ID
+    */
+    static void showContactDialog(const QString &id);
+
+private:
+    /**
+    * @brief Returns address book contact.
+    *
+    * @param id contact ID
+    * @return OssoABookContact
+    */
+    static OssoABookContact *lookup(const QString& id);
+};
+
+#endif // OSSOABOOKDIALOG_H
index a0ebc33..72cd122 100644 (file)
@@ -3,6 +3,7 @@
     Copyright (C) 2010  Ixonos Plc. Authors:
 
         Pekka Nissinen - pekka.nissinen@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
@@ -20,6 +21,8 @@
 */
 
 #include <QDebug>
+#include <QListWidget>
+#include <QResizeEvent>
 #include <QVBoxLayout>
 
 #include "panelbase.h"
@@ -29,27 +32,63 @@ PanelBase::PanelBase(QWidget *parent)
 {
     qDebug() << __PRETTY_FUNCTION__;
 
+
+    // --- GENERIC BUTTONS ---
+    m_genericButtons = new QWidget;
+    m_genericButtonsLayout = new QVBoxLayout;
+
     const int CONTEXT_BUTTON_MARGIN_LEFT = 2;
     const int CONTEXT_BUTTON_MARGIN_TOP = 10;
     const int CONTEXT_BUTTON_MARGIN_RIGHT = 0;
     const int CONTEXT_BUTTON_MARGIN_BOTTOM = 0;
     const int CONTEXT_BUTTON_SPACING = 0;
-
-    m_contextButtons = new QWidget;
-
-    m_contextButtonLayout = new QVBoxLayout;
-    m_contextButtonLayout->setContentsMargins(CONTEXT_BUTTON_MARGIN_LEFT,
+    m_genericButtonsLayout->setContentsMargins(CONTEXT_BUTTON_MARGIN_LEFT,
                                               CONTEXT_BUTTON_MARGIN_TOP,
                                               CONTEXT_BUTTON_MARGIN_RIGHT,
                                               CONTEXT_BUTTON_MARGIN_BOTTOM);
-    m_contextButtonLayout->setSpacing(CONTEXT_BUTTON_SPACING);
+    m_genericButtonsLayout->setSpacing(CONTEXT_BUTTON_SPACING);
+
+    m_genericButtons->setLayout(m_genericButtonsLayout);
+
+    // --- ITEM RELATED BUTTONS ---
+    m_itemButtons = new QWidget(this);
+    m_itemButtonsLayout = new QHBoxLayout;
+
+    const int ITEM_CONTEXT_BUTTON_MARGIN_BOTTOM = 0;
+    const int ITEM_CONTEXT_BUTTON_MARGIN_LEFT = 2;
+    const int ITEM_CONTEXT_BUTTON_MARGIN_RIGHT = 2;
+    const int ITEM_CONTEXT_BUTTON_MARGIN_TOP = 2;
+    const int ITEM_CONTEXT_BUTTON_SPACING = 0;
+    m_itemButtonsLayout->setContentsMargins(ITEM_CONTEXT_BUTTON_MARGIN_LEFT,
+                                            ITEM_CONTEXT_BUTTON_MARGIN_TOP,
+                                            ITEM_CONTEXT_BUTTON_MARGIN_RIGHT,
+                                            ITEM_CONTEXT_BUTTON_MARGIN_BOTTOM);
+    m_itemButtonsLayout->setSpacing(ITEM_CONTEXT_BUTTON_SPACING);
+
+    m_itemButtons->setLayout(m_itemButtonsLayout);
+}
+
+QWidget* PanelBase::genericPanelButtons() const
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    return m_genericButtons;
+}
+
+QWidget* PanelBase::itemButtons() const
+{
+    qDebug() << __PRETTY_FUNCTION__;
 
-    m_contextButtons->setLayout(m_contextButtonLayout);
+    return m_itemButtons;
 }
 
-QWidget* PanelBase::contextButtons() const
+void PanelBase::onListItemSelectionChanged()
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    return m_contextButtons;
+    QListWidget *listWidget = dynamic_cast<QListWidget *>(sender());
+    if (listWidget && (listWidget->selectedItems().count() > 0))
+        emit listItemSelectionChanged(true);
+    else
+        emit listItemSelectionChanged(false);
 }
index 6f4dd0a..dee16ab 100644 (file)
@@ -3,6 +3,7 @@
     Copyright (C) 2010  Ixonos Plc. Authors:
 
         Pekka Nissinen - pekka.nissinen@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
@@ -24,6 +25,8 @@
 
 #include <QWidget>
 
+class QHBoxLayout;
+class QListWidgetItem;
 class QVBoxLayout;
 
 class ImageButton;
@@ -32,6 +35,7 @@ class ImageButton;
  * @brief Base class for panels
  *
  * @author Pekka Nissinen - pekka.nissinen (at) ixonos.com
+ * @author Sami Rämö - sami.ramo (at) ixonos.com
  */
 class PanelBase : public QWidget
 {
@@ -50,11 +54,26 @@ public:
  ******************************************************************************/
 public:
     /**
-     * @brief Getter for the context buttons
+     * @brief Getter for the generic panel related context buttons
      *
      * @returns Pointer to context buttons widget
      */
-    QWidget* contextButtons() const;
+    QWidget* genericPanelButtons() const;
+
+    /**
+     * @brief Getter for the list item related context buttons
+     *
+     * @returns Pointer to context buttons widget
+     */
+    QWidget* itemButtons() const;
+
+protected slots:
+    /**
+     * @brief Call when there is a change in list item selection
+     *
+     * Emits listItemSelectionChanged(bool). Parameter is true if any item is selected.
+     */
+    void onListItemSelectionChanged();
 
 /*******************************************************************************
  * SIGNALS
@@ -67,13 +86,22 @@ signals:
      */
     void openPanelRequested(QWidget *widget);
 
+    /**
+     * @brief Emitted when there is a change in list item selection
+     *
+     * @param itemIsSelected True if any item is selected.
+     */
+    void listItemSelectionChanged(bool itemIsSelected);
+
 /*******************************************************************************
  * DATA MEMBERS
  ******************************************************************************/
 protected:
-    QVBoxLayout *m_contextButtonLayout; ///< Layout for context buttons
+    QVBoxLayout *m_genericButtonsLayout;    ///< Layout for generic context buttons
+    QHBoxLayout *m_itemButtonsLayout;       ///< Layout for item related context buttons
 
 private:
-    QWidget *m_contextButtons;          ///< Widget for context buttons
+    QWidget *m_genericButtons;              ///< Widget for generic context buttons
+    QWidget *m_itemButtons;                 ///< Widget for item related context buttons
 };
 #endif // PANELBASE_H
index d721628..c3fcd64 100644 (file)
@@ -41,7 +41,7 @@ const int PANEL_BOTTOM_PADDING = 0; ///< Amount of padding in bottom of panels
 const int PANEL_BAR_WIDTH = 5;                                              ///< Width of the slider bar
 const int PANEL_TAB_BAR_WIDTH = 74;                                         ///< Panel tab bar total width
 const int PANEL_BAR_TABBED_WIDTH = PANEL_BAR_WIDTH + PANEL_TAB_BAR_WIDTH;   ///< Width of the tabbed bar
-const int PANEL_WIDTH  = 384;                                               ///< Width of the panel
+const int PANEL_WIDTH  = 384;                                               ///< Width of the panel contents area
 const int PANEL_HEIGHT = DEFAULT_SCREEN_HEIGHT - PANEL_TOP_PADDING
                          - PANEL_BOTTOM_PADDING;                            ///< Height of the panel
 
index 45998f4..55b711f 100644 (file)
@@ -43,6 +43,9 @@ RoutingPanel::RoutingPanel(QWidget *parent)
     connect(m_routeWaypointListView, SIGNAL(routeWaypointItemClicked(GeoCoordinate)),
             this, SIGNAL(routeWaypointItemClicked(GeoCoordinate)));
 
+    connect(m_routeWaypointListView, SIGNAL(listItemSelectionChanged()),
+            this, SLOT(onListItemSelectionChanged()));
+
     QVBoxLayout *panelLayout = new QVBoxLayout;
     panelLayout->setContentsMargins(PANEL_MARGIN_LEFT, PANEL_MARGIN_TOP,
                                     PANEL_MARGIN_RIGHT, PANEL_MARGIN_BOTTOM);
@@ -62,8 +65,8 @@ RoutingPanel::RoutingPanel(QWidget *parent)
             this, SLOT(clearRouteButtonClicked()));
     m_clearRouteButton->setDisabled(true);
 
-    m_contextButtonLayout->addWidget(routeToCursorButton);
-    m_contextButtonLayout->addWidget(m_clearRouteButton);
+    m_genericButtonsLayout->addWidget(routeToCursorButton);
+    m_genericButtonsLayout->addWidget(m_clearRouteButton);
 }
 
 void RoutingPanel::clearListsSelections()
diff --git a/src/ui/searchhistorylistitem.cpp b/src/ui/searchhistorylistitem.cpp
new file mode 100644 (file)
index 0000000..53fd7a4
--- /dev/null
@@ -0,0 +1,49 @@
+#include <QDebug>
+
+#include "avatarimage.h"
+#include "../common.h"
+#include "listcommon.h"
+
+#include "searchhistorylistitem.h"
+
+const int SEARCH_HISTORY_SUBITEM_TEXT_MAX_WIDTH = SUBITEM_TEXT_MAX_WIDTH + MARGIN + IMAGE_WIDTH;
+
+SearchHistoryListItem::SearchHistoryListItem()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    setSubitemTextWidth(SEARCH_HISTORY_SUBITEM_TEXT_MAX_WIDTH);
+}
+
+SearchHistoryListItem::~SearchHistoryListItem()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+}
+
+QDateTime SearchHistoryListItem::dateTime() const
+{
+    return m_dateTime;
+}
+
+void SearchHistoryListItem::setDateTime(const QDateTime &dateTime)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    if (dateTime.isNull())
+        m_dateTime = QDateTime::currentDateTime();
+    else
+        m_dateTime = dateTime;
+}
+
+void SearchHistoryListItem::setSearchHistoryData(const QString &searchString,
+                                                 const QDateTime &dateTime)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    setDateTime(dateTime);
+    setTitle(shortenText(searchString, ITEM_WIDTH - 3 * MARGIN, ListItem::TEXT_SIZE_NORMAL));
+    setImage(AvatarImage::create(QPixmap(":/res/images/search_history.png"), AvatarImage::Small));
+
+    clearSubItems();
+    addSubItem(m_dateTime.toString(), QPixmap(":/res/images/clock.png"));
+}
diff --git a/src/ui/searchhistorylistitem.h b/src/ui/searchhistorylistitem.h
new file mode 100644 (file)
index 0000000..b6b877a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+   Situare - A location system for Facebook
+   Copyright (C) 2010  Ixonos Plc. Authors:
+
+       Jussi Laitinen - jussi.laitinen@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 SEARCHHISTORYLISTITEM_H
+#define SEARCHHISTORYLISTITEM_H
+
+#include <QDateTime>
+
+#include "extendedlistitem.h"
+
+/**
+* @brief List item stores information about search history.
+*
+* @author Jussi Laitinen - jussi.laitinen (at) ixonos.com
+*/
+class SearchHistoryListItem : public ExtendedListItem
+{
+public:
+    /**
+    * @brief Constructor.
+    *
+    * Sets sub items' text width.
+    */
+    SearchHistoryListItem();
+
+    /**
+    * @brief Destructor.
+    */
+    ~SearchHistoryListItem();
+
+/******************************************************************************
+* MEMBER FUNCTIONS AND SLOTS
+******************************************************************************/
+public:
+    /**
+    * @brief Returns date and time.
+    *
+    * @return QDateTime
+    */
+    QDateTime dateTime() const;
+
+    /**
+    * @brief Sets search history data for this item.
+    *
+    * @param searchString search string
+    * @param dateTime date and time for search
+    */
+    void setSearchHistoryData(const QString &searchString, const QDateTime &dateTime);
+
+private:
+    /**
+    * @brief Sets date and time.
+    *
+    * @param dateTime QDateTime date and time
+    */
+    void setDateTime(const QDateTime &dateTime);
+
+/******************************************************************************
+* DATA MEMBERS
+******************************************************************************/
+private:
+    QDateTime m_dateTime;   ///< Date time
+};
+
+#endif // LOCATIONLISTITEM_H
diff --git a/src/ui/searchhistorylistview.cpp b/src/ui/searchhistorylistview.cpp
new file mode 100644 (file)
index 0000000..f6f7c80
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+   Situare - A location system for Facebook
+   Copyright (C) 2010  Ixonos Plc. Authors:
+
+       Jussi Laitinen - jussi.laitinen@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 "listitem.h"
+
+#include "searchhistorylistview.h"
+
+SearchHistoryListView::SearchHistoryListView(QWidget *parent)
+    : ListView(parent)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+}
+
+bool SearchHistoryListView::listItemClicked(ListItem *item)
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    bool selected = ListView::listItemClicked(item);
+
+    if (item && selected)
+        emit searchHistoryItemClicked(item->title());
+
+    return selected;
+}
diff --git a/src/ui/searchhistorylistview.h b/src/ui/searchhistorylistview.h
new file mode 100644 (file)
index 0000000..610df45
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+   Situare - A location system for Facebook
+   Copyright (C) 2010  Ixonos Plc. Authors:
+
+       Jussi Laitinen - jussi.laitinen@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 LOCATIONHISTORYLISTVIEW_H
+#define LOCATIONHISTORYLISTVIEW_H
+
+#include "listview.h"
+
+/**
+* @brief Shows search histroy in list view.
+*
+* @author Jussi Laitinen - jussi.laitinen (at) ixonos.com
+*/
+class SearchHistoryListView : public ListView
+{
+    Q_OBJECT
+
+public:
+    /**
+    * @brief Constructor.
+    *
+    * @param parent QWidget
+    */
+    SearchHistoryListView(QWidget *parent = 0);
+
+public slots:
+    /**
+    * @brief Slot for list item clicked.
+    *
+    * @param item ListItem
+    * @return true if item was selected, false otherwise
+    */
+    bool listItemClicked(ListItem *item);
+
+signals:
+    /**
+    * @brief Signal is emitted when search history item is clicked.
+    *
+    * @param searchString search string used
+    */
+    void searchHistoryItemClicked(const QString &searchString);
+};
+
+#endif // LOCATIONHISTORYLISTVIEW_H
index af58c61..3f130fc 100644 (file)
@@ -29,6 +29,7 @@
 #include <QStackedWidget>
 #include <QStateMachine>
 
+#include "listitemcontextbuttonbar.h"
 #include "panelbar.h"
 #include "panelbase.h"
 #include "panelcontentstack.h"
@@ -73,7 +74,7 @@ TabbedPanel::TabbedPanel(QWidget *parent)
     m_panelBar = new PanelBar(this);
     m_panelBar->move(PANEL_TAB_BAR_WIDTH, PANEL_TOP_Y);
 
-    // --- CONTEXT BUTTON BAR ---
+    // --- GENERIC PANEL CONTEXT BUTTON BAR ---
     m_panelContextButtonBar = new PanelContextButtonBar(this);
     m_panelContextButtonBar->move(PANEL_CONTEXT_BUTTON_BAR_LEFT_X, PANEL_HEIGHT);
 
@@ -83,9 +84,17 @@ TabbedPanel::TabbedPanel(QWidget *parent)
     connect(m_panelContextButtonBar, SIGNAL(positionChangeRequested()),
             this, SLOT(repositionContextButtonBar()));
 
+    // --- LIST ITEM RELATED CONTEXT BUTTONS BAR ---
+    m_itemContextButtonBar = new ListItemContextButtonBar(this);
+    m_itemContextButtonBar->hide();
+
+    connect(this, SIGNAL(listItemSelectionChanged(bool)),
+            m_itemContextButtonBar, SLOT(onListItemSelectionChanged(bool)));
+
     // --- PANEL CONTENT ---
     m_panelContentStack = new PanelContentStack(this);
     m_panelContentStack->move(PANEL_TAB_BAR_WIDTH + PANEL_BAR_WIDTH, PANEL_TOP_Y);
+    m_panelContentStack->stackUnder(m_itemContextButtonBar);
 
     // --- PANEL ANIMATION ---
     QStateMachine *panelStateMachine = new QStateMachine(this);
@@ -209,7 +218,7 @@ void TabbedPanel::repositionContextButtonBar()
     qDebug() << __PRETTY_FUNCTION__;
 
     m_panelContextButtonBar->move(PANEL_CONTEXT_BUTTON_BAR_LEFT_X, height());
-    
+
     calculateMask();
 }
 
@@ -252,7 +261,10 @@ void TabbedPanel::setCurrentIndex(int index)
             openPanel();
 
         m_panelContextButtonBar->setContextButtons(
-                static_cast<PanelBase *>(m_panelContentStack->widget(index))->contextButtons());
+                static_cast<PanelBase *>(m_panelContentStack->widget(index))->genericPanelButtons());
+
+        QWidget *itemContextButtons = static_cast<PanelBase *>(m_panelContentStack->widget(index))->itemButtons();
+        m_itemContextButtonBar->setContextButtons(itemContextButtons);
 
         emit currentChanged(index);
     }
index 12fefa9..87a056d 100644 (file)
@@ -32,6 +32,7 @@ class QSignalTransition;
 class QState;
 class QStateMachine;
 
+class ListItemContextButtonBar;
 class PanelBar;
 class PanelContentStack;
 class PanelContextButtonBar;
@@ -163,6 +164,13 @@ signals:
     void currentChanged(int index);
 
     /**
+     * @brief Emitted when there is a change in list item selection
+     *
+     * @param itemIsSelected True if any item is selected.
+     */
+    void listItemSelectionChanged(bool itemIsSelected);
+
+    /**
      * @brief Signal that is sent when panel is closed
      *
      * @sa openPanel
@@ -196,6 +204,7 @@ private:
     QState *m_stateClosed;      ///< State of the closed panel
     QState *m_stateOpened;      ///< State of the opened panel
 
+    ListItemContextButtonBar *m_itemContextButtonBar;   ///< Widget for list item context button bar
     PanelBar *m_panelBar;                               ///< Widget for panel bar
     PanelContentStack *m_panelContentStack;             ///< Stack for panel widgets
     PanelContextButtonBar * m_panelContextButtonBar;    ///< Widget for panel context button bar
index 6ed5ff8..c8a1d51 100644 (file)
@@ -89,8 +89,8 @@ UserInfoPanel::UserInfoPanel(QWidget *parent)
                                                              ":/res/images/send_position_s.png",
                                                              "", this);
 
-    m_contextButtonLayout->addWidget(updateFriendsButton);
-    m_contextButtonLayout->addWidget(updateStatusMessageButton);
+    m_genericButtonsLayout->addWidget(updateFriendsButton);
+    m_genericButtonsLayout->addWidget(updateStatusMessageButton);
 
     connect(updateFriendsButton, SIGNAL(clicked()),
             this, SIGNAL(refreshUserData()));
index 1b298f8..ba0807d 100644 (file)
@@ -9,7 +9,8 @@ SOURCES += \
     ../../../src/ui/panelcontentstack.cpp \
     ../../../src/ui/panelcontextbuttonbar.cpp \
     ../../../src/ui/paneltab.cpp \
-    ../../../src/ui/paneltabbar.cpp
+    ../../../src/ui/paneltabbar.cpp \
+    ../../../src/ui/listitemcontextbuttonbar.cpp
 HEADERS += \
     ../../../src/ui/tabbedpanel.h \
     ../../../src/ui/panelbar.h \
@@ -18,6 +19,7 @@ HEADERS += \
     ../../../src/ui/panelcontextbuttonbar.h \
     ../../../src/ui/paneltab.h \
     ../../../src/ui/paneltabbar.h \
-    ../../../src/ui/panelcommon.h
+    ../../../src/ui/panelcommon.h \
+    ../../../src/ui/listitemcontextbuttonbar.h
 RESOURCES += ../../../images.qrc
 DEFINES += QT_NO_DEBUG_OUTPUT