/* ============================================================
*
* This file is a part of the rekonq project
*
* Copyright (C) 2012 by Andrea Diamantini <adjam7 at gmail dot com>
*
*
* 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 <http://www.gnu.org/licenses/>.
*
* ============================================================ */


// Self Includes
#include "application.h"
#include "application.moc"

// Auto Includes
#include "rekonq.h"

// Ui Includes
#include "ui_webappcreation.h"

// Local Includes
#include "searchengine.h"

#include "tabbar.h"
#include "tabwindow.h"

#include "webwindow.h"
#include "webtab.h"
#include "webpage.h"

#include "urlresolver.h"

// Local Manager(s) Includes
#include "adblockmanager.h"
#include "downloadmanager.h"
#include "historymanager.h"
#include "iconmanager.h"
#include "sessionmanager.h"

// Ui Includes
#include "ui_cleardata.h"

// KDE Includes
#include <KCmdLineArgs>

#include <KDialog>
#include <KProcess>
#include <KPushButton>
#include <KStandardDirs>
#include <KWindowSystem>
#include <KWindowInfo>
#include <KStartupInfo>

#include <KMessageBox>

// Qt Includes
#include <QDBusInterface>
#include <QDBusReply>
#include <QDir>


Application::Application()
    : KUniqueApplication()
{
}


Application::~Application()
{
    // ok, we are closing well.
    // Don't recover on next load..
    ReKonfig::setRecoverOnCrash(0);
    saveConfiguration();

    kDebug() << "Bye bye (k)baby...";
}


