Add new widget MainWindow.
[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
58 void AdopterWindow::takeBookView(BookView *view,
59                                  Progress *prog,
60                                  TranslucentButton *previous,
61                                  TranslucentButton *next)
62 {
63     TRACE;
64
65     Q_ASSERT(view);
66     Q_ASSERT(prog);
67     Q_ASSERT(previous);
68     Q_ASSERT(next);
69
70     leaveBookView();
71
72     bookView = view;
73     bookView->setParent(this);
74     centralWidget()->layout()->addWidget(bookView);
75     bookView->show();
76
77     progress = prog;
78     previousButton = previous;
79     nextButton = next;
80     progress->setParent(this);
81     previousButton->setParent(this);
82     nextButton->setParent(this);
83
84     // Handle page and/or volume keys
85     connect(this, SIGNAL(pageUp()), this, SLOT(onPageUp()),
86             Qt::QueuedConnection);
87     connect(this, SIGNAL(pageDown()), this, SLOT(onPageDown()),
88             Qt::QueuedConnection);
89 }
90
91 void AdopterWindow::leaveBookView()
92 {
93     TRACE;
94     if (bookView) {
95         bookView->hide();
96         centralWidget()->layout()->removeWidget(bookView);
97     }
98     bookView = 0;
99     progress = 0;
100     nextButton = 0;
101     previousButton = 0;
102     disconnect(this, SLOT(onPageUp()));
103     disconnect(this, SLOT(onPageDown()));
104 }
105
106 bool AdopterWindow::hasBookView()
107 {
108     return bookView != 0;
109 }
110
111 void AdopterWindow::show()
112 {
113     Trace t("AdopterWindow::show");
114 #ifdef Q_OS_SYMBIAN
115     foreach (QWidget *w, QApplication::allWidgets()) {
116         w->setContextMenuPolicy(Qt::NoContextMenu);
117     }
118     showMaximized();
119 #else
120     QMainWindow::show();
121 #endif
122 }
123
124 QAction *AdopterWindow::addToolBarAction(QObject *receiver,
125                                          const char *member,
126                                          const QString &iconName,
127                                          const QString &text,
128                                          bool important)
129 {
130     TRACE;
131     qDebug() << "icon" << iconName << "text" << text;
132     QAction *action;
133 #ifndef Q_OS_SYMBIAN
134     Q_UNUSED(important);
135     action = toolBar->addAction(QIcon(Platform::instance()->icon(iconName)),
136                                 text, receiver, member);
137 #else
138     if (!toolBar && important) {
139         // Create tool bar if needed
140         toolBar = new QToolBar("", this);
141         // toolBar->setFixedHeight(63);
142         toolBar->setStyleSheet("margin:0; border:0; padding:0");
143         toolBar->setSizePolicy(QSizePolicy::MinimumExpanding,
144                                QSizePolicy::Maximum);
145         addToolBar(Qt::BottomToolBarArea, toolBar);
146     }
147     if (important) {
148         // Add tool bar action
149         QPushButton *button = new QPushButton(this);
150         button->setIconSize(QSize(60, 60));
151         button->setFixedSize(89, 60);
152         button->setIcon(QIcon(Platform::instance()->icon(iconName)));
153         button->setSizePolicy(QSizePolicy::MinimumExpanding,
154                               QSizePolicy::Maximum);
155         connect(button, SIGNAL(clicked()), receiver, member);
156         toolBar->addWidget(button);
157     }
158     // Add menu action, too
159     action = new QAction(text, this);
160     menuBar()->addAction(action);
161     connect(action, SIGNAL(triggered()), receiver, member);
162 #endif
163
164 #if defined Q_WS_MAEMO_5
165     action->setText("");
166     action->setToolTip("");
167 #endif
168
169     return action;
170 }
171
172 void AdopterWindow::addToolBarSpace()
173 {
174 #ifndef Q_OS_SYMBIAN
175     QFrame *frame = new QFrame(toolBar);
176     frame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
177     toolBar->addWidget(frame);
178 #endif
179 }
180
181 void AdopterWindow::grabVolumeKeys(bool grab)
182 {
183     TRACE;
184     grabbingVolumeKeys = grab;
185 #ifdef Q_WS_MAEMO_5
186     doGrabVolumeKeys(grab);
187 #endif
188 }
189
190 #ifdef Q_WS_MAEMO_5
191
192 void AdopterWindow::doGrabVolumeKeys(bool grab)
193 {
194     TRACE;
195     if (!isVisible()) {
196         qDebug() << "Not visible - skipping";
197         return;
198     }
199     if (!winId()) {
200         qDebug() << "Could not get window ID - skipping";
201         return;
202     }
203     unsigned long val = grab? 1: 0;
204     Atom atom =
205             XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False);
206     if (!atom) {
207         qCritical() << "Unable to obtain _HILDON_ZOOM_KEY_ATOM";
208         return;
209     }
210     XChangeProperty(QX11Info::display(),
211         winId(),
212         atom,
213         XA_INTEGER,
214         32,
215         PropModeReplace,
216         reinterpret_cast<unsigned char *>(&val),
217         1);
218     qDebug() << "Grabbed volume keys";
219 }
220
221 #endif // Q_WS_MAEMO_5
222
223 #ifdef Q_OS_SYMBIAN
224
225 void AdopterWindow::updateToolBar()
226 {
227     TRACE;
228     if (toolBar) {
229         QRect geometry = QApplication::desktop()->geometry();
230         bool isPortrait = geometry.width() < geometry.height();
231         bool isToolBarHidden = toolBar->isHidden();
232         if (isPortrait && isToolBarHidden) {
233             qDebug() << "Show tool bar";
234             toolBar->setVisible(true);
235         } else if (!isPortrait && !isToolBarHidden) {
236             qDebug() << "Hide tool bar";
237             toolBar->setVisible(false);
238         }
239     }
240 }
241
242 bool AdopterWindow::portrait()
243 {
244     QRect geometry = QApplication::desktop()->geometry();
245     return geometry.width() < geometry.height();
246 }
247
248 #endif // Q_OS_SYMBIAN
249
250 void AdopterWindow::showEvent(QShowEvent *e)
251 {
252     Trace t("AdopterWindow::showEvent");
253
254 #ifdef Q_OS_SYMBIAN
255     updateToolBar();
256 #endif
257     QMainWindow::showEvent(e);
258 #if defined(Q_WS_MAEMO_5)
259     doGrabVolumeKeys(grabbingVolumeKeys);
260 #endif
261     placeDecorations();
262 }
263
264 void AdopterWindow::resizeEvent(QResizeEvent *event)
265 {
266     Trace t("AdopterWindow::resizeEvent");
267 #ifdef Q_OS_SYMBIAN
268     updateToolBar();
269 #endif
270     QMainWindow::resizeEvent(event);
271     placeDecorations();
272     if (bookView) {
273         QTimer::singleShot(110, bookView, SLOT(restoreLastBookmark()));
274     }
275 }
276
277 void AdopterWindow::closeEvent(QCloseEvent *event)
278 {
279     Trace t("AdopterWindow::closeEvent");
280     if (bookView) {
281         bookView->setLastBookmark();
282     }
283     QMainWindow::closeEvent(event);
284 }
285
286 void AdopterWindow::leaveEvent(QEvent *event)
287 {
288     Trace t("AdopterWindow::leaveEvent");
289     if (bookView) {
290         bookView->setLastBookmark();
291     }
292     QMainWindow::leaveEvent(event);
293 }
294
295 void AdopterWindow::keyPressEvent(QKeyEvent *event)
296 {
297     TRACE;
298     switch (event->key()) {
299     case Qt::Key_PageDown:
300 #ifdef Q_WS_MAEMO_5
301     case Qt::Key_F7:
302 #endif
303         emit pageDown();
304         event->accept();
305         break;
306     case Qt::Key_PageUp:
307 #ifdef Q_WS_MAEMO_5
308     case Qt::Key_F8:
309 #endif
310         emit pageUp();
311         event->accept();
312         break;
313     default:
314         ;
315     }
316     QMainWindow::keyPressEvent(event);
317 }
318
319 void AdopterWindow::onSettingsChanged(const QString &key)
320 {
321     if (key == "usevolumekeys") {
322         bool grab = Settings::instance()->value(key, false).toBool();
323         qDebug() << "AdopterWindow::onSettingsChanged: usevolumekeys" << grab;
324         grabVolumeKeys(grab);
325     }
326 }
327
328 void AdopterWindow::placeDecorations()
329 {
330     Trace t("AdopterWindow::placeDecorations");
331
332     if (!hasBookView()) {
333         return;
334     }
335
336     int toolBarHeight = 0;
337
338     QRect geo = bookView->geometry();
339     qDebug() << "bookView:" << geo;
340
341 #ifdef Q_OS_SYMBIAN
342     // Work around Symbian bug: If tool bar is hidden, increase bottom
343     // decorator widgets' Y coordinates by the tool bar's height
344     if (toolBar && toolBar->isHidden()) {
345         toolBarHeight = toolBar->height();
346     }
347
348     // Work around another Symbian bug: When returning from full screen mode
349     // in landscape, the book view widget's height is miscalculated.
350     // My apologies for this kludge
351     if (geo.height() == 288) {
352         qDebug() << "Adjusting bottom Y";
353         toolBarHeight -= 288 - 223;
354     }
355 #endif // Q_OS_SYMBIAN
356
357     progress->setGeometry(geo.x(),
358         geo.y() + geo.height() - progress->thickness() + toolBarHeight,
359         geo.width(), progress->thickness());
360     previousButton->setGeometry(geo.x(),
361         geo.y() + geo.height() - TranslucentButton::pixels + toolBarHeight,
362         TranslucentButton::pixels, TranslucentButton::pixels);
363     nextButton->setGeometry(
364         geo.x() + geo.width() - TranslucentButton::pixels,
365         geo.y(), TranslucentButton::pixels, TranslucentButton::pixels);
366     progress->flash();
367     previousButton->flash();
368     nextButton->flash();
369     qDebug() << "progress:" << progress->geometry();
370 }
371
372 void AdopterWindow::onPageUp()
373 {
374     if (bookView && grabbingVolumeKeys) {
375         setEnabled(false);
376         bookView->goPreviousPage();
377         setEnabled(true);
378     }
379 }
380
381 void AdopterWindow::onPageDown()
382 {
383     if (bookView && grabbingVolumeKeys) {
384         setEnabled(false);
385         bookView->goNextPage();
386         setEnabled(true);
387     }
388 }
389