Clean up book view decorations code.
[dorian] / adopterwindow.cpp
1 #include <QtGui>
2
3 #if defined(Q_WS_MAEMO_5)
4 #   include <QtGui/QX11Info>
5 #   include <X11/Xlib.h>
6 #   include <X11/Xatom.h>
7 #   include <QAbstractKineticScroller>
8 #endif
9
10 #include "adopterwindow.h"
11 #include "trace.h"
12 #include "bookview.h"
13 #include "platform.h"
14 #include "settings.h"
15 #include "progress.h"
16 #include "translucentbutton.h"
17
18 AdopterWindow::AdopterWindow(QWidget *parent):
19     QMainWindow(parent), bookView(0), grabbingVolumeKeys(false), toolBar(0),
20     progress(0), previousButton(0), nextButton(0)
21 {
22     TRACE;
23
24 #ifdef Q_WS_MAEMO_5
25     setAttribute(Qt::WA_Maemo5StackedWindow, true);
26 #endif
27
28     QFrame *frame = new QFrame(this);
29     QVBoxLayout *layout = new QVBoxLayout(frame);
30     layout->setMargin(0);
31     frame->setLayout(layout);
32     frame->show();
33     setCentralWidget(frame);
34
35 #ifdef Q_OS_SYMBIAN
36     QAction *closeAction = new QAction(parent? tr("Back"): tr("Exit"), this);
37     closeAction->setSoftKeyRole(QAction::NegativeSoftKey);
38     connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
39     QMainWindow::addAction(closeAction);
40 #else
41     // Tool bar
42     setUnifiedTitleAndToolBarOnMac(true);
43     toolBar = addToolBar("");
44     toolBar->setMovable(false);
45     toolBar->setFloatable(false);
46     toolBar->toggleViewAction()->setVisible(false);
47 #if defined(Q_WS_X11) && !defined(Q_WS_MAEMO_5)
48     toolBar->setIconSize(QSize(42, 42));
49 #endif
50 #endif // Q_OS_SYMBIAN
51
52     // Monitor settings
53     connect(Settings::instance(), SIGNAL(valueChanged(const QString &)),
54             this, SLOT(onSettingsChanged(const QString &)));
55 }
56
57 void AdopterWindow::takeBookView(BookView *view,
58                                  Progress *prog,
59                                  TranslucentButton *previous,
60                                  TranslucentButton *next)
61 {
62     TRACE;
63
64     Q_ASSERT(view);
65     Q_ASSERT(prog);
66     Q_ASSERT(previous);
67     Q_ASSERT(next);
68
69     leaveBookView();
70
71     bookView = view;
72     bookView->setParent(this);
73     bookView->show();
74     centralWidget()->layout()->addWidget(bookView);
75
76     progress = prog;
77     previousButton = previous;
78     nextButton = next;
79     progress->setParent(this);
80     previousButton->setParent(this);
81     nextButton->setParent(this);
82 }
83
84 void AdopterWindow::leaveBookView()
85 {
86     TRACE;
87     if (bookView) {
88         centralWidget()->layout()->removeWidget(bookView);
89     }
90     bookView = 0;
91     progress = 0;
92     nextButton = 0;
93     previousButton = 0;
94 }
95
96 bool AdopterWindow::hasBookView()
97 {
98     return bookView != 0;
99 }
100
101 void AdopterWindow::show()
102 {
103 #ifdef Q_OS_SYMBIAN
104     foreach (QWidget *w, QApplication::allWidgets()) {
105         w->setContextMenuPolicy(Qt::NoContextMenu);
106     }
107     showMaximized();
108     raise();
109 #else
110     QMainWindow::show();
111 #endif
112 }
113
114 QAction *AdopterWindow::addToolBarAction(QObject *receiver,
115                                          const char *member,
116                                          const QString &iconName,
117                                          const QString &text,
118                                          bool important)
119 {
120     TRACE;
121     qDebug() << "icon" << iconName << "text" << text;
122     QAction *action;
123 #ifndef Q_OS_SYMBIAN
124     Q_UNUSED(important);
125     action = toolBar->addAction(QIcon(Platform::instance()->icon(iconName)),
126                                 text, receiver, member);
127 #else
128     if (!toolBar && important) {
129         // Create tool bar if needed
130         toolBar = new QToolBar("", this);
131         // toolBar->setFixedWidth(QApplication::desktop()->
132         //                        availableGeometry().width());
133         toolBar->setFixedHeight(65);
134         toolBar->setStyleSheet("margin:0; border:0; padding:0");
135         toolBar->setSizePolicy(QSizePolicy::MinimumExpanding,
136                                QSizePolicy::Maximum);
137         addToolBar(Qt::BottomToolBarArea, toolBar);
138     }
139     if (important) {
140         // Add tool bar action
141         QPushButton *button = new QPushButton(this);
142         button->setIconSize(QSize(60, 60));
143         button->setFixedSize(89, 60);
144         button->setIcon(QIcon(Platform::instance()->icon(iconName)));
145         button->setSizePolicy(QSizePolicy::MinimumExpanding,
146                               QSizePolicy::Maximum);
147         connect(button, SIGNAL(clicked()), receiver, member);
148         toolBar->addWidget(button);
149     }
150     // Add menu action, too
151     action = new QAction(text, this);
152     menuBar()->addAction(action);
153     connect(action, SIGNAL(triggered()), receiver, member);
154 #endif
155
156 #if defined Q_WS_MAEMO_5
157     action->setText("");
158     action->setToolTip("");
159 #endif
160
161     return action;
162 }
163
164 void AdopterWindow::addToolBarSpace()
165 {
166 #ifndef Q_OS_SYMBIAN
167     QFrame *frame = new QFrame(toolBar);
168     frame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
169     toolBar->addWidget(frame);
170 #endif
171 }
172
173 void AdopterWindow::grabVolumeKeys(bool grab)
174 {
175     TRACE;
176     grabbingVolumeKeys = grab;
177 #ifdef Q_WS_MAEMO_5
178     doGrabVolumeKeys(grab);
179 #endif
180 }
181
182 #ifdef Q_WS_MAEMO_5
183
184 void AdopterWindow::doGrabVolumeKeys(bool grab)
185 {
186     TRACE;
187     if (!isVisible()) {
188         qDebug() << "Not visible - skipping";
189         return;
190     }
191     if (!winId()) {
192         qDebug() << "Could not get window ID - skipping";
193         return;
194     }
195     unsigned long val = grab? 1: 0;
196     Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False);
197     if (!atom) {
198         qCritical() << "Unable to obtain _HILDON_ZOOM_KEY_ATOM";
199         return;
200     }
201     XChangeProperty(QX11Info::display(),
202         winId(),
203         atom,
204         XA_INTEGER,
205         32,
206         PropModeReplace,
207         reinterpret_cast<unsigned char *>(&val),
208         1);
209     qDebug() << "Grabbed volume keys";
210 }
211
212 #endif // Q_WS_MAEMO_5
213
214 void AdopterWindow::showEvent(QShowEvent *e)
215 {
216     Trace t("AdopterWindow::showEvent");
217
218 #if defined(Q_WS_MAEMO_5)
219     doGrabVolumeKeys(grabbingVolumeKeys);
220 #endif // Q_WS_MAEMO_5
221     QMainWindow::showEvent(e);
222 }
223
224 void AdopterWindow::resizeEvent(QResizeEvent *event)
225 {
226     Trace t("AdopterWindow::resizeEvent");
227
228 #ifdef Q_OS_SYMBIAN
229     if (toolBar) {
230         if (portrait()) {
231             qDebug() << "Show tool bar";
232             toolBar->setVisible(true);
233         } else {
234             qDebug() << "Hide tool bar";
235             toolBar->setVisible(false);
236         }
237     }
238 #endif // Q_OS_SYMBIAN
239
240     if (hasBookView()) {
241         QTimer::singleShot(100, this, SLOT(placeDecorations()));
242     }
243     QMainWindow::resizeEvent(event);
244 }
245
246 void AdopterWindow::keyPressEvent(QKeyEvent *event)
247 {
248     TRACE;
249     if (bookView && grabbingVolumeKeys) {
250         switch (event->key()) {
251 #ifdef Q_WS_MAEMO_5
252         case Qt::Key_F7:
253             qDebug() << "F7";
254             bookView->goNextPage();
255             event->accept();
256             break;
257         case Qt::Key_F8:
258             qDebug() << "F8";
259             bookView->goPreviousPage();
260             event->accept();
261             break;
262 #endif // Q_WS_MAEMO_5
263         case Qt::Key_PageUp:
264             bookView->goPreviousPage();
265             event->accept();
266             break;
267         case Qt::Key_PageDown:
268             bookView->goNextPage();
269             event->accept();
270             break;
271         default:
272             ;
273         }
274     }
275     QMainWindow::keyPressEvent(event);
276 }
277
278 void AdopterWindow::onSettingsChanged(const QString &key)
279 {
280     if (key == "usevolumekeys") {
281         bool grab = Settings::instance()->value(key, false).toBool();
282         qDebug() << "AdopterWindow::onSettingsChanged: usevolumekeys" << grab;
283         grabVolumeKeys(grab);
284     }
285 }
286
287 bool AdopterWindow::portrait()
288 {
289     QRect geometry = QApplication::desktop()->geometry();
290     return geometry.width() < geometry.height();
291 }
292
293 void AdopterWindow::placeDecorations()
294 {
295     Trace t("AdopterWindow::placeDecorations");
296
297     if (!hasBookView()) {
298         return;
299     }
300
301     int toolBarHeight = 0;
302
303     QRect geo = bookView->geometry();
304     qDebug() << "bookView:" << geo;
305
306 #ifdef Q_OS_SYMBIAN
307     // Work around Symbian bug: If tool bar is hidden, increase bottom
308     // decorator widgets' Y coordinates by the tool bar's height
309     if (!portrait() && toolBar) {
310         toolBarHeight = toolBar->height();
311     }
312
313     // Work around another Symbian bug: When returning from full screen mode
314     // in landscape, the book view widget's height is miscalculated.
315     // My apologies for this kludge
316     if (geo.height() == 288) {
317         qDebug() << "Adjusting bottom Y";
318         toolBarHeight -= 288 - 223;
319     }
320 #endif // Q_OS_SYMBIAN
321
322     progress->setGeometry(geo.x(),
323         geo.y() + geo.height() - progress->thickness() + toolBarHeight,
324         geo.width(), progress->thickness());
325     previousButton->setGeometry(geo.x(),
326         geo.y() + geo.height() - TranslucentButton::pixels + toolBarHeight,
327         TranslucentButton::pixels, TranslucentButton::pixels);
328     nextButton->setGeometry(
329         geo.x() + geo.width() - TranslucentButton::pixels,
330         geo.y(), TranslucentButton::pixels, TranslucentButton::pixels);
331     progress->flash();
332     previousButton->flash();
333     nextButton->flash();
334     qDebug() << "progress:" << progress->geometry();
335 }