int Application::newInstance()
{
    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...
    static bool isFirstLoad = true;
    bool areThereArguments = (args->count() > 0);
    bool hasToBeRecoveredFromCrash = (ReKonfig::recoverOnCrash() > 0);
    // note that hasToBeRecoveredFromCrash is always true if it is not the first load
    // !isFirstLoad -> hasToBeRecoveredFromCrash

    kDebug() << "is first load? " << isFirstLoad;
    kDebug() << "are there arguments? " << areThereArguments;
    kDebug() << "is rekonq crashed? " << hasToBeRecoveredFromCrash;

    bool incognito = args->isSet("incognito");
    bool webapp = args->isSet("webapp");

    if (webapp)
    {
        kDebug() << "WEBAPP MODE...";
        if (args->count() == 0)
        {
            KMessageBox::error(0, i18n("Error"), i18n("Cannot launch webapp mode without an URL to load"));
            return 1;
        }

        if (args->count() > 1)
        {
            KMessageBox::error(0, i18n("Error"), i18n("Cannot load more than one URL in webapp mode"));
            return 1;
        }

        KUrl u = args->url(0);
        if (!u.isLocalFile() || !QFile::exists(u.toLocalFile()))
        {
            u = UrlResolver::urlFromTextTyped(args->arg(0));
        }
        kDebug() << "URL: " << u;

        WebTab *tab = newWebApp();
        connect(tab->page(), SIGNAL(pageCreated(WebPage*)), this, SLOT(pageCreated(WebPage*)));
        tab->view()->load(u);

        if (isFirstLoad)
        {
            // updating rekonq configuration
            updateConfiguration();

            setWindowIcon(KIcon("rekonq"));

            // just create History Manager...
            HistoryManager::self();
        }

        KStartupInfo::appStarted();
        isFirstLoad = false;
        return 0;
    }

    if (areThereArguments)
    {
        kDebug() << "DEFAULT MODE, WITH ARGUMENTS...";

        // prepare URLS to load
        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
            {
                // "rekonq kde.org" || "rekonq kde:kdialog" cases
                urlList += UrlResolver::urlFromTextTyped(args->arg(i));
            }
        }

        if (isFirstLoad)
        {
            bool restoreOk = false;
            if (ReKonfig::startupBehaviour() == 2)
            {
                restoreOk = SessionManager::self()->restoreSessionFromScratch();
            }
            else
            {
                restoreOk = SessionManager::self()->restoreJustThePinnedTabs();
            }

            isFirstLoad = !restoreOk;
        }

        // first argument: 99% of the time we have just that...
        if (isFirstLoad || m_tabWindows.count() == 0)
        {
            // No windows in the current desktop? No windows at all?
            // Create a new one and load there sites...
            if (incognito)
                loadUrl(urlList.at(0), Rekonq::NewPrivateWindow);
            else
                loadUrl(urlList.at(0), Rekonq::NewWindow);
        }
        else
        {
            if (incognito)
            {
                loadUrl(urlList.at(0), Rekonq::NewPrivateWindow);
            }
            else if (!ReKonfig::openExternalLinksInNewWindow())
            {
                loadUrl(urlList.at(0), Rekonq::NewFocusedTab);
            }
            else
            {
                loadUrl(urlList.at(0), Rekonq::NewWindow);
            }

            if (!tabWindow()->isActiveWindow())
                KWindowSystem::demandAttention(tabWindow()->winId(), true);
        }

        // following arguments: what's best behavior here?
        // I'm pretty sure no one has real opinion about...
        if (!ReKonfig::openExternalLinksInNewWindow())
        {
            for (int i = 1; i < urlList.count(); ++i)
                loadUrl(urlList.at(i), Rekonq::NewFocusedTab);
        }
        else
        {
            for (int i = 1; i < urlList.count(); ++i)
                if (incognito)
                    loadUrl(urlList.at(i), Rekonq::NewPrivateWindow);
                else
                    loadUrl(urlList.at(i), Rekonq::NewWindow);
        }
    }
    else    // ok, NO arguments
    {
        kDebug() << "DEFAULT MODE, NO ARGUMENTS...";
        if (isFirstLoad)
        {
            // NOTE: just load new tabs/windows without arguments
            // if NOT is Session restored...
            if (!isSessionRestored())
            {
                switch (ReKonfig::startupBehaviour())
                {
                case 0: // open home page
                    if (incognito)
                    {
                        loadUrl(KUrl(ReKonfig::homePage()), Rekonq::NewPrivateWindow);
                        break;
                    }
                    if (SessionManager::self()->restoreJustThePinnedTabs())
                        loadUrl(KUrl(ReKonfig::homePage()) , Rekonq::NewTab);
                    else
                        loadUrl(KUrl(ReKonfig::homePage()) , Rekonq::NewWindow);
                    break;
                case 1: // open new tab page
                    if (incognito)
                    {
                        loadUrl(KUrl("about:home"), Rekonq::NewPrivateWindow);
                        break;
                    }
                    if (SessionManager::self()->restoreJustThePinnedTabs())
                        loadUrl(KUrl("about:home") , Rekonq::NewTab);
                    else
                        loadUrl(KUrl("about:home"), Rekonq::NewWindow);
                    break;
                case 2: // restore session
                    if (incognito)
                    {
                        loadUrl(KUrl("about:home"), Rekonq::NewPrivateWindow);
                        break;
                    }
                    if (SessionManager::self()->restoreSessionFromScratch())
                    {
                        break;
                    }
                default:
                    newTabWindow()->newTab();
                    break;
                }
            }
        }
        else
        {
            Rekonq::OpenType type = incognito ? Rekonq::NewPrivateWindow : Rekonq::NewWindow;

            switch (ReKonfig::newTabsBehaviour())
            {
            case 0: // new tab page
                loadUrl(KUrl("about:home") , type);
                break;
            case 2: // homepage
                loadUrl(KUrl(ReKonfig::homePage()) , type);
                break;
            case 1: // blank page
            default:
                loadUrl(KUrl("about:blank") , type);
                break;
            }
        }
    }

    // ok, now last stuffs...
    if (isFirstLoad)
    {
        if (hasToBeRecoveredFromCrash && !incognito)
        {
            QTimer::singleShot(1000, tabWindow()->currentWebWindow(), SLOT(showCrashMessageBar()));
        }
        else
        {
            SessionManager::self()->setSessionManagementEnabled(true);
        }

        if (ReKonfig::checkDefaultSearchEngine() && !hasToBeRecoveredFromCrash && SearchEngine::defaultEngine().isNull())
            QTimer::singleShot(2000, tabWindow()->currentWebWindow()->tabView(), SLOT(showSearchEngineBar()));

        // updating rekonq configuration
        updateConfiguration();

        setWindowIcon(KIcon("rekonq"));

        // just create History Manager...
        HistoryManager::self();

        ReKonfig::setRecoverOnCrash(ReKonfig::recoverOnCrash() + 1);
        saveConfiguration();
    }

    KStartupInfo::appStarted();
    isFirstLoad = false;

    return 0;
}


