/* ============================================================ * * This file is a part of the rekonq project * * Copyright (C) 2008-2010 by Andrea Diamantini * Copyright (C) 2009 by Paweł Prażak * Copyright (C) 2009-2010 by Lionel Chauvin * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * ============================================================ */ // Self Includes #include "application.h" #include "application.moc" // Auto Includes #include "rekonq.h" // Local Includes #include "mainwindow.h" #include "historymanager.h" #include "bookmarkprovider.h" #include "mainview.h" #include "webtab.h" #include "urlbar.h" #include "sessionmanager.h" #include "adblockmanager.h" #include "opensearchmanager.h" #include "webview.h" #include "filterurljob.h" #include "tabbar.h" // KDE Includes #include #include #include #include #include #include #include #include // Qt Includes #include QWeakPointer Application::s_historyManager; QWeakPointer Application::s_bookmarkProvider; QWeakPointer Application::s_sessionManager; QWeakPointer Application::s_adblockManager; QWeakPointer Application::s_opensearchManager; Application::Application() : KUniqueApplication() { connect(Weaver::instance(), SIGNAL(jobDone(ThreadWeaver::Job*)), this, SLOT(loadResolvedUrl(ThreadWeaver::Job*))); } Application::~Application() { // ok, we are closing well. // Don't recover on next load.. ReKonfig::setRecoverOnCrash(0); saveConfiguration(); foreach(QWeakPointer window, m_mainWindows) { delete window.data(); window.clear(); } delete s_bookmarkProvider.data(); s_bookmarkProvider.clear(); delete s_historyManager.data(); s_historyManager.clear(); delete s_sessionManager.data(); s_sessionManager.clear(); delete s_adblockManager.data(); s_adblockManager.clear(); delete s_opensearchManager.data(); s_opensearchManager.clear(); } int Application::newInstance() { KCmdLineArgs::setCwd(QDir::currentPath().toUtf8()); KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); // not that easy, indeed // We have to consider 3 variables here: // 1) Is first load? // 2) Are there arguments? // 3) Is rekonq recovering from crash? // so, we have 8 possible cases... bool isFirstLoad = m_mainWindows.isEmpty(); bool areThereArguments = (args->count() > 0); bool isRekonqCrashed = (ReKonfig::recoverOnCrash() == 1); kDebug() << "is first load? " << isFirstLoad; kDebug() << "are there arguments? " << areThereArguments; kDebug() << "is rekonq crashed? " << isRekonqCrashed; int exitValue = 1 * isFirstLoad + 2 * areThereArguments + 4 * isRekonqCrashed; if(isRekonqCrashed) { if( isFirstLoad && sessionManager()->restoreSession() ) { kDebug() << "session restored from crash"; } } else { if( isFirstLoad && ReKonfig::startupBehaviour() == 2 ) { sessionManager()->restoreSession(); kDebug() << "session restored following settings"; if(areThereArguments) loadUrl( KUrl("about:blank"), Rekonq::NewFocusedTab); } } if(areThereArguments) { KUrl::List urlList; for(int i = 0; i < args->count(); ++i) { const KUrl u = args->url(i); if (u.isLocalFile() && QFile::exists(u.toLocalFile())) // "rekonq somefile.html" case urlList += u; else urlList += KUrl( args->arg(i) ); // "rekonq kde.org" || "rekonq kde:kdialog" case } if (isFirstLoad) { // No windows in the current desktop? No windows at all? // Create a new one and load there sites... loadUrl(urlList.at(0), Rekonq::CurrentTab); for (int i = 1; i < urlList.count(); ++i) loadUrl( urlList.at(i), Rekonq::NewTab); } else { // are there any windows there? use it int index = m_mainWindows.size(); if (index > 0) { MainWindow *m = m_mainWindows.at(index - 1).data(); if(m->isMinimized()) m->showNormal(); if( !m->isActiveWindow() ) { m->activateWindow(); m->raise(); } Q_FOREACH(const KUrl &u, urlList) loadUrl(u, Rekonq::NewFocusedTab); } } } else { if (isFirstLoad) // we are starting rekonq, for the first time with no args: use startup behaviour { switch (ReKonfig::startupBehaviour()) { case 0: // open home page mainWindow()->homePage(); break; case 1: // open new tab page loadUrl(KUrl("about:home")); break; case 2: // restore session // NOTE: this has just been considered break; default: mainWindow()->homePage(); break; } } else // rekonq has just been started. Just open a new window { switch (ReKonfig::newTabsBehaviour()) { case 0: // new tab page loadUrl(KUrl("about:home") , Rekonq::NewWindow); break; case 1: // blank page loadUrl(KUrl("about:blank") , Rekonq::NewWindow); break; case 2: // homepage loadUrl(KUrl(ReKonfig::homePage()) , Rekonq::NewWindow); break; default: loadUrl(KUrl("about:blank") , Rekonq::NewWindow); break; } } } if(isFirstLoad) { // give me some time to do the other things.. QTimer::singleShot(100, this, SLOT(postLaunch())); } return exitValue; } Application *Application::instance() { return (qobject_cast(QCoreApplication::instance())); } void Application::postLaunch() { // updating rekonq configuration updateConfiguration(); setWindowIcon(KIcon("rekonq")); // set Icon Database Path to store "favicons" associated with web sites QString directory = KStandardDirs::locateLocal("cache" , "" , true); QWebSettings::setIconDatabasePath(directory); Application::historyManager(); Application::sessionManager(); // bookmarks loading connect(Application::bookmarkProvider(), SIGNAL(openUrl(const KUrl&, const Rekonq::OpenType&)), Application::instance(), SLOT(loadUrl(const KUrl&, const Rekonq::OpenType&))); // crash recovering int n = ReKonfig::recoverOnCrash(); ReKonfig::setRecoverOnCrash(++n); saveConfiguration(); } void Application::saveConfiguration() const { ReKonfig::self()->writeConfig(); } MainWindow *Application::mainWindow() { if (m_mainWindows.isEmpty()) return newMainWindow(); MainWindow *active = qobject_cast(QApplication::activeWindow()); if (!active) { return m_mainWindows.at(0).data(); } return active; } HistoryManager *Application::historyManager() { if (s_historyManager.isNull()) { s_historyManager = new HistoryManager(); QWebHistoryInterface::setDefaultInterface(s_historyManager.data()); } return s_historyManager.data(); } BookmarkProvider *Application::bookmarkProvider() { if (s_bookmarkProvider.isNull()) { s_bookmarkProvider = new BookmarkProvider(instance()); } return s_bookmarkProvider.data(); } SessionManager *Application::sessionManager() { if (s_sessionManager.isNull()) { s_sessionManager = new SessionManager(instance()); } return s_sessionManager.data(); } OpenSearchManager *Application::opensearchManager() { if (s_opensearchManager.isNull()) { s_opensearchManager = new OpenSearchManager(instance()); s_opensearchManager.data()->setSearchProvider("google"); //TODO: use other suggestion engines } return s_opensearchManager.data(); } KIcon Application::icon(const KUrl &url) { // avoid infinite loop at startup if (Application::instance()->mainWindowList().isEmpty()) return KIcon("text-html"); // first things first.. if (url.isEmpty()) return KIcon("text-html"); // rekonq icons.. if (url == KUrl("about:closedTabs")) return KIcon("tab-close"); if (url == KUrl("about:history")) return KIcon("view-history"); if (url == KUrl("about:bookmarks")) return KIcon("bookmarks"); if (url == KUrl("about:favorites")) return KIcon("emblem-favorite"); KIcon icon = KIcon(QWebSettings::iconForUrl(url)); if (icon.isNull()) { kDebug() << "null icon"; icon = KIcon("text-html"); } return icon; } void Application::loadUrl(const KUrl& url, const Rekonq::OpenType& type) { if (url.isEmpty()) return; if (!url.isValid()) { KMessageBox::error(0, i18n("Malformed URL:\n%1", url.url(KUrl::RemoveTrailingSlash))); return; } // first, create the webview(s) to not let hangs UI.. WebTab *tab = 0; MainWindow *w = 0; w = (type == Rekonq::NewWindow) ? newMainWindow() : mainWindow(); switch (type) { case Rekonq::NewTab: if( ReKonfig::openTabNoWindow() ) tab = w->mainView()->newWebTab( !ReKonfig::openTabsBack() ); else { w = newMainWindow(); tab = w->mainView()->currentWebTab(); } break; case Rekonq::NewFocusedTab: tab = w->mainView()->newWebTab(true); break; case Rekonq::NewBackTab: tab = w->mainView()->newWebTab(false); break; case Rekonq::NewWindow: case Rekonq::CurrentTab: tab = w->mainView()->currentWebTab(); break; }; // rapidly show first loading url.. int tabIndex = w->mainView()->indexOf(tab); Q_ASSERT( tabIndex != -1 ); UrlBar *barForTab = qobject_cast(w->mainView()->widgetBar()->widget(tabIndex)); barForTab->setQUrl(url); WebView *view = tab->view(); if (view) { FilterUrlJob *job = new FilterUrlJob(view, url.pathOrUrl(), this); Weaver::instance()->enqueue(job); } } MainWindow *Application::newMainWindow(bool withTab) { MainWindow *w = new MainWindow(); if (withTab) w->mainView()->newWebTab(); // remember using newWebTab and NOT newTab here!! m_mainWindows.prepend(w); w->show(); return w; } void Application::removeMainWindow(MainWindow *window) { m_mainWindows.removeOne(window); } MainWindowList Application::mainWindowList() { return m_mainWindows; } AdBlockManager *Application::adblockManager() { if (s_adblockManager.isNull()) { s_adblockManager = new AdBlockManager(instance()); } return s_adblockManager.data(); } void Application::loadResolvedUrl(ThreadWeaver::Job *job) { FilterUrlJob *threadedJob = static_cast(job); KUrl url = threadedJob->url(); WebView *view = threadedJob->view(); // Bye and thanks :) delete threadedJob; if (view) { view->load(url); } } void Application::newWindow() { loadUrl(KUrl("about:home"), Rekonq::NewWindow); mainWindow()->mainView()->urlBar()->setFocus(); } void Application::updateConfiguration() { // ============== Tabs ================== bool b = ReKonfig::closeTabSelectPrevious(); Q_FOREACH(const QWeakPointer &w, m_mainWindows) { MainView *mv = w.data()->mainView(); mv->updateTabBar(); if (b) mv->tabBar()->setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); else mv->tabBar()->setSelectionBehaviorOnRemove(QTabBar::SelectRightTab); } QWebSettings *defaultSettings = QWebSettings::globalSettings(); // =========== Fonts ============== defaultSettings->setFontFamily(QWebSettings::StandardFont, ReKonfig::standardFontFamily() ); defaultSettings->setFontFamily(QWebSettings::FixedFont, ReKonfig::fixedFontFamily() ); defaultSettings->setFontFamily(QWebSettings::SerifFont, ReKonfig::serifFontFamily() ); defaultSettings->setFontFamily(QWebSettings::SansSerifFont, ReKonfig::sansSerifFontFamily() ); defaultSettings->setFontFamily(QWebSettings::CursiveFont, ReKonfig::cursiveFontFamily()); defaultSettings->setFontFamily(QWebSettings::FantasyFont, ReKonfig::fantasyFontFamily()); // compute font size // (I have to admit I know nothing about these DPI questions..: copied from kwebkitpart, as someone suggested) // font size in pixels = font size in inches × screen dpi int defaultFontSize = ReKonfig::defaultFontSize(); int minimumFontSize = ReKonfig::minFontSize(); int logDpiY = mainWindow()->currentTab()->view()->logicalDpiY(); kDebug() << "Logical Dot per Inch Y: " << logDpiY; float toPix = (logDpiY < 96.0) ? 96.0/72.0 : logDpiY/72.0 ; defaultSettings->setFontSize(QWebSettings::DefaultFontSize, qRound(defaultFontSize * toPix) ); defaultSettings->setFontSize(QWebSettings::MinimumFontSize, qRound(minimumFontSize * toPix) ); // ================ WebKit ============================ defaultSettings->setAttribute(QWebSettings::AutoLoadImages, ReKonfig::autoLoadImages()); defaultSettings->setAttribute(QWebSettings::DnsPrefetchEnabled, ReKonfig::dnsPrefetch()); defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, ReKonfig::javascriptEnabled()); defaultSettings->setAttribute(QWebSettings::JavaEnabled, ReKonfig::javaEnabled()); defaultSettings->setAttribute(QWebSettings::JavascriptCanOpenWindows, ReKonfig::javascriptCanOpenWindows()); defaultSettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, ReKonfig::javascriptCanAccessClipboard()); defaultSettings->setAttribute(QWebSettings::LinksIncludedInFocusChain, ReKonfig::linksIncludedInFocusChain()); defaultSettings->setAttribute(QWebSettings::ZoomTextOnly, ReKonfig::zoomTextOnly()); defaultSettings->setAttribute(QWebSettings::PrintElementBackgrounds, ReKonfig::printElementBackgrounds()); if (ReKonfig::pluginsEnabled() == 2) defaultSettings->setAttribute(QWebSettings::PluginsEnabled, false); else defaultSettings->setAttribute(QWebSettings::PluginsEnabled, true); // ===== HTML 5 features WebKit support ====== defaultSettings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, ReKonfig::offlineStorageDatabaseEnabled()); defaultSettings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, ReKonfig::offlineWebApplicationCacheEnabled()); defaultSettings->setAttribute(QWebSettings::LocalStorageEnabled, ReKonfig::localStorageEnabled()); if (ReKonfig::localStorageEnabled()) { QString path = KStandardDirs::locateLocal("cache", QString("WebkitLocalStorage/rekonq"), true); path.remove("rekonq"); QWebSettings::setOfflineStoragePath(path); QWebSettings::setOfflineStorageDefaultQuota(50000); } // Applies user defined CSS to all open webpages. If there no longer is a // user defined CSS removes it from all open webpages. if (!ReKonfig::userCSS().isEmpty()) defaultSettings->setUserStyleSheetUrl(ReKonfig::userCSS()); // ====== load Settings on main classes Application::historyManager()->loadSettings(); Application::adblockManager()->loadSettings(); defaultSettings = 0; } void Application::addDownload(const QString &srcUrl, const QString &destUrl) { QWebSettings *globalSettings = QWebSettings::globalSettings(); if (globalSettings->testAttribute(QWebSettings::PrivateBrowsingEnabled)) return; QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); QFile downloadFile(downloadFilePath); if (!downloadFile.open(QFile::WriteOnly | QFile::Append)) { kDebug() << "Unable to open download file (WRITE mode).."; return; } QDataStream out(&downloadFile); out << srcUrl; out << destUrl; out << QDateTime::currentDateTime(); downloadFile.close(); } DownloadList Application::downloads() { DownloadList list; QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); QFile downloadFile(downloadFilePath); if (!downloadFile.open(QFile::ReadOnly)) { kDebug() << "Unable to open download file (READ mode).."; return list; } QDataStream in(&downloadFile); while (!in.atEnd()) { QString srcUrl; in >> srcUrl; QString destUrl; in >> destUrl; QDateTime dt; in >> dt; DownloadItem item(srcUrl, destUrl, dt); list << item; } return list; } bool Application::clearDownloadsHistory() { QString downloadFilePath = KStandardDirs::locateLocal("appdata" , "downloads"); QFile downloadFile(downloadFilePath); return downloadFile.remove(); }