|
1 #include "BrowserWindow.h" |
|
2 #include "WindowsView.h" |
|
3 #include "ChromeLayout.h" |
|
4 #include "ChromeWidget.h" |
|
5 #include "ChromeView.h" |
|
6 #include "ChromeDOM.h" //Get rid of this dependency |
|
7 #include "GWebContentView.h" |
|
8 #include <QGraphicsWidget> |
|
9 #include <QGraphicsScene> |
|
10 #include <QGraphicsTextItem> |
|
11 #include <QVBoxLayout> |
|
12 #include "webpagecontroller.h" |
|
13 #include "ViewStack.h" |
|
14 #ifdef Q_WS_MAEMO_5 |
|
15 #include <QtGui/QX11Info> |
|
16 #include <X11/Xlib.h> |
|
17 #include <X11/Xatom.h> |
|
18 #endif |
|
19 |
|
20 namespace GVA { |
|
21 |
|
22 bool BrowserWindow::m_preventDisconnectPageTitleChanged = false; // workaraound for multiple windows crash |
|
23 bool BrowserWindow::m_preventConnectPageTitleChanged = false; // workaround for multiple windows crash |
|
24 |
|
25 BrowserWindow::BrowserWindow(ChromeWidget * chrome, WindowsView * windows, QWidget * parent, Qt::WindowFlags flags) |
|
26 : QMainWindow(parent, flags), |
|
27 m_page(0), |
|
28 m_specialPage(0), |
|
29 m_decorated(false), |
|
30 m_chrome(chrome), |
|
31 m_scene(new QGraphicsScene()), |
|
32 m_snapshot(0), |
|
33 m_windows(windows), |
|
34 m_state(menuEnabled), |
|
35 m_slidedUp(false), |
|
36 m_viewName("WebView"), |
|
37 m_changingMode(false) |
|
38 { |
|
39 m_view = new ChromeView(m_scene, m_chrome, this); |
|
40 setCentralWidget(m_view); |
|
41 show(); |
|
42 ViewController *controller = viewController(); |
|
43 if(controller) { |
|
44 connect(controller, SIGNAL(currentViewChanged(ControllableViewBase *)), this, SLOT(onViewChanged(ControllableViewBase *))); |
|
45 } |
|
46 slideViewIfRequired(100); // display UrlSearchBar for every new window |
|
47 } |
|
48 |
|
49 void BrowserWindow::setPage(WRT::WrtBrowserContainer * page) |
|
50 { |
|
51 m_page = page; |
|
52 connectPageTitleChanged(); |
|
53 } |
|
54 |
|
55 // hide or show UrlSearchBar if required |
|
56 // This is a workaround for the problem that created by the fact that |
|
57 // multiple instances of BrowserWindow use same instance of m_chrome and m_chrome->layout() |
|
58 // |
|
59 void BrowserWindow::slideViewIfRequired(int value) |
|
60 { |
|
61 if(value > 0) { // slide up to display UrlSearchBar |
|
62 m_chrome->layout()->slideView(value); |
|
63 m_slidedUp = true; |
|
64 return; |
|
65 } |
|
66 |
|
67 if((m_slidedUp == true) && (value < 0)) { // slide down UrlSearchBar |
|
68 m_chrome->layout()->slideView(value); |
|
69 m_slidedUp = false; |
|
70 return; |
|
71 } |
|
72 } |
|
73 |
|
74 void BrowserWindow::toggleDecoration() |
|
75 { |
|
76 m_decorated = !m_decorated; |
|
77 if(m_decorated) { |
|
78 showDecoration(); |
|
79 } |
|
80 else { |
|
81 hideDecoration(); |
|
82 } |
|
83 } |
|
84 |
|
85 void BrowserWindow::showDecoration() |
|
86 { |
|
87 m_state |= active; |
|
88 if(m_page) |
|
89 WebPageController::getSingleton()->setCurrentPage(m_page); |
|
90 m_windows->deactivate(this); |
|
91 if(m_snapshot) |
|
92 m_snapshot->hide(); |
|
93 if(m_chrome){ |
|
94 m_chrome->layout()->setPos(0,0); |
|
95 m_scene->addItem(m_chrome->layout()); |
|
96 m_chrome->layout()->show(); |
|
97 // Ensure that the layout size is in-synch with the window size. |
|
98 m_chrome->layout()->resize(size()); |
|
99 } |
|
100 } |
|
101 |
|
102 void BrowserWindow::hideDecoration() |
|
103 { |
|
104 m_state &= ~active; |
|
105 |
|
106 m_windows->activate(this); |
|
107 if(m_chrome) |
|
108 m_scene->removeItem(m_chrome->layout()); |
|
109 |
|
110 if(m_page){ |
|
111 m_page->triggerAction(QWebPage::Stop); |
|
112 //QImage image = WebPageController::getSingleton()->pageThumbnail(m_page); |
|
113 // if(image.isNull()){ |
|
114 //QImage image = m_page->pageThumbnail(1,1); |
|
115 // |
|
116 |
|
117 QImage image; |
|
118 //This is really a bit hackish: the page controller should be able |
|
119 //to figure this out; |
|
120 //if(m_windows->contentView()->currentPageIsSuperPage()){ |
|
121 //m_specialPage = static_cast<WRT::WrtBrowserContainer*>(m_windows->contentView()->wrtPage()); |
|
122 //m_windows->contentView()->updateWebPage(m_page); |
|
123 //image = m_windows->contentView()->pageThumbnail(1,1); |
|
124 //} |
|
125 //else |
|
126 QSize s(800,464); |
|
127 image = m_page->thumbnail(s); |
|
128 if(m_snapshot){ |
|
129 m_scene->removeItem(m_snapshot); |
|
130 delete m_snapshot; |
|
131 } |
|
132 m_snapshot = new QGraphicsPixmapItem(QPixmap::fromImage(image)); |
|
133 m_scene->addItem(m_snapshot); |
|
134 m_snapshot->show(); |
|
135 } else { |
|
136 qDebug() << "BrowserWindow::hideDecoration: page not set"; |
|
137 } |
|
138 } |
|
139 |
|
140 void BrowserWindow::closeWindow() |
|
141 { |
|
142 //Tell the page controler to close this page. |
|
143 //The controller emits pageClosed. WindowsView |
|
144 //handles this and deletes this browser window |
|
145 // Don't delete if only 1 window open..causes crash on exit |
|
146 if (WebPageController::getSingleton()->pageCount() > 1) |
|
147 WebPageController::getSingleton()->closePage(m_page); |
|
148 } |
|
149 |
|
150 //Handle window events |
|
151 bool BrowserWindow::event(QEvent * event) |
|
152 { |
|
153 //qDebug() << "=====================BrowserWindow:event: " << event->type(); |
|
154 switch (event->type()) { |
|
155 case QEvent::WindowBlocked: |
|
156 m_state |= blocked; |
|
157 break; |
|
158 case QEvent::WindowUnblocked: |
|
159 m_state &= ~blocked; |
|
160 break; |
|
161 case QEvent::WindowActivate: //Newly shown window or window maximized |
|
162 handleWindowActivate(); |
|
163 m_chrome->windowStateChange(windowState()); |
|
164 break; |
|
165 case QEvent::WindowDeactivate: |
|
166 handleWindowDeactivate(); |
|
167 m_chrome->windowStateChange(windowState()); |
|
168 break; |
|
169 case QEvent::Close: |
|
170 m_state |= blocked; |
|
171 closeWindow(); |
|
172 break; |
|
173 default: |
|
174 break; |
|
175 } |
|
176 return QMainWindow::event(event); |
|
177 } |
|
178 |
|
179 void BrowserWindow::changeEvent(QEvent * event) { |
|
180 switch (event->type()) { |
|
181 case QEvent::WindowStateChange: |
|
182 m_chrome->windowStateChange(windowState()); |
|
183 break; |
|
184 default: |
|
185 break; |
|
186 } |
|
187 QMainWindow::changeEvent(event); |
|
188 } |
|
189 |
|
190 void BrowserWindow::handleWindowActivate() { |
|
191 if(m_changingMode) { |
|
192 // Ignore if in the process of changing from fullscreen to normal. We get a deactivate followed by |
|
193 // an activate call when this is done. Clear the flag for the next time activate or deactivate is |
|
194 // called for some other reason. |
|
195 m_changingMode = false; |
|
196 return; |
|
197 } |
|
198 #ifdef Q_WS_MAEMO_5 |
|
199 grabZoomKeys(true); |
|
200 #endif |
|
201 showDecoration(); |
|
202 if(m_chrome) { |
|
203 connect(m_chrome, SIGNAL(requestToggleNormalFullScreen()), this, SLOT(toggleNormalFullScreen())); |
|
204 } |
|
205 } |
|
206 |
|
207 void BrowserWindow::handleWindowDeactivate() { |
|
208 if(m_changingMode) { |
|
209 // Ignore if in the process of changing from fullscreen to normal. |
|
210 return; |
|
211 } |
|
212 #ifdef Q_WS_MAEMO_5 |
|
213 grabZoomKeys(false); |
|
214 #endif |
|
215 if(!((m_state & blocked) == blocked)) |
|
216 hideDecoration(); |
|
217 slideViewIfRequired(-100); // hide UrlSearchBar if required |
|
218 if(m_chrome) { |
|
219 disconnect(m_chrome, SIGNAL(requestToggleNormalFullScreen()), this, SLOT(toggleNormalFullScreen())); |
|
220 } |
|
221 } |
|
222 |
|
223 void BrowserWindow::setMenuEnabled(bool enabled) |
|
224 { |
|
225 if(enabled) |
|
226 m_state |= menuEnabled; |
|
227 else |
|
228 m_state &= ~menuEnabled; |
|
229 |
|
230 fixupWindowTitle(); |
|
231 } |
|
232 |
|
233 void BrowserWindow::setTitle(const QString &title) |
|
234 { |
|
235 if(title.isEmpty()) { |
|
236 setWindowTitle(QApplication::applicationName()); |
|
237 } |
|
238 else { |
|
239 setWindowTitle(title); |
|
240 } |
|
241 |
|
242 fixupWindowTitle(); |
|
243 } |
|
244 |
|
245 /// Hack to hide the menu bar arrow when the menu is disabled. |
|
246 void BrowserWindow::fixupWindowTitle() { |
|
247 QString title = windowTitle(); |
|
248 title = title.trimmed(); |
|
249 if(!m_windows->isMenuEnabled()) { |
|
250 // The menu is disabled, add some spaces to the title to push the down arrow out of view. |
|
251 title += QString(60, ' '); |
|
252 } |
|
253 setWindowTitle(title); |
|
254 } |
|
255 |
|
256 void BrowserWindow::onPageTitleChanged(const QString &title) |
|
257 { |
|
258 setTitle(title); |
|
259 } |
|
260 |
|
261 void BrowserWindow::onViewChanged(ControllableViewBase *newView) { |
|
262 Q_ASSERT(newView); |
|
263 |
|
264 if(m_windows->contentView()->currentPageIsSuperPage()) { |
|
265 if(!m_preventDisconnectPageTitleChanged) |
|
266 disconnectPageTitleChanged(); |
|
267 m_preventDisconnectPageTitleChanged = true; |
|
268 m_preventConnectPageTitleChanged = false; |
|
269 } |
|
270 else { |
|
271 if(!m_preventConnectPageTitleChanged) |
|
272 connectPageTitleChanged(); |
|
273 m_preventDisconnectPageTitleChanged = false; |
|
274 m_preventConnectPageTitleChanged = true; |
|
275 } |
|
276 if(m_state & active) { |
|
277 setTitle(newView->title()); |
|
278 } |
|
279 } |
|
280 |
|
281 ViewController *BrowserWindow::viewController() { |
|
282 ViewStack *viewStack = ViewStack::getSingleton(); |
|
283 if(viewStack) { |
|
284 return viewStack->getViewController(); |
|
285 } |
|
286 |
|
287 return 0; |
|
288 } |
|
289 |
|
290 void BrowserWindow::connectPageTitleChanged() { |
|
291 connect(m_page->mainFrame(), SIGNAL(titleChanged(const QString &)), |
|
292 this, SLOT(onPageTitleChanged(const QString &))); |
|
293 } |
|
294 |
|
295 void BrowserWindow::disconnectPageTitleChanged() { |
|
296 disconnect(m_page->mainFrame(), SIGNAL(titleChanged(const QString &)), |
|
297 this, SLOT(onPageTitleChanged(const QString &))); |
|
298 } |
|
299 |
|
300 |
|
301 void BrowserWindow::toggleNormalFullScreen() { |
|
302 m_changingMode = true; |
|
303 |
|
304 // Block paint updates while switching modes. This avoids ugly flicker in toolbar. |
|
305 setUpdatesEnabled(false); |
|
306 |
|
307 if(isFullScreen()) |
|
308 showNormal(); |
|
309 else { |
|
310 // Show full screen unless it's showing a super page: bookmarks, histroy etc. should always |
|
311 // be in normal mode. |
|
312 if(!m_windows->contentView()->currentPageIsSuperPage()) { |
|
313 showFullScreen(); |
|
314 } |
|
315 } |
|
316 // Un-block updates. |
|
317 setUpdatesEnabled(true); |
|
318 } |
|
319 |
|
320 #ifdef Q_WS_MAEMO_5 |
|
321 // Tell the system we want to handle volume key events (or not). |
|
322 void BrowserWindow::grabZoomKeys(bool grab) |
|
323 { |
|
324 if (!winId()) { |
|
325 qWarning("Can't grab keys unless we have a window id"); |
|
326 return; |
|
327 } |
|
328 |
|
329 unsigned long val = (grab) ? 1 : 0; |
|
330 Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False); |
|
331 if (!atom) { |
|
332 qWarning("Unable to obtain _HILDON_ZOOM_KEY_ATOM. This example will only work " |
|
333 "on a Maemo 5 device!"); |
|
334 return; |
|
335 } |
|
336 |
|
337 XChangeProperty (QX11Info::display(), |
|
338 winId(), |
|
339 atom, |
|
340 XA_INTEGER, |
|
341 32, |
|
342 PropModeReplace, |
|
343 reinterpret_cast<unsigned char *>(&val), |
|
344 1); |
|
345 } |
|
346 |
|
347 void BrowserWindow::keyPressEvent(QKeyEvent* event) |
|
348 { |
|
349 switch (event->key()) { |
|
350 case Qt::Key_F7: |
|
351 { |
|
352 // Handle "volume down" key by triggering zoom-in. |
|
353 ControllableViewBase *view = m_chrome->getView("WebView"); |
|
354 if(view) { |
|
355 view->triggerAction("ZoomIn"); |
|
356 } |
|
357 event->accept(); |
|
358 } |
|
359 break; |
|
360 |
|
361 case Qt::Key_F8: |
|
362 { |
|
363 // Handle "volume up" key by triggering zoom-out. |
|
364 ControllableViewBase *view = m_chrome->getView("WebView"); |
|
365 if(view) { |
|
366 view->triggerAction("ZoomOut"); |
|
367 } |
|
368 event->accept(); |
|
369 } |
|
370 break; |
|
371 } |
|
372 QWidget::keyPressEvent(event); |
|
373 } |
|
374 #endif |
|
375 }; |