/* ============================================================ * * This file is a part of the rekonq project * * Copyright (C) 2009-2012 by Andrea Diamantini * Copyright (C) 2009 by Yoram Bar-Haim < * Copyright (C) 2009-2011 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 "sessionmanager.h" #include "sessionmanager.moc" // Local Includes #include "application.h" #include "tabhistory.h" #include "sessionwidget.h" #include "rekonqwindow.h" #include "tabbar.h" #include "webwindow.h" #include "webpage.h" // KDE Includes #include #include #include #include // Qt Includes #include #include #include // Only used internally bool readSessionDocument(QDomDocument & document, const QString & sessionFilePath) { QFile sessionFile(sessionFilePath); if (!sessionFile.exists()) return false; if (!sessionFile.open(QFile::ReadOnly)) { kDebug() << "Unable to open session file" << sessionFile.fileName(); return false; } if (!document.setContent(&sessionFile, false)) { kDebug() << "Unable to parse session file" << sessionFile.fileName(); return false; } return true; } int loadTabs(RekonqWindow *tw, QDomElement & window, bool useFirstTab, bool justThePinnedOnes = false) { int currentTab = 0; for (unsigned int tabNo = 0; tabNo < window.elementsByTagName("tab").length(); tabNo++) { QDomElement tab = window.elementsByTagName("tab").at(tabNo).toElement(); bool tabIsPinned = tab.hasAttribute("pinned"); kDebug() << "Tab #" << tabNo << " is pinned? " << tabIsPinned; if (!justThePinnedOnes || tabIsPinned) { if (tab.hasAttribute("currentTab")) currentTab = tabNo; KUrl u = KUrl(tab.attribute("url")); TabHistory tabHistory; tabHistory.title = tab.attribute("title"); tabHistory.url = tab.attribute("url"); QDomCDATASection historySection = tab.firstChild().toCDATASection(); tabHistory.history = QByteArray::fromBase64(historySection.data().toAscii()); if (tabNo == 0 && useFirstTab) { tw->loadUrl(u, Rekonq::CurrentTab, &tabHistory); } else { tw->loadUrl(u, Rekonq::NewTab, &tabHistory); } if (tabIsPinned) { tw->tabBar()->setTabData(tabNo, true); if (tw->tabBar()->tabButton(tabNo, QTabBar::RightSide)) tw->tabBar()->tabButton(tabNo, QTabBar::RightSide)->hide(); // NOTE: this is not good here: where is its proper place? } } } return currentTab; } bool areTherePinnedTabs(QDomElement & window) { bool b = false; for (unsigned int tabNo = 0; tabNo < window.elementsByTagName("tab").length(); tabNo++) { QDomElement tab = window.elementsByTagName("tab").at(tabNo).toElement(); b = tab.hasAttribute("pinned"); if (b) return true; } return b; } // ------------------------------------------------------------------------------------------------- QWeakPointer SessionManager::s_sessionManager; SessionManager *SessionManager::self() { if (s_sessionManager.isNull()) { s_sessionManager = new SessionManager(qApp); } return s_sessionManager.data(); } // ---------------------------------------------------------------------------------------------- SessionManager::SessionManager(QObject *parent) : QObject(parent) , m_safe(true) , m_isSessionEnabled(false) { m_sessionFilePath = KStandardDirs::locateLocal("appdata" , "session"); } void SessionManager::saveSession() { if (!m_isSessionEnabled || !m_safe) return; m_safe = false; kDebug() << "SAVING SESSION..."; QFile sessionFile(m_sessionFilePath); if (!sessionFile.open(QFile::WriteOnly | QFile::Truncate)) { kDebug() << "Unable to open session file" << sessionFile.fileName(); return; } RekonqWindowList wl = rApp->rekonqWindowList(); QDomDocument document("session"); QDomElement session = document.createElement("session"); document.appendChild(session); Q_FOREACH(const QWeakPointer &w, wl) { if (w.data()->isPrivateBrowsingMode()) continue; QDomElement window = document.createElement("window"); int tabInserted = 0; window.setAttribute("name", w.data()->objectName()); TabWidget *tw = w.data()->tabWidget(); for (signed int tabNo = 0; tabNo < tw->count(); tabNo++) { KUrl u = tw->webWindow(tabNo)->url(); tabInserted++; QDomElement tab = document.createElement("tab"); tab.setAttribute("title", tw->webWindow(tabNo)->title()); // redundant, but needed for closedSites() // as there's not way to read out the historyData tab.setAttribute("url", u.url()); if (tw->currentIndex() == tabNo) { tab.setAttribute("currentTab", 1); } if (tw->tabBar()->tabData(tabNo).toBool()) // pinned tab info { tab.setAttribute("pinned", 1); } QByteArray history; QDataStream historyStream(&history, QIODevice::ReadWrite); historyStream << *(tw->webWindow(tabNo)->page()->history()); QDomCDATASection historySection = document.createCDATASection(history.toBase64()); tab.appendChild(historySection); window.appendChild(tab); } if (tabInserted > 0) session.appendChild(window); } QTextStream TextStream(&sessionFile); document.save(TextStream, 2); sessionFile.close(); m_safe = true; return; } bool SessionManager::restoreSessionFromScratch() { QDomDocument document("session"); if (!readSessionDocument(document, m_sessionFilePath)) return false; for (unsigned int winNo = 0; winNo < document.elementsByTagName("window").length(); winNo++) { QDomElement window = document.elementsByTagName("window").at(winNo).toElement(); RekonqWindow *tw = rApp->newWindow(); int currentTab = loadTabs(tw, window, true, false); tw->tabWidget()->setCurrentIndex(currentTab); } return true; } bool SessionManager::restoreJustThePinnedTabs() { QDomDocument document("session"); if (!readSessionDocument(document, m_sessionFilePath)) return false; bool done = false; for (unsigned int winNo = 0; winNo < document.elementsByTagName("window").length(); winNo++) { QDomElement window = document.elementsByTagName("window").at(winNo).toElement(); if (!areTherePinnedTabs(window)) continue; done = true; RekonqWindow *tw = rApp->newWindow(false); int currentTab = loadTabs(tw, window, false, true); tw->tabWidget()->setCurrentIndex(currentTab); } return done; } void SessionManager::restoreCrashedSession() { QDomDocument document("session"); if (!readSessionDocument(document, m_sessionFilePath)) return; for (unsigned int winNo = 0; winNo < document.elementsByTagName("window").length(); winNo++) { QDomElement window = document.elementsByTagName("window").at(winNo).toElement(); RekonqWindow *tw = (winNo == 0) ? rApp->rekonqWindow() : rApp->newWindow(); KUrl u = tw->currentWebWindow()->url(); bool useCurrentTab = (u.isEmpty() || u.protocol() == QL1S("about")); int currentTab = loadTabs(tw, window, useCurrentTab); tw->tabWidget()->setCurrentIndex(currentTab); } setSessionManagementEnabled(true); } bool SessionManager::restoreWindow(RekonqWindow* window) { QDomDocument document("session"); if (!readSessionDocument(document, m_sessionFilePath)) return false; unsigned int winNo; for (winNo = 0; winNo < document.elementsByTagName("window").length(); winNo++) { QDomElement savedWindowElement = document.elementsByTagName("window").at(winNo).toElement(); if (window->objectName() != savedWindowElement.attribute("name", "")) continue; int currentTab = loadTabs(window, savedWindowElement, false); window->tabWidget()->setCurrentIndex(currentTab); return true; } return false; } QList SessionManager::closedSitesForWindow(const QString &windowName) { QList list; QDomDocument document("session"); if (!readSessionDocument(document, m_sessionFilePath)) return list; for (unsigned int winNo = 0; winNo < document.elementsByTagName("tab").length(); winNo++) { QDomElement windowElement = document.elementsByTagName("window").at(winNo).toElement(); if (windowName != windowElement.attribute("name", "")) continue; for (unsigned int tabNo = 0; tabNo < windowElement.elementsByTagName("tab").length(); tabNo++) { QDomElement tab = windowElement.elementsByTagName("tab").at(tabNo).toElement(); TabHistory tabHistory; tabHistory.title = tab.attribute("title"); tabHistory.url = tab.attribute("url"); QDomCDATASection historySection = tab.firstChild().toCDATASection(); tabHistory.history = QByteArray::fromBase64(historySection.data().toAscii()); list << tabHistory; } return list; } return list; } // ------------------------------------------------------------------------------------------------------- bool SessionManager::saveYourSession(int index) { kDebug() << "SAVING YOUR OWN SESSION..."; const QString & sessionPath = KStandardDirs::locateLocal("appdata" , QL1S("usersessions/")); const QString & sessionName = QL1S("ses") + QString::number(index); QFile sessionFile(sessionPath + sessionName); if (!sessionFile.open(QFile::WriteOnly | QFile::Truncate)) { kDebug() << "Unable to open session file" << sessionFile.fileName(); return false; } RekonqWindowList wl = rApp->rekonqWindowList(); QDomDocument document("session"); QDomElement session = document.createElement("session"); document.appendChild(session); Q_FOREACH(const QWeakPointer &w, wl) { if (w.data()->isPrivateBrowsingMode()) continue; QDomElement window = document.createElement("window"); int tabInserted = 0; window.setAttribute("name", w.data()->objectName()); TabWidget *tw = w.data()->tabWidget(); for (signed int tabNo = 0; tabNo < tw->count(); tabNo++) { KUrl u = tw->webWindow(tabNo)->url(); tabInserted++; QDomElement tab = document.createElement("tab"); tab.setAttribute("title", tw->webWindow(tabNo)->title()); // redundant, but needed for closedSites() // as there's not way to read out the historyData tab.setAttribute("url", u.url()); if (tw->currentIndex() == tabNo) { tab.setAttribute("currentTab", 1); } if (tw->tabBar()->tabData(tabNo).toBool()) // pinned tab info { tab.setAttribute("pinned", 1); } QByteArray history; QDataStream historyStream(&history, QIODevice::ReadWrite); historyStream << *(tw->webWindow(tabNo)->page()->history()); QDomCDATASection historySection = document.createCDATASection(history.toBase64()); tab.appendChild(historySection); window.appendChild(tab); } if (tabInserted > 0) session.appendChild(window); } QTextStream TextStream(&sessionFile); document.save(TextStream, 2); sessionFile.close(); return true; } bool SessionManager::restoreYourSession(int index) { const QString & sessionPath = KStandardDirs::locateLocal("appdata" , QL1S("usersessions/")); const QString & sessionName = QL1S("ses") + QString::number(index); QDomDocument document("session"); if (!readSessionDocument(document,sessionPath + sessionName)) return false; // trace the windows to delete RekonqWindowList wList = rApp->rekonqWindowList(); for (unsigned int winNo = 0; winNo < document.elementsByTagName("window").length(); winNo++) { QDomElement window = document.elementsByTagName("window").at(winNo).toElement(); RekonqWindow *tw = rApp->newWindow(); int currentTab = loadTabs(tw, window, true, false); tw->tabWidget()->setCurrentIndex(currentTab); } Q_FOREACH(const QWeakPointer &w, wList) { if (!w.isNull()) w.data()->close(); } return true; } void SessionManager::manageSessions() { kDebug() << "OK ,manage session.."; QPointer dialog = new KDialog(); dialog->setCaption(i18nc("@title:window", "Manage Session")); dialog->setButtons(KDialog::Ok | KDialog::Close); dialog->button(KDialog::Ok)->setIcon(KIcon("system-run")); dialog->button(KDialog::Ok)->setText(i18n("Load")); SessionWidget widg; dialog->setMainWidget(&widg); connect(dialog, SIGNAL(okClicked()), &widg, SLOT(loadSession())); dialog->exec(); }