Application *Application::instance()
{
    return (qobject_cast<Application *>(QCoreApplication::instance()));
}


void Application::saveConfiguration() const
{
    ReKonfig::self()->writeConfig();
}


TabWindow *Application::tabWindow()
{
    TabWindow *active = qobject_cast<TabWindow*>(QApplication::activeWindow());

    if (!active)
    {
        if (m_tabWindows.isEmpty())
            return 0;

        Q_FOREACH(const QWeakPointer<TabWindow> &pointer, m_tabWindows)
        {
            if (KWindowInfo(pointer.data()->effectiveWinId(), NET::WMDesktop, 0).isOnCurrentDesktop())
                return pointer.data();
        }
        return m_tabWindows.at(0).data();
    }
    return active;
}


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;
    }

    Rekonq::OpenType newType = type;
    // Don't open useless tabs or windows for actions in about: pages
    if (url.url().contains("about:") && url.url().contains("/"))
        newType = Rekonq::CurrentTab;

    TabWindow *w = 0;
    if (newType == Rekonq::NewPrivateWindow)
    {
        w = newTabWindow(true, true);
        newType = Rekonq::CurrentTab;
    }
    else if (newType == Rekonq::NewWindow
             || ((newType == Rekonq::NewTab || newType == Rekonq::NewFocusedTab) && tabWindowList().count() == 0))
    {
        w = newTabWindow();
        newType = Rekonq::CurrentTab;
    }
    else
    {
        w = tabWindow();
    }

    w->loadUrl(url, newType);
}


TabWindow *Application::newTabWindow(bool withTab, bool PrivateBrowsingMode)
{
    TabWindow *w = new TabWindow(withTab, PrivateBrowsingMode);

    // set object name
    int n = m_tabWindows.count() + 1;
    w->setObjectName(QL1S("win") + QString::number(n));

    // This is used to track which window was activated most recently
    w->installEventFilter(this);

    m_tabWindows.prepend(w);
    w->show();

    return w;
}


WebTab *Application::newWebApp()
{
    WebTab *tab = new WebTab;

    tab->installEventFilter(this);
    m_webApps.prepend(tab);

    tab->show();

    return tab;
}


TabWindowList Application::tabWindowList()
{
    return m_tabWindows;
}


WebAppList Application::webAppList()
{
    return m_webApps;
}


bool Application::eventFilter(QObject* watched, QEvent* event)
{
    // Track which window was activated most recently to prefer it on window choosing
    // (e.g. when another application opens a link)
    if (event->type() == QEvent::WindowActivate)
    {
        TabWindow *window = qobject_cast<TabWindow*>(watched);
        if (window)
        {
            if (m_tabWindows.at(0).data() != window)
            {
                int index = m_tabWindows.indexOf(QWeakPointer<TabWindow>(window));
                Q_ASSERT(index != -1);
                m_tabWindows.prepend(m_tabWindows.takeAt(index));
            }
        }
    }

    // As we are filtering the events occurred to the tabwindows, check also
    // when we close one of them, remove from tab window list and check if it was last...
    if (event->type() == QEvent::Close)
    {
        TabWindow *window = qobject_cast<TabWindow*>(watched);
        if (window)
            m_tabWindows.removeOne(window);

        WebTab *webApp = qobject_cast<WebTab*>(watched);
        m_webApps.removeOne(webApp);

        if (m_tabWindows.count() == 0 && m_webApps.count() == 0)
            quit();
    }

    return QObject::eventFilter(watched, event);
}


