1 /* ============================================================
3 * This file is a part of the rekonq project
5 * Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com>
6 * Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com>
7 * Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
8 * Copyright (C) 2010 by Matthieu Gicquel <matgic78 at gmail dot com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License or (at your option) version 3 or any later version
15 * accepted by the membership of KDE e.V. (or its successor approved
16 * by the membership of KDE e.V.), which shall act as a proxy
17 * defined in Section 14 of version 3 of the license.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 * ============================================================ */
32 #include "mainview.moc"
40 #include "sessionmanager.h"
46 #include <KStandardShortcut>
47 #include <KMessageBox>
48 #include <KStandardDirs>
49 #include <KPassivePopup>
50 #include <KLocalizedString>
60 #include <QVBoxLayout>
63 MainView::MainView(MainWindow *parent)
65 , _widgetBar(new StackedUrlBar(this))
67 , m_currentTabIndex(0)
68 , m_parentWindow(parent)
71 TabBar *tabBar = new TabBar(this);
72 m_addTabButton = new QToolButton(this);
75 // set mouse tracking for tab previews
76 setMouseTracking(true);
78 // loading pixmap path
79 m_loadingGitPath = KStandardDirs::locate("appdata" , "pics/loading.mng");
81 // connecting tabbar signals
82 connect(tabBar, SIGNAL(closeTab(int)), this, SLOT(closeTab(int)));
83 connect(tabBar, SIGNAL(mouseMiddleClick(int)), this, SLOT(closeTab(int)));
84 connect(tabBar, SIGNAL(newTabRequest()), this, SLOT(newTab()));
86 connect(tabBar, SIGNAL(cloneTab(int)), this, SLOT(cloneTab(int)));
87 connect(tabBar, SIGNAL(closeOtherTabs(int)), this, SLOT(closeOtherTabs(int)));
88 connect(tabBar, SIGNAL(reloadTab(int)), this, SLOT(reloadTab(int)));
89 connect(tabBar, SIGNAL(reloadAllTabs()), this, SLOT(reloadAllTabs()));
90 connect(tabBar, SIGNAL(detachTab(int)), this, SLOT(detachTab(int)));
92 connect(tabBar, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
93 connect(tabBar, SIGNAL(tabMoved(int, int)), _widgetBar, SLOT(moveBar(int, int)));
95 // current page index changing
96 connect(this, SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int)));
98 QTimer::singleShot(0, this, SLOT(postLaunch()));
102 MainView::~MainView()
105 delete m_addTabButton;
109 void MainView::postLaunch()
111 QStringList list = Application::sessionManager()->closedSites();
112 foreach(const QString &line, list)
114 if(line.startsWith( QL1S("about") ))
116 QString title = line;
118 HistoryItem item(url, QDateTime::currentDateTime(), title);
119 m_recentlyClosedTabs.removeAll(item);
120 m_recentlyClosedTabs.prepend(item);
124 connect(this, SIGNAL(tabsChanged()), Application::sessionManager(), SLOT(saveSession()));
125 connect(this, SIGNAL(currentChanged(int)), Application::sessionManager(), SLOT(saveSession()));
127 m_addTabButton->setDefaultAction(m_parentWindow->actionByName("new_tab"));
129 m_addTabButton->setAutoRaise(true);
130 m_addTabButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
134 void MainView::updateTabButtonPosition()
136 static bool ButtonInCorner = false;
138 int tabWidgetWidth = frameSize().width();
139 int tabBarWidth = tabBar()->tabSizeHint(0).width() * tabBar()->count();
141 if (tabBarWidth + m_addTabButton->width() > tabWidgetWidth)
145 setCornerWidget(m_addTabButton);
146 ButtonInCorner = true;
153 m_addTabButton->show();
154 ButtonInCorner = false;
157 // detecting X position
158 int newPosX = tabBarWidth;
159 int tabWidthHint = tabBar()->tabSizeHint(0).width();
160 if (tabWidthHint < sizeHint().width() / 4)
161 newPosX = tabWidgetWidth - m_addTabButton->width();
163 m_addTabButton->move(newPosX, 0);
168 TabBar *MainView::tabBar() const
170 TabBar *tabBar = qobject_cast<TabBar *>(KTabWidget::tabBar());
175 UrlBar *MainView::urlBar() const
177 return _widgetBar->urlBar(m_currentTabIndex);
181 WebTab *MainView::currentWebTab() const
183 return webTab(currentIndex());
187 void MainView::updateTabBar()
189 if (ReKonfig::alwaysShowTabBar())
191 if (!isTabBarHidden())
193 if (tabBar()->isHidden())
196 m_addTabButton->show();
198 updateTabButtonPosition();
203 if (tabBar()->count() == 1)
206 m_addTabButton->hide();
208 else if (!isTabBarHidden())
210 if (tabBar()->isHidden())
213 m_addTabButton->show();
215 updateTabButtonPosition();
220 void MainView::setTabBarHidden(bool hide)
222 m_addTabButton->setVisible(!hide);
223 KTabWidget::setTabBarHidden(hide);
227 void MainView::webReload()
229 WebTab *webTab = currentWebTab();
230 QAction *action = webTab->view()->page()->action(QWebPage::Reload);
235 void MainView::webStop()
237 WebTab *webTab = currentWebTab();
238 QAction *action = webTab->view()->page()->action(QWebPage::Stop);
243 // When index is -1 index chooses the current tab
244 void MainView::reloadTab(int index)
247 index = currentIndex();
248 if (index < 0 || index >= count())
251 webTab(index)->view()->reload();
255 // this slot is called on tab switching
256 void MainView::currentChanged(int index)
258 // retrieve the webview related to the index
259 WebTab *tab = this->webTab(index);
263 // retrieve the old webview (that where we move from)
264 WebTab *oldTab = this->webTab(m_currentTabIndex);
267 m_currentTabIndex = index;
271 // disconnecting webpage from mainview
272 disconnect(oldTab->page(), SIGNAL(statusBarMessage(const QString&)),
273 this, SIGNAL(showStatusBarMessage(const QString&)));
274 disconnect(oldTab->page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)),
275 this, SIGNAL(linkHovered(const QString&)));
278 connect(tab->page(), SIGNAL(statusBarMessage(const QString&)),
279 this, SIGNAL(showStatusBarMessage(const QString&)));
280 connect(tab->page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)),
281 this, SIGNAL(linkHovered(const QString&)));
283 emit currentTitle(tab->view()->title());
284 _widgetBar->setCurrentIndex(index);
286 // clean up "status bar"
287 emit showStatusBarMessage(QString());
289 // notify UI to eventually switch stop/reload button
290 int progr = tab->progress();
292 emit browserTabLoading(false);
294 emit browserTabLoading(true);
296 // update zoom slider
297 if (!Application::instance()->mainWindowList().isEmpty())
298 Application::instance()->mainWindow()->setZoomSliderFactor(tab->view()->zoomFactor());
300 // set focus to the current webview
301 if (tab->url().scheme() == QL1S("about"))
302 _widgetBar->currentWidget()->setFocus();
304 tab->view()->setFocus();
308 WebTab *MainView::webTab(int index) const
310 WebTab *tab = qobject_cast<WebTab *>(this->widget(index));
316 kDebug() << "WebTab with index " << index << "not found. Returning NULL." ;
321 WebTab *MainView::newWebTab(bool focused, bool nearParent)
323 WebTab* tab = new WebTab(this);
324 UrlBar *bar = new UrlBar(tab);
326 // connecting webview with mainview
327 connect(tab->view(), SIGNAL(loadStarted()), this, SLOT(webViewLoadStarted()));
328 connect(tab->view(), SIGNAL(loadFinished(bool)), this, SLOT(webViewLoadFinished(bool)));
329 connect(tab->view(), SIGNAL(iconChanged()), this, SLOT(webViewIconChanged()));
330 connect(tab->view(), SIGNAL(titleChanged(const QString &)), this, SLOT(webViewTitleChanged(const QString &)));
331 connect(tab->view(), SIGNAL(urlChanged(const QUrl &)), this, SLOT(webViewUrlChanged(const QUrl &)));
333 // connecting webPage signals with mainview
334 connect(tab->view()->page(), SIGNAL(windowCloseRequested()), this, SLOT(windowCloseRequested()));
335 connect(tab->view()->page(), SIGNAL(printRequested(QWebFrame *)), this, SIGNAL(printRequested(QWebFrame *)));
339 insertTab(currentIndex() + 1, tab, i18n("(Untitled)"));
340 _widgetBar->insertWidget(currentIndex() + 1, bar);
344 addTab(tab, i18n("(Untitled)"));
345 _widgetBar->addWidget(bar);
351 setCurrentWidget(tab);
360 void MainView::newTab()
362 WebView *w = newWebTab()->view();
364 switch (ReKonfig::newTabsBehaviour())
366 case 0: // new tab page
367 w->load(KUrl("about:home"));
369 case 1: // blank page
373 w->load(KUrl(ReKonfig::homePage()));
378 urlBar()->setFocus();
382 void MainView::reloadAllTabs()
384 for (int i = 0; i < count(); ++i)
386 webTab(i)->view()->reload();
391 void MainView::windowCloseRequested()
393 WebPage *page = qobject_cast<WebPage *>(sender());
394 WebView *view = qobject_cast<WebView *>(page->view());
395 int index = indexOf(view->parentWidget());
401 m_parentWindow->close();
409 kDebug() << "Invalid tab index" << "line:" << __LINE__;
413 void MainView::closeOtherTabs(int index)
418 for (int i = count() - 1; i > index; --i)
423 for (int i = index - 1; i >= 0; --i)
432 // When index is -1 index chooses the current tab
433 void MainView::cloneTab(int index)
436 index = currentIndex();
437 if (index < 0 || index >= count())
440 WebTab *tab = newWebTab();
441 KUrl url = webTab(index)->url();
443 // workaround against bug in webkit:
444 // only set url if it is not empty
445 // otherwise the current working directory will be used
447 tab->view()->setUrl(url);
453 // When index is -1 index chooses the current tab
454 void MainView::closeTab(int index, bool del)
456 // open default homePage if just one tab is opened
459 WebView *w = currentWebTab()->view();
461 if( currentWebTab()->url().protocol() == QL1S("about") )
464 switch (ReKonfig::newTabsBehaviour())
466 case 0: // new tab page
467 case 1: // blank page
468 w->load(KUrl("about:home"));
469 urlBar()->setFocus();
472 w->load(KUrl(ReKonfig::homePage()));
481 index = currentIndex();
482 if (index < 0 || index >= count())
485 WebTab *tab = webTab(index);
489 if (tab->view()->isModified())
491 int risp = KMessageBox::warningContinueCancel(this,
492 i18n("This tab contains changes that have not been submitted.\n"
493 "Closing the tab will discard these changes.\n"
494 "Do you really want to close this tab?\n"),
495 i18n("Closing Modified Tab"), KGuiItem(i18n("Close &Tab"), "tab-close"), KStandardGuiItem::cancel());
496 if (risp != KMessageBox::Continue)
500 if (!tab->url().isEmpty())
502 QString title = tab->view()->title();
503 QString url = tab->url().prettyUrl();
504 HistoryItem item(url, QDateTime::currentDateTime(), title);
505 m_recentlyClosedTabs.removeAll(item);
506 m_recentlyClosedTabs.prepend(item);
510 updateTabBar(); // UI operation: do it ASAP!!
512 UrlBar *urlbar = _widgetBar->urlBar(index);
513 _widgetBar->removeWidget(urlbar);
515 _widgetBar->setCurrentIndex(m_currentTabIndex);
519 tab->deleteLater(); // tab is scheduled for deletion.
520 urlbar->deleteLater();
527 void MainView::webViewLoadStarted()
529 WebView *view = qobject_cast<WebView *>(sender());
530 int index = indexOf(view->parentWidget());
533 QLabel *label = animatedLoading(index, true);
536 label->movie()->start();
540 if (index != currentIndex())
543 emit browserTabLoading(true);
544 emit showStatusBarMessage(i18n("Loading..."));
548 void MainView::webViewLoadFinished(bool ok)
550 WebView *view = qobject_cast<WebView *>(sender());
553 index = indexOf(view->parentWidget());
557 QLabel *label = animatedLoading(index, true);
558 QMovie *movie = label->movie();
563 webViewIconChanged();
564 emit browserTabLoading(false);
566 // don't display messages for background tabs
567 if (index != currentIndex())
573 emit showStatusBarMessage(i18n("Done"), Rekonq::Success);
575 // emit showStatusBarMessage(i18n("Failed to load"), Rekonq::Error);
579 void MainView::webViewIconChanged()
581 WebView *view = qobject_cast<WebView *>(sender());
582 int index = indexOf(view->parentWidget());
585 KIcon icon = Application::icon(view->url());
586 QLabel *label = animatedLoading(index, false);
587 QMovie *movie = label->movie();
590 label->setPixmap(icon.pixmap(16, 16));
595 void MainView::webViewTitleChanged(const QString &title)
597 QString tabTitle = title;
600 tabTitle = i18n("(Untitled)");
602 WebView *view = qobject_cast<WebView *>(sender());
603 int index = indexOf(view->parentWidget());
606 setTabText(index, tabTitle);
608 if (currentIndex() == index)
610 emit currentTitle(tabTitle);
612 Application::historyManager()->updateHistoryEntry(view->url(), tabTitle);
616 void MainView::webViewUrlChanged(const QUrl &url)
618 WebView *view = qobject_cast<WebView *>(sender());
619 int index = indexOf(view->parentWidget());
622 tabBar()->setTabData(index, url);
628 void MainView::nextTab()
630 int next = currentIndex() + 1;
633 setCurrentIndex(next);
637 void MainView::previousTab()
639 int next = currentIndex() - 1;
642 setCurrentIndex(next);
645 void MainView::openClosedTabs()
647 foreach (const HistoryItem &item, recentlyClosedTabs())
649 Application::instance()->loadUrl( KUrl(item.url), Rekonq::SettingOpenTab);
653 void MainView::openClosedTab()
655 KAction *action = qobject_cast<KAction *>(sender());
658 Application::instance()->loadUrl(action->data().toUrl(), Rekonq::SettingOpenTab);
662 void MainView::switchToTab()
664 // uses the sender to determine the tab index
665 QAction *sender = static_cast<QAction*>(QObject::sender());
666 int index = sender->data().toInt();
667 index -= 1; // to compensate for off by 1 presented to the user
668 if( index < 0 || index >= count() )
670 setCurrentIndex( index );
673 QLabel *MainView::animatedLoading(int index, bool addMovie)
678 QLabel *label = qobject_cast<QLabel* >(tabBar()->tabButton(index, QTabBar::LeftSide));
681 label = new QLabel(this);
683 if (addMovie && !label->movie())
685 QMovie *movie = new QMovie(m_loadingGitPath, QByteArray(), label);
687 label->setMovie(movie);
690 tabBar()->setTabButton(index, QTabBar::LeftSide, 0);
691 tabBar()->setTabButton(index, QTabBar::LeftSide, label);
696 void MainView::resizeEvent(QResizeEvent *event)
699 KTabWidget::resizeEvent(event);
703 void MainView::detachTab(int index)
706 index = currentIndex();
707 if (index < 0 || index >= count())
710 WebTab *tab = webTab(index);
713 if (u.scheme() == QL1S("about"))
716 Application::instance()->loadUrl(u, Rekonq::NewWindow);
720 QString label = tab->view()->title();
721 UrlBar *bar = _widgetBar->urlBar(index);
722 closeTab(index, false);
724 MainWindow *w = Application::instance()->newMainWindow(false);
725 w->mainView()->addTab(tab, Application::icon(u), label);
726 _widgetBar->insertWidget(0, bar);
727 w->mainView()->updateTabBar();