Emit error signal when login fails
[situare] / src / ui / tabbedpanel.cpp
1 /*
2     Situare - A location system for Facebook
3     Copyright (C) 2010  Ixonos Plc. Authors:
4
5         Kaj Wallin - kaj.wallin@ixonos.com
6         Pekka Nissinen - pekka.nissinen@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 <QAbstractButton>
24 #include <QButtonGroup>
25 #include <QDebug>
26 #include <QPropertyAnimation>
27 #include <QRegion>
28 #include <QSignalTransition>
29 #include <QStackedWidget>
30 #include <QStateMachine>
31
32 #include "listitemcontextbuttonbar.h"
33 #include "panelbar.h"
34 #include "panelbase.h"
35 #include "panelcontentstack.h"
36 #include "panelcontextbuttonbar.h"
37 #include "paneltabbar.h"
38
39 #include "tabbedpanel.h"
40
41 const int PANEL_CONTEXT_BUTTON_BAR_LEFT_X = 1;
42 const int PANEL_TAB_BAR_TOP_SPACING = 8;
43
44 TabbedPanel::TabbedPanel(QWidget *parent)
45     : QWidget(parent),
46       m_open(false),
47       m_closeRequestPending(false)
48 {
49     qDebug() << __PRETTY_FUNCTION__;
50
51     const int PANEL_LEFT_X = 0;
52     const int PANEL_TOP_Y = 0;
53
54     resize(PANEL_BAR_TABBED_WIDTH + PANEL_WIDTH, PANEL_HEIGHT);
55     move(PANEL_CLOSED_X, PANEL_TOP_PADDING);
56
57     // --- TABS ---
58     m_panelTabBar = new PanelTabBar(this);
59     m_panelTabBar->move(PANEL_LEFT_X, PANEL_TAB_BAR_TOP_SPACING);
60
61     connect(m_panelTabBar, SIGNAL(currentChanged(int)),
62             this, SLOT(setCurrentIndex(int)));
63
64     connect(m_panelTabBar, SIGNAL(sizeChangeRequested()),
65             this, SLOT(calculateMask()));
66
67     connect(m_panelTabBar, SIGNAL(tabCloseRequested(int)),
68              this, SLOT(closePanel()));
69
70     connect(this, SIGNAL(panelClosed()),
71             m_panelTabBar, SLOT(deselectTabs()));
72
73     // --- BAR ---
74     m_panelBar = new PanelBar(this);
75     m_panelBar->move(PANEL_TAB_BAR_WIDTH, PANEL_TOP_Y);
76
77     // --- GENERIC PANEL CONTEXT BUTTON BAR ---
78     m_panelContextButtonBar = new PanelContextButtonBar(this);
79     m_panelContextButtonBar->move(PANEL_CONTEXT_BUTTON_BAR_LEFT_X, PANEL_HEIGHT);
80
81     connect(m_panelContextButtonBar, SIGNAL(barHidden()),
82             this, SLOT(closePanel()));
83
84     connect(m_panelContextButtonBar, SIGNAL(positionChangeRequested()),
85             this, SLOT(repositionContextButtonBar()));
86
87     // --- LIST ITEM RELATED CONTEXT BUTTONS BAR ---
88     m_itemContextButtonBar = new ListItemContextButtonBar(this);
89     m_itemContextButtonBar->hide();
90
91     connect(this, SIGNAL(listItemSelectionChanged(bool)),
92             m_itemContextButtonBar, SLOT(onListItemSelectionChanged(bool)));
93
94     // --- PANEL CONTENT ---
95     m_panelContentStack = new PanelContentStack(this);
96     m_panelContentStack->move(PANEL_TAB_BAR_WIDTH + PANEL_BAR_WIDTH, PANEL_TOP_Y);
97     m_panelContentStack->stackUnder(m_itemContextButtonBar);
98
99     // --- PANEL ANIMATION ---
100     QStateMachine *panelStateMachine = new QStateMachine(this);
101
102     m_stateClosed = new QState(panelStateMachine);
103     m_stateOpened = new QState(panelStateMachine);
104
105     QPropertyAnimation *panelAnimation = new QPropertyAnimation(this, "pos", this);
106
107     panelStateMachine->setInitialState(m_stateClosed);
108
109     QSignalTransition *panelTransitionOpen = m_stateClosed->addTransition(this,
110                                                                           SIGNAL(toggleState()),
111                                                                           m_stateOpened);
112     panelTransitionOpen->addAnimation(panelAnimation);
113
114     QSignalTransition *panelTransitionClose = m_stateOpened->addTransition(this,
115                                                                            SIGNAL(toggleState()),
116                                                                            m_stateClosed);
117     panelTransitionClose->addAnimation(panelAnimation);
118
119     connect(panelAnimation, SIGNAL(finished()),
120             this, SLOT(stateChanged()));
121
122     QPoint closedPosition(PANEL_CLOSED_X, PANEL_TOP_PADDING);
123     m_stateClosed->assignProperty(this, "pos", closedPosition);
124
125     QPoint openedPosition(PANEL_OPENED_X, PANEL_TOP_PADDING);
126     m_stateOpened->assignProperty(this, "pos", openedPosition);
127
128     panelStateMachine->start();
129 }
130
131 int TabbedPanel::addTab(QWidget *widget, const QIcon& icon)
132 {
133     qDebug() << __PRETTY_FUNCTION__;
134
135     const int APPEND_INDEX = -1;
136
137     return insertTab(APPEND_INDEX, widget, icon);
138 }
139
140 void TabbedPanel::calculateMask()
141 {
142     qDebug() << __PRETTY_FUNCTION__;
143
144     QRect panelTabBarRect = m_panelTabBar->rect();
145     QRect panelContextButtonBarRect = m_panelContextButtonBar->rect();
146     int panelContextButtonBarY = height() - panelContextButtonBarRect.height();
147
148     if (!m_open)
149         panelContextButtonBarY = height();
150
151     QRegion panelTabBarRegion(0, PANEL_TAB_BAR_TOP_SPACING,
152                          panelTabBarRect.width(), panelTabBarRect.height());
153     QRegion panelContextButtonBarRegion(0, panelContextButtonBarY,
154                                       panelContextButtonBarRect.width(),
155                                       panelContextButtonBarRect.height());
156     QRegion panelContentRegion(panelTabBarRect.right() + 1, 0,
157                                PANEL_WIDTH + PANEL_BAR_WIDTH, height());
158     QRegion panelRegion = panelTabBarRegion + panelContentRegion + panelContextButtonBarRegion;
159
160     setMask(panelRegion);
161 }
162
163 void TabbedPanel::closePanel()
164 {
165     qDebug() << __PRETTY_FUNCTION__;
166
167     if (m_open) {
168         m_open = false;
169
170         if (m_panelContextButtonBar->isBarVisible()) {
171             m_closeRequestPending = true;
172             m_panelContextButtonBar->hideContextButtonBar();
173         } else {
174             emit toggleState();
175         }
176     } else if (m_closeRequestPending) {
177         m_closeRequestPending = false;
178         emit toggleState();
179     }
180 }
181
182 int TabbedPanel::insertTab(int index, QWidget *widget, const QIcon& icon)
183 {
184     qDebug() << __PRETTY_FUNCTION__;
185
186     index = m_panelContentStack->insertWidget(index, widget);
187     m_panelTabBar->insertTab(index, icon);
188
189     return index;
190 }
191
192 void TabbedPanel::openPanel(QWidget *widget)
193 {
194     qDebug() << __PRETTY_FUNCTION__;
195
196     if (widget) {
197         m_panelTabBar->selectTab(m_panelContentStack->indexOf(widget));
198     } else if (!m_open) {
199         if (!m_closeRequestPending) {
200             m_open = true;
201             emit toggleState();
202         }
203     }
204 }
205
206 void TabbedPanel::removeTab(int index)
207 {
208     qDebug() << __PRETTY_FUNCTION__;
209
210     if (QWidget *widget = m_panelContentStack->widget(index)) {
211         m_panelContentStack->removeWidget(widget);
212         m_panelTabBar->removeTab(index);
213     }
214 }
215
216 void TabbedPanel::repositionContextButtonBar()
217 {
218     qDebug() << __PRETTY_FUNCTION__;
219
220     m_panelContextButtonBar->move(PANEL_CONTEXT_BUTTON_BAR_LEFT_X, height());
221
222     calculateMask();
223 }
224
225 void TabbedPanel::resizePanel(const QSize &size)
226 {
227     qDebug() << __PRETTY_FUNCTION__;
228
229     resize(PANEL_BAR_TABBED_WIDTH + PANEL_WIDTH,
230            size.height() - PANEL_TOP_PADDING - PANEL_BOTTOM_PADDING);
231
232     if (!m_open)
233         move(size.width() - PANEL_TAB_BAR_WIDTH - PANEL_BAR_WIDTH, PANEL_TOP_PADDING);
234     else
235         move(size.width() - PANEL_TAB_BAR_WIDTH - PANEL_BAR_WIDTH - PANEL_WIDTH, PANEL_TOP_PADDING);
236
237     m_panelBar->resizeBar(size);
238
239     m_panelContextButtonBar->move(PANEL_CONTEXT_BUTTON_BAR_LEFT_X, size.height());
240
241     m_panelContentStack->resizeContentStack(size);
242
243     QPoint closedPosition(size.width() - PANEL_TAB_BAR_WIDTH - PANEL_BAR_WIDTH, PANEL_TOP_PADDING);
244     m_stateClosed->assignProperty(this, "pos", closedPosition);
245
246     QPoint openedPosition(size.width() - PANEL_TAB_BAR_WIDTH - PANEL_BAR_WIDTH - PANEL_WIDTH,
247                           PANEL_TOP_PADDING);
248     m_stateOpened->assignProperty(this, "pos", openedPosition);
249
250     calculateMask();
251 }
252
253 void TabbedPanel::setCurrentIndex(int index)
254 {
255     qDebug() << __PRETTY_FUNCTION__;
256
257     if ((index < m_panelContentStack->count()) && (index >= 0)) {
258         m_panelContentStack->setCurrentIndex(index);
259
260         if (!m_open)
261             openPanel();
262
263         m_panelContextButtonBar->setContextButtons(
264                 static_cast<PanelBase *>(m_panelContentStack->widget(index))->genericPanelButtons());
265
266         QWidget *itemContextButtons = static_cast<PanelBase *>(m_panelContentStack->widget(index))->itemButtons();
267         m_itemContextButtonBar->setContextButtons(itemContextButtons);
268
269         emit currentChanged(index);
270     }
271 }
272
273 void TabbedPanel::setTabsEnabled(const QList<int> &tabIndexes, bool enabled)
274 {
275     qDebug() << __PRETTY_FUNCTION__;
276
277     QButtonGroup *tabs = m_panelTabBar->tabs();
278
279     foreach (int tabIndex, tabIndexes) {
280         QAbstractButton *tabButton = tabs->button(tabIndex);
281
282         if (tabButton) {
283             if (tabButton->isChecked())
284                 closePanel();
285
286             tabButton->setEnabled(enabled);
287         }
288     }
289 }
290
291 void TabbedPanel::stateChanged()
292 {
293     qDebug() << __PRETTY_FUNCTION__;
294
295     calculateMask();
296
297     if (m_open) {
298         m_panelContextButtonBar->showContextButtonBar();
299         emit panelOpened();
300     } else {
301         emit panelClosed();
302     }
303 }