void Application::updateConfiguration()
{
    // ============== Tabs ==================
    bool b = ReKonfig::closeTabSelectPrevious();
    Q_FOREACH(const QWeakPointer<TabWindow> &w, m_tabWindows)
    {
        if (b)
            w.data()->tabBar()->setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab);
        else
            w.data()->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
    if (tabWindow() && tabWindow()->currentWebWindow())
    {
        int logDpiY = tabWindow()->currentWebWindow()->logicalDpiY();
        float toPix = (logDpiY < 96.0)
                      ? 96.0 / 72.0
                      : logDpiY / 72.0 ;

        int defaultFontSize = ReKonfig::defaultFontSize();
        int minimumFontSize = ReKonfig::minFontSize();

        defaultSettings->setFontSize(QWebSettings::DefaultFontSize, qRound(defaultFontSize * toPix));
        defaultSettings->setFontSize(QWebSettings::MinimumFontSize, qRound(minimumFontSize * toPix));
    }

    // encodings
    QString enc = ReKonfig::defaultEncoding();
    defaultSettings->setDefaultTextEncoding(enc);

    // ================ WebKit ============================
    defaultSettings->setAttribute(QWebSettings::DnsPrefetchEnabled, ReKonfig::dnsPrefetch());
    defaultSettings->setAttribute(QWebSettings::PrintElementBackgrounds, ReKonfig::printElementBackgrounds());

    defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, ReKonfig::javascriptEnabled());
    defaultSettings->setAttribute(QWebSettings::JavascriptCanOpenWindows, ReKonfig::javascriptCanOpenWindows());
    defaultSettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, ReKonfig::javascriptCanAccessClipboard());

    defaultSettings->setAttribute(QWebSettings::JavaEnabled, ReKonfig::javaEnabled());

    if (ReKonfig::pluginsEnabled() == 2)
        defaultSettings->setAttribute(QWebSettings::PluginsEnabled, false);
    else
        defaultSettings->setAttribute(QWebSettings::PluginsEnabled, true);

    // Enabling WebKit "Page Cache" feature: http://webkit.org/blog/427/webkit-page-cache-i-the-basics/
    defaultSettings->setMaximumPagesInCache(3);

    // ===== 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);
    }

    // ================= WebGl ===================
    defaultSettings->setAttribute(QWebSettings::WebGLEnabled, ReKonfig::webGL());
    defaultSettings->setAttribute(QWebSettings::AcceleratedCompositingEnabled, ReKonfig::webGL());

    // Applies user defined CSS to all open webpages.
    defaultSettings->setUserStyleSheetUrl(ReKonfig::userCSS());

    // ====== load Settings on main classes
    HistoryManager::self()->loadSettings();

    defaultSettings = 0;

    if (!tabWindow())
        return;

    // FIXME What about this?
//     ReKonfig::useFavicon()
//     ? tabWindow()->changeWindowIcon(tabWindow()->mainView()->currentIndex())
//     : tabWindow()->setWindowIcon(KIcon("rekonq"))
//     ;
//
    // hovering unfocused tabs options
    switch (ReKonfig::hoveringTabOption())
    {
    case 0: // tab previews
    case 3: // nothing
        for (int i = 0; i < tabWindow()->tabBar()->count(); i++)
        {
            tabWindow()->tabBar()->setTabToolTip(i, QL1S(""));
        }
        break;

    case 1: // title previews
        for (int i = 0; i < tabWindow()->tabBar()->count(); i++)
        {
            tabWindow()->tabBar()->setTabToolTip(i, tabWindow()->tabText(i).remove('&'));
        }
        break;

    case 2: // url previews
        for (int i = 0; i < tabWindow()->tabBar()->count(); i++)
        {
            tabWindow()->tabBar()->setTabToolTip(i, tabWindow()->webWindow(i)->url().toMimeDataString());
        }
        break;

    default: // non extant case
        ASSERT_NOT_REACHED(unknown hoveringTabOption);
        break;
    }

}


void Application::queryQuit()
{
    if (m_webApps.count() > 0)
    {
        tabWindow()->close();
        return;
    }

    if (tabWindowList().count() > 1)
    {
        int answer = KMessageBox::questionYesNoCancel(
                         tabWindow(),
                         i18n("Do you want to close the window or the whole application?"),
                         i18n("Application/Window closing..."),
                         KGuiItem(i18n("C&lose Current Window"),
                                  KIcon("window-close")),
                         KStandardGuiItem::quit(),
                         KStandardGuiItem::cancel(),
                         "confirmClosingMultipleWindows"
                     );

        switch (answer)
        {
        case KMessageBox::Yes:
            tabWindow()->close();
            return;

        case KMessageBox::No:
            break;

        default:
            return;
        }
    }

    // in case of just one window...
    quit();
}


void Application::clearPrivateData()
{
    QPointer<KDialog> dialog = new KDialog(tabWindow());
    dialog->setCaption(i18nc("@title:window", "Clear Private Data"));
    dialog->setButtons(KDialog::Ok | KDialog::Cancel);

    dialog->button(KDialog::Ok)->setIcon(KIcon("edit-clear"));
    dialog->button(KDialog::Ok)->setText(i18n("Clear"));

    Ui::ClearDataWidget clearWidget;
    QWidget widget;
    clearWidget.setupUi(&widget);
    clearWidget.clearHistory->setChecked(ReKonfig::clearHistory());
    clearWidget.clearDownloads->setChecked(ReKonfig::clearDownloads());
    clearWidget.clearCookies->setChecked(ReKonfig::clearCookies());
    clearWidget.clearCachedPages->setChecked(ReKonfig::clearCachedPages());
    clearWidget.clearWebIcons->setChecked(ReKonfig::clearWebIcons());
    clearWidget.homePageThumbs->setChecked(ReKonfig::clearHomePageThumbs());

    dialog->setMainWidget(&widget);
    dialog->exec();

    if (dialog->result() == QDialog::Accepted)
    {
        //Save current state
        ReKonfig::setClearHistory(clearWidget.clearHistory->isChecked());
        ReKonfig::setClearDownloads(clearWidget.clearDownloads->isChecked());
        ReKonfig::setClearCookies(clearWidget.clearDownloads->isChecked());
        ReKonfig::setClearCachedPages(clearWidget.clearCachedPages->isChecked());
        ReKonfig::setClearWebIcons(clearWidget.clearWebIcons->isChecked());
        ReKonfig::setClearHomePageThumbs(clearWidget.homePageThumbs->isChecked());

        if (clearWidget.clearHistory->isChecked())
        {
            HistoryManager::self()->clear();
        }

        if (clearWidget.clearDownloads->isChecked())
        {
            DownloadManager::self()->clearDownloadsHistory();
        }

        if (clearWidget.clearCookies->isChecked())
        {
            QDBusInterface kcookiejar("org.kde.kded", "/modules/kcookiejar", "org.kde.KCookieServer");
            QDBusReply<void> reply = kcookiejar.call("deleteAllCookies");
        }

        if (clearWidget.clearCachedPages->isChecked())
        {
            KProcess::startDetached(KStandardDirs::findExe("kio_http_cache_cleaner"),
                                    QStringList(QL1S("--clear-all")));
        }

        if (clearWidget.clearWebIcons->isChecked())
        {
            IconManager::self()->clearIconCache();
        }

        if (clearWidget.homePageThumbs->isChecked())
        {
            QString path = KStandardDirs::locateLocal("cache", QString("thumbs/rekonq"), true);
            path.remove("rekonq");
            QDir cacheDir(path);
            QStringList fileList = cacheDir.entryList();
            Q_FOREACH(const QString & str, fileList)
            {
                QFile file(path + str);
                file.remove();
            }
        }
    }

    dialog->deleteLater();
}


void Application::createWebAppShortcut()
{
    KUrl u = tabWindow()->currentWebWindow()->url();
    QString h = u.host();

    QPointer<KDialog> dialog = new KDialog(tabWindow());
    dialog->setCaption(i18nc("@title:window", "Create Application Shortcut"));
    dialog->setButtons(KDialog::Ok | KDialog::Cancel);
    dialog->button(KDialog::Ok)->setText(i18n("Create"));
    dialog->setMinimumSize(400, 50);
    dialog->setWindowIcon(QIcon(IconManager::self()->iconForUrl(u).pixmap(16)));

    Ui::webAppCreation wAppWidget;
    QWidget widget;
    wAppWidget.setupUi(&widget);

    QString webAppTitle = tabWindow()->currentWebWindow()->title().remove('&');
    wAppWidget.nameLineEdit->setText(webAppTitle);
    wAppWidget.kcfg_createDesktopAppShortcut->setChecked(ReKonfig::createDesktopAppShortcut());
    wAppWidget.kcfg_createMenuAppShortcut->setChecked(ReKonfig::createMenuAppShortcut());

    dialog->setMainWidget(&widget);
    dialog->exec();

    if (dialog->result() == QDialog::Accepted)
    {
        ReKonfig::setCreateDesktopAppShortcut(wAppWidget.kcfg_createDesktopAppShortcut->isChecked());
        ReKonfig::setCreateMenuAppShortcut(wAppWidget.kcfg_createMenuAppShortcut->isChecked());

        IconManager::self()->saveDesktopIconForUrl(u);
        QString iconPath = KStandardDirs::locateLocal("cache" , "favicons/" , true) + h + QL1S("_WEBAPPICON.png");

        if (!wAppWidget.nameLineEdit->text().isEmpty())
            webAppTitle = wAppWidget.nameLineEdit->text();

        QString webAppDescription;
        if (!wAppWidget.descriptionLineEdit->text().isEmpty())
            webAppDescription = wAppWidget.descriptionLineEdit->text();

        QString shortcutString = QL1S("#!/usr/bin/env xdg-open\n")
                                 + QL1S("[Desktop Entry]\n")
                                 + QL1S("Name=") + webAppTitle
                                 + QL1S("\n")
                                 + QL1S("GenericName=") + webAppDescription
                                 + QL1S("\n")
                                 + QL1S("Icon=") + iconPath + QL1S("\n")
                                 + QL1S("Exec=rekonq --webapp ") + u.url() + QL1S("\n")
                                 + QL1S("Type=Application\n")
                                 + QL1S("Categories=Application;Network\n")
                                 ;

        if (ReKonfig::createDesktopAppShortcut())
        {
            QString desktop = KGlobalSettings::desktopPath();
            QFile wAppFile(desktop + QL1C('/') + webAppTitle);

            if (!wAppFile.open(QIODevice::WriteOnly | QIODevice::Text))
            {
                kDebug() << "Unable to open file: " << wAppFile.errorString();
                return;
            }

            QTextStream out(&wAppFile);
            out.setCodec("UTF-8");
            out << shortcutString;

            wAppFile.setPermissions(QFile::ReadUser | QFile::WriteUser | QFile::ExeUser | QFile::ReadGroup | QFile::ReadOther);
            wAppFile.close();
        }

        if (ReKonfig::createMenuAppShortcut())
        {
            QString appMenuDir = KStandardDirs::locateLocal("xdgdata-apps", QString());
            QFile wAppFile(appMenuDir + QL1C('/') + webAppTitle + QL1S(".desktop"));

            if (!wAppFile.open(QIODevice::WriteOnly | QIODevice::Text))
            {
                kDebug() << "Unable to open file: " << wAppFile.errorString();
                return;
            }

            QTextStream out(&wAppFile);
            out.setCodec("UTF-8");
            out << shortcutString;

            wAppFile.close();
        }

    }

    dialog->deleteLater();
}


void Application::bookmarksToolbarToggled(bool b)
{
    emit toggleBookmarksToolbar(b);
}


void Application::newPrivateBrowsingWindow()
{
    // NOTE: what about an "about:incognito" page?
    loadUrl(KUrl("about:home"), Rekonq::NewPrivateWindow);
}


void Application::pageCreated(WebPage *pg)
{
    if (m_tabWindows.isEmpty())
    {
        // NOTE: This is "adjusted" from newTabWindow() code...
        TabWindow *w = new TabWindow(pg);

        // set object name
        int n = m_tabWindows.count() + 1;
        w->setObjectName(QL1S("win") + QString::number(n));

        // This is used to track which window was activated most recently
        w->installEventFilter(this);

        m_tabWindows.prepend(w);
        w->show();

        return;
    }

    TabWindow *tw = tabWindow();
    tw->newTab(pg);

    tw->activateWindow();
    tw->raise();
}