Added LocationSearchPanel (which is currently a copy of RoutingPanel)
[situare] / src / ui / locationsearchpanel.cpp
1 /*
2     Situare - A location system for Facebook
3     Copyright (C) 2010  Ixonos Plc. Authors:
4
5         Jussi Laitinen - jussi.laitinen@ixonos.com
6         Sami Rämö - sami.ramo@ixonos.com
7
8     Situare is free software; you can redistribute it and/or
9     modify it under the terms of the GNU General Public License
10     version 2 as published by the Free Software Foundation.
11
12     Situare is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with Situare; if not, write to the Free Software
19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
20     USA.
21 */
22
23 #include "coordinates/geocoordinate.h"
24 #include "extendedlistitemdelegate.h"
25 #include "locationlistitem.h"
26 #include "locationlistview.h"
27 #include "imagebutton.h"
28 #include "panelcommon.h"
29 #include "routewaypointlistitem.h"
30 #include "routewaypointlistview.h"
31 #include "routing/location.h"
32 #include "routing/route.h"
33
34 #include "locationsearchpanel.h"
35
36 LocationSearchPanel::LocationSearchPanel(QWidget *parent)
37     : PanelBase(parent)
38 {
39     qDebug() << __PRETTY_FUNCTION__;
40
41     // --- ROUTING INSTRUCTIONS WIDGET ---
42     m_routeWaypointListView = new RouteWaypointListView(this);
43     m_routeWaypointListView->setItemDelegate(new ExtendedListItemDelegate(this));
44
45     connect(m_routeWaypointListView, SIGNAL(routeWaypointItemClicked(GeoCoordinate)),
46             this, SIGNAL(routeWaypointItemClicked(GeoCoordinate)));
47
48     QVBoxLayout *routingViewLayout = new QVBoxLayout;
49     routingViewLayout->setContentsMargins(PANEL_MARGIN_LEFT, PANEL_MARGIN_TOP,
50                                           PANEL_MARGIN_RIGHT, PANEL_MARGIN_BOTTOM);
51
52     // main routing layout
53     m_routingView = new QWidget();
54     m_routingView->setLayout(routingViewLayout);
55     routingViewLayout->addWidget(m_routeWaypointListView);
56
57     // --- SEARCH RESULTS WIDGET ---
58     // header
59     QWidget *resultsHeaderWidget = new QWidget();
60     resultsHeaderWidget->setAutoFillBackground(true);
61     QPalette labelPalette = resultsHeaderWidget->palette();
62     labelPalette.setColor(QPalette::Background, Qt::black);
63     resultsHeaderWidget->setPalette(labelPalette);
64
65     QHBoxLayout *headerLayout = new QHBoxLayout();
66     resultsHeaderWidget->setLayout(headerLayout);
67     headerLayout->setContentsMargins(PANEL_MARGIN_LEFT, PANEL_MARGIN_TOP,
68                                      PANEL_MARGIN_RIGHT, PANEL_MARGIN_BOTTOM);
69
70     m_resultsLabel = new QLabel(this);
71     headerLayout->addWidget(m_resultsLabel, 0, Qt::AlignCenter);
72
73     // list view
74     m_locationListView = new LocationListView(this);
75     m_locationListView->setItemDelegate(new ExtendedListItemDelegate(this));
76
77     connect(m_locationListView,
78             SIGNAL(locationItemClicked(const GeoCoordinate&, const GeoCoordinate&)),
79             this,
80             SIGNAL(locationItemClicked(const GeoCoordinate&, const GeoCoordinate&)));
81
82     connect(m_locationListView, SIGNAL(listItemSelectionChanged()),
83             this, SLOT(setRouteButtonDisabled()));
84
85     QVBoxLayout *resultsListViewLayout = new QVBoxLayout;
86     resultsListViewLayout->setContentsMargins(PANEL_MARGIN_LEFT, PANEL_MARGIN_TOP,
87                                        PANEL_MARGIN_RIGHT, PANEL_MARGIN_BOTTOM);
88     resultsListViewLayout->addWidget(m_locationListView);
89
90     // main results layout
91     m_resultsView = new QWidget();
92     QVBoxLayout *resultsViewLayout = new QVBoxLayout;
93     const int CONTENTS_MARGIN_LEFT = 0;
94     resultsViewLayout->setContentsMargins(CONTENTS_MARGIN_LEFT, PANEL_MARGIN_TOP,
95                                           PANEL_MARGIN_RIGHT, PANEL_MARGIN_BOTTOM);
96     m_resultsView->setLayout(resultsViewLayout);
97
98     resultsViewLayout->addWidget(resultsHeaderWidget);
99     resultsViewLayout->addLayout(resultsListViewLayout);
100
101     // --- MAIN LAYOUT ---
102     QVBoxLayout *LocationSearchPanelLayout = new QVBoxLayout;
103     LocationSearchPanelLayout->setMargin(0);
104     LocationSearchPanelLayout->setSpacing(0);
105     setLayout(LocationSearchPanelLayout);
106
107     m_views = new QStackedLayout();
108     LocationSearchPanelLayout->addLayout(m_views);
109     m_views->setContentsMargins(PANEL_MARGIN_LEFT, PANEL_MARGIN_TOP,
110                                 PANEL_MARGIN_RIGHT, PANEL_MARGIN_BOTTOM);
111
112     m_views->addWidget(m_routingView);
113     m_views->addWidget(m_resultsView);
114
115     // --- CONTEXT BUTTONS ---
116     m_searchLocationButton = new ImageButton(":/res/images/search.png",
117                                              ":/res/images/search_s.png", "", this);
118     m_searchLocationButton->setCheckable(true);
119     connect(m_searchLocationButton, SIGNAL(toggled(bool)),
120             this, SLOT(searchLocationButtonToggled(bool)));
121
122     m_routeButton = new ImageButton(":res/images/route_to_location.png",
123                                     ":res/images/route_to_location_s.png", "", this);
124     m_routeButton->setCheckable(true);
125     m_routeButton->setDisabled(true);
126     connect(m_routeButton, SIGNAL(toggled(bool)),
127             this, SLOT(routeButtonToggled(bool)));
128
129     m_contextButtonLayout->addWidget(m_searchLocationButton);
130     m_contextButtonLayout->addWidget(m_routeButton);
131 }
132
133 void LocationSearchPanel::clearListsSelections()
134 {
135     qDebug() << __PRETTY_FUNCTION__;
136
137     m_locationListView->clearItemSelection();
138     m_routeWaypointListView->clearItemSelection();
139
140     setRouteButtonDisabled();
141 }
142
143 void LocationSearchPanel::hideEvent(QHideEvent *event)
144 {
145     qDebug() << __PRETTY_FUNCTION__;
146
147     QWidget::hideEvent(event);
148
149     clearListsSelections();
150 }
151
152 void LocationSearchPanel::populateLocationListView(const QList<Location> &locations)
153 {
154     qDebug() << __PRETTY_FUNCTION__;
155
156     m_resultsLabel->setText(tr("Search results: %1").arg(locations.count()));
157
158     m_locationListView->clearList();
159
160     for (int i = 0; i < locations.size(); ++i) {
161         LocationListItem *item = new LocationListItem();
162         item->setLocationData(locations.at(i));
163         m_locationListView->addListItem(QString::number(i), item);
164     }
165
166     const int FIRST_LOCATION_ITEM_INDEX = 0;
167     const int ONE_LOCATION_ITEM = 1;
168
169     if (locations.size() == ONE_LOCATION_ITEM) {
170         ListItem *item = m_locationListView->listItemAt(FIRST_LOCATION_ITEM_INDEX);
171
172         if (item)
173             m_locationListView->setSelectedItem(item);
174     }
175
176     m_locationListView->scrollToTop();
177 }
178
179 void LocationSearchPanel::routeButtonToggled(bool checked)
180 {
181     qDebug() << __PRETTY_FUNCTION__;
182
183     if (checked) {
184         routeToSelectedLocation();
185         m_searchLocationButton->setChecked(false);
186     } else {
187         emit clearRoute();
188         m_routeWaypointListView->clearList();
189         setRouteButtonDisabled();
190     }
191 }
192
193 void LocationSearchPanel::routeToSelectedLocation()
194 {
195     qDebug() << __PRETTY_FUNCTION__;
196
197     LocationListItem *item = dynamic_cast<LocationListItem *>
198                              (m_locationListView->selectedItem());
199
200     if (item)
201         emit routeToLocation(item->coordinates());
202 }
203
204 void LocationSearchPanel::searchLocationButtonToggled(bool checked)
205 {
206     qDebug() << __PRETTY_FUNCTION__;
207
208     if (checked) {
209         showResultsView();
210         emit requestSearchLocation();
211     } else {
212         showRoutingView();
213     }
214 }
215
216 void LocationSearchPanel::setRoute(Route &route)
217 {
218     qDebug() << __PRETTY_FUNCTION__;
219
220     m_routeWaypointListView->clearList();
221
222     QList<RouteSegment> segments = route.segments();
223     QList<GeoCoordinate> geometryPoints = route.geometryPoints();
224
225     for (int i = 0; i < segments.size(); ++i) {
226         RouteWaypointListItem *item = new RouteWaypointListItem();
227         RouteSegment routeSegment = segments.at(i);
228         item->setRouteWaypointData(routeSegment,
229                                    geometryPoints.at(routeSegment.positionIndex()));
230
231         m_routeWaypointListView->addListItem(QString::number(i), item);
232     }
233
234     m_routeWaypointListView->scrollToTop();
235
236     // route might come from FriendListPanel's route to friend button, so we have to
237     // check the routing button without emitting new routing request
238     blockSignals(true);
239     m_routeButton->setEnabled(true);
240     m_routeButton->setChecked(true);
241     blockSignals(false);
242     m_searchLocationButton->setChecked(false);
243
244     // search location button might be already false, so we have to make sure the
245     // toggle action handler is called every time
246     searchLocationButtonToggled(false);
247
248     emit openPanelRequested(this);
249 }
250
251 void LocationSearchPanel::setRouteButtonDisabled()
252 {
253     qDebug() << __PRETTY_FUNCTION__;
254
255     m_routeButton->setDisabled(m_locationListView->selectedItems().isEmpty()
256                                && !m_routeButton->isChecked());
257 }
258
259 void LocationSearchPanel::showResultsView()
260 {
261     qDebug() << __PRETTY_FUNCTION__;
262
263     m_views->setCurrentWidget(m_resultsView);
264     m_routeWaypointListView->clearItemSelection();
265 }
266
267 void LocationSearchPanel::showRoutingView()
268 {
269     qDebug() << __PRETTY_FUNCTION__;
270
271     m_views->setCurrentWidget(m_routingView);
272     m_locationListView->clearItemSelection();
273 }