From 80e89b2644256f6d5ffd3dd1eb20ce75760ebab5 Mon Sep 17 00:00:00 2001 From: nowrep Date: Tue, 21 Aug 2012 20:28:38 +0200 Subject: [PATCH] New Restore Session GUI - allows choosing to/not to restore each tab - added as new qupzilla:restore page - thanks a lot for work by Franz Fellner closes #515 --- AUTHORS | 1 + src/lib/3rdparty/qtwin.cpp | 5 +- src/lib/app/mainapplication.cpp | 65 ++++++------ src/lib/app/mainapplication.h | 6 +- src/lib/app/qupzilla.cpp | 23 ++--- src/lib/app/qupzilla.h | 4 +- src/lib/data/html.qrc | 1 + src/lib/data/html/restore.html | 29 ++++++ src/lib/lib.pro | 12 ++- src/lib/network/qupzillaschemehandler.cpp | 32 +++++- src/lib/network/qupzillaschemehandler.h | 1 + src/lib/session/recoverywidget.cpp | 120 ++++++++++++++++++++++ src/lib/session/recoverywidget.h | 57 ++++++++++ src/lib/session/recoverywidget.ui | 70 +++++++++++++ src/lib/session/restoremanager.cpp | 87 ++++++++++++++++ src/lib/session/restoremanager.h | 45 ++++++++ src/lib/webview/tabwidget.cpp | 33 +++--- src/lib/webview/tabwidget.h | 6 +- src/lib/webview/webpage.cpp | 12 ++- src/main/main.pro | 4 +- src/plugins.pri | 1 + 21 files changed, 532 insertions(+), 82 deletions(-) create mode 100644 src/lib/data/html/restore.html create mode 100644 src/lib/session/recoverywidget.cpp create mode 100644 src/lib/session/recoverywidget.h create mode 100644 src/lib/session/recoverywidget.ui create mode 100644 src/lib/session/restoremanager.cpp create mode 100644 src/lib/session/restoremanager.h diff --git a/AUTHORS b/AUTHORS index c146084f3..dd080a0fa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -7,6 +7,7 @@ Contributors: Mladen Pejaković (webview context menu improvements, speed dial background) Alexander Samilov (tab previews) Seyyed Razi Alavizadeh (fixed UI for RTL languages) +Franz Fellner (new restore session ui) Bryan M Dunsmore (opening background tabs, closing window when closing last tab) Mariusz Fik (fixed tab order in preferences dialog) Daniele Cocca (close tabs with middle click, initial work on speed dial) diff --git a/src/lib/3rdparty/qtwin.cpp b/src/lib/3rdparty/qtwin.cpp index b2bf2606f..3e650176b 100644 --- a/src/lib/3rdparty/qtwin.cpp +++ b/src/lib/3rdparty/qtwin.cpp @@ -65,7 +65,7 @@ static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; -QHash widgetsBlurState = QHash(); +QHash widgetsBlurState = QHash(); /* * Internal helper class that notifies windows if the @@ -261,8 +261,7 @@ bool WindowNotifier::winEvent(MSG* message, long* result) if (widget) { widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); bool isBlur = widgetsBlurState.value(widget, false); - if (compositionEnabled && isBlur) - { + if (compositionEnabled && isBlur) { // hack for fixing black background when enabling composition QtWin::enableBlurBehindWindow(widget, false); QtWin::extendFrameIntoClientArea(widget); diff --git a/src/lib/app/mainapplication.cpp b/src/lib/app/mainapplication.cpp index 1ba4dbe00..e267b2e1c 100644 --- a/src/lib/app/mainapplication.cpp +++ b/src/lib/app/mainapplication.cpp @@ -48,6 +48,7 @@ #include "clearprivatedata.h" #include "commandlineoptions.h" #include "useragentmanager.h" +#include "restoremanager.h" #ifdef Q_WS_MAC #include @@ -81,6 +82,7 @@ MainApplication::MainApplication(int &argc, char** argv) , m_networkCache(0) , m_desktopNotifications(0) , m_searchEnginesManager(0) + , m_restoreManager(0) , m_dbWriter(new DatabaseWriter(this)) , m_uaManager(new UserAgentManager) , m_isPrivateSession(false) @@ -109,7 +111,6 @@ MainApplication::MainApplication(int &argc, char** argv) TRANSLATIONSDIR = DATADIR + "locale/"; THEMESDIR = DATADIR + "themes/"; - setOverrideCursor(Qt::WaitCursor); setWindowIcon(QIcon(":icons/exeicons/qupzilla-window.png")); bool noAddons = false; QUrl startUrl; @@ -234,11 +235,16 @@ MainApplication::MainApplication(int &argc, char** argv) Settings settings; m_startingAfterCrash = settings.value("SessionRestore/isRunning", false).toBool(); bool checkUpdates = settings.value("Web-Browser-Settings/CheckUpdates", DEFAULT_CHECK_UPDATES).toBool(); + int afterLaunch = settings.value("Web-URL-Settings/afterLaunch", 1).toInt(); settings.setValue("SessionRestore/isRunning", true); if (checkUpdates) { new Updater(qupzilla); } + + if (m_startingAfterCrash || afterLaunch == 3) { + m_restoreManager = new RestoreManager(m_activeProfil + "session.dat"); + } } QTimer::singleShot(0, this, SLOT(postLaunch())); @@ -816,12 +822,12 @@ void MainApplication::aboutToCloseWindow(QupZilla* window) m_mainWindows.removeOne(window); } -//Version of session.dat file +// Version of session.dat file static const int sessionVersion = 0x0003; bool MainApplication::saveStateSlot() { - if (m_isPrivateSession || m_isRestoring || m_mainWindows.count() == 0) { + if (m_isPrivateSession || m_isRestoring || m_mainWindows.count() == 0 || m_restoreManager) { return false; } @@ -858,7 +864,7 @@ bool MainApplication::saveStateSlot() return true; } -bool MainApplication::restoreStateSlot(QupZilla* window) +bool MainApplication::restoreStateSlot(QupZilla* window, const RestoreData &recoveryData) { if (m_isPrivateSession) { return false; @@ -866,47 +872,34 @@ bool MainApplication::restoreStateSlot(QupZilla* window) m_isRestoring = true; - if (!QFile::exists(m_activeProfil + "session.dat")) { + if (recoveryData.isEmpty()) { m_isRestoring = false; + return false; } - QFile file(m_activeProfil + "session.dat"); - file.open(QIODevice::ReadOnly); - QDataStream stream(&file); + int windowCount = recoveryData.size(); + int currentWindow = 0; - QByteArray tabState; - QByteArray windowState; - int version; - int windowCount; + while (window) { + const RestoreManager::WindowData &wd = recoveryData.at(currentWindow); + window->restoreWindowState(wd); + window->show(); - stream >> version; - if (version != sessionVersion) { - m_isRestoring = false; - return false; - } - stream >> windowCount; - stream >> tabState; - stream >> windowState; + ++currentWindow; - window->restoreWindowState(windowState, tabState); - - if (windowCount > 1) { - for (int i = 1; i < windowCount; i++) { - stream >> tabState; - stream >> windowState; - - QupZilla* window = new QupZilla(Qz::BW_OtherRestoredWindow); + if (currentWindow < windowCount) { + window = new QupZilla(Qz::BW_OtherRestoredWindow); m_mainWindows.append(window); - - window->restoreWindowState(windowState, tabState); - - window->show(); + } + else { + window = 0; } } - file.close(); + destroyRestoreManager(); m_isRestoring = false; + return true; } @@ -959,6 +952,12 @@ bool MainApplication::checkSettingsDir() return dir.isReadable(); } +void MainApplication::destroyRestoreManager() +{ + delete m_restoreManager; + m_restoreManager = 0; +} + MainApplication::~MainApplication() { delete m_uaManager; diff --git a/src/lib/app/mainapplication.h b/src/lib/app/mainapplication.h index 14433868a..28ab36159 100644 --- a/src/lib/app/mainapplication.h +++ b/src/lib/app/mainapplication.h @@ -24,6 +24,7 @@ #include #include +#include "restoremanager.h" #include "qtsingleapplication.h" #include "qz_namespace.h" @@ -64,7 +65,7 @@ public: void connectDatabase(); void loadSettings(); void reloadSettings(); - bool restoreStateSlot(QupZilla* window); + bool restoreStateSlot(QupZilla* window, const RestoreData &recoveryData); QupZilla* makeNewWindow(Qz::BrowserWindow type, const QUrl &startUrl = QUrl()); void aboutToCloseWindow(QupZilla* window); bool isStateChanged(); @@ -80,6 +81,7 @@ public: inline int windowCount() { return m_mainWindows.count(); } bool checkSettingsDir(); + void destroyRestoreManager(); QupZilla* getWindow(); CookieManager* cookieManager(); @@ -99,6 +101,7 @@ public: DatabaseWriter* dbWriter() { return m_dbWriter; } UserAgentManager* uaManager() { return m_uaManager; } + RestoreManager* restoreManager() { return m_restoreManager; } #ifdef Q_WS_MAC bool event(QEvent* e); @@ -147,6 +150,7 @@ private: QNetworkDiskCache* m_networkCache; DesktopNotificationsFactory* m_desktopNotifications; SearchEnginesManager* m_searchEnginesManager; + RestoreManager* m_restoreManager; DatabaseWriter* m_dbWriter; UserAgentManager* m_uaManager; diff --git a/src/lib/app/qupzilla.cpp b/src/lib/app/qupzilla.cpp index 994c8b75d..3e7a48eab 100644 --- a/src/lib/app/qupzilla.cpp +++ b/src/lib/app/qupzilla.cpp @@ -162,19 +162,12 @@ void QupZilla::postLaunch() switch (m_startBehaviour) { case Qz::BW_FirstAppWindow: - if (afterLaunch == 3) { - addTab = !mApp->restoreStateSlot(this); + if (mApp->isStartingAfterCrash()) { + addTab = true; + startUrl = QUrl("qupzilla:restore"); } - else if (mApp->isStartingAfterCrash()) { - QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Last session crashed"), - tr("QupZilla crashed :-(
Oops, the last session " - "of QupZilla was interrupted unexpectedly. We apologize " - "for this. Would you like to try restoring the last " - "saved state?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - if (button == QMessageBox::Yes) { - addTab = !mApp->restoreStateSlot(this); - } + else if (afterLaunch == 3 && mApp->restoreManager()) { + addTab = !mApp->restoreStateSlot(this, mApp->restoreManager()->restoreData()); } break; @@ -1358,10 +1351,10 @@ void QupZilla::addDeleteOnCloseWidget(QWidget* widget) } } -void QupZilla::restoreWindowState(const QByteArray &window, const QByteArray &tabs) +void QupZilla::restoreWindowState(const RestoreManager::WindowData &d) { - QMainWindow::restoreState(window); - m_tabWidget->restoreState(tabs); + QMainWindow::restoreState(d.windowState); + m_tabWidget->restoreState(d.tabsState, d.currentTab); } void QupZilla::aboutQupZilla() diff --git a/src/lib/app/qupzilla.h b/src/lib/app/qupzilla.h index 9db62ec98..087eb9619 100644 --- a/src/lib/app/qupzilla.h +++ b/src/lib/app/qupzilla.h @@ -22,6 +22,7 @@ #include #include "qwebkitversion.h" +#include "restoremanager.h" #include "qz_namespace.h" class QMenuBar; @@ -48,6 +49,7 @@ class NavigationBar; class ClickableLabel; class WebInspectorDockWidget; class LocationBar; + class QT_QUPZILLA_EXPORT QupZilla : public QMainWindow { Q_OBJECT @@ -74,7 +76,7 @@ public: void addBookmark(const QUrl &url, const QString &title, const QIcon &icon); void addDeleteOnCloseWidget(QWidget* widget); - void restoreWindowState(const QByteArray &window, const QByteArray &tabs); + void restoreWindowState(const RestoreManager::WindowData &d); SideBar* addSideBar(); virtual QMenuBar* menuBar() const; diff --git a/src/lib/data/html.qrc b/src/lib/data/html.qrc index 781cfc53b..9c0f561bd 100644 --- a/src/lib/data/html.qrc +++ b/src/lib/data/html.qrc @@ -22,5 +22,6 @@ html/broken-page.png html/setting.png html/config.html + html/restore.html diff --git a/src/lib/data/html/restore.html b/src/lib/data/html/restore.html new file mode 100644 index 000000000..0d4edd67e --- /dev/null +++ b/src/lib/data/html/restore.html @@ -0,0 +1,29 @@ + + + +%TITLE% + + + +
+ +

%OOPS%

+

%APOLOGIZE%

+ +
    +
  • %TRY-REMOVING%
  • +
  • %START-NEW%
  • + + + + diff --git a/src/lib/lib.pro b/src/lib/lib.pro index d17c826f5..d4f31b8e7 100644 --- a/src/lib/lib.pro +++ b/src/lib/lib.pro @@ -16,6 +16,7 @@ INCLUDEPATH += 3rdparty\ autofill\ bookmarks\ cookies\ + session\ downloads\ history\ navigation\ @@ -182,7 +183,9 @@ SOURCES += \ preferences/pluginsmanager.cpp \ other/qzsettings.cpp \ other/useragentmanager.cpp \ - preferences/useragentdialog.cpp + preferences/useragentdialog.cpp \ + session/recoverywidget.cpp \ + session/restoremanager.cpp HEADERS += \ webview/tabpreview.h \ @@ -336,7 +339,9 @@ HEADERS += \ preferences/pluginsmanager.h \ other/qzsettings.h \ other/useragentmanager.h \ - preferences/useragentdialog.h + preferences/useragentdialog.h \ + session/recoverywidget.h \ + session/restoremanager.h FORMS += \ preferences/autofillmanager.ui \ @@ -380,7 +385,8 @@ FORMS += \ other/checkboxdialog.ui \ other/iconchooser.ui \ adblock/adblockaddsubscriptiondialog.ui \ - preferences/useragentdialog.ui + preferences/useragentdialog.ui \ + session/recoverywidget.ui RESOURCES += \ data/icons.qrc \ diff --git a/src/lib/network/qupzillaschemehandler.cpp b/src/lib/network/qupzillaschemehandler.cpp index 6d7ceccee..e76496500 100644 --- a/src/lib/network/qupzillaschemehandler.cpp +++ b/src/lib/network/qupzillaschemehandler.cpp @@ -25,6 +25,7 @@ #include "pluginproxy.h" #include "plugininterface.h" #include "settings.h" +#include "iconprovider.h" #include #include @@ -61,7 +62,7 @@ QupZillaSchemeReply::QupZillaSchemeReply(const QNetworkRequest &req, QObject* pa m_pageName = req.url().path(); QStringList knownPages; - knownPages << "about" << "reportbug" << "start" << "speeddial" << "config"; + knownPages << "about" << "reportbug" << "start" << "speeddial" << "config" << "restore"; if (knownPages.contains(m_pageName)) { m_buffer.open(QIODevice::ReadWrite); @@ -96,6 +97,9 @@ void QupZillaSchemeReply::loadPage() else if (m_pageName == "config") { stream << configPage(); } + else if (m_pageName == "restore") { + stream << restorePage(); + } stream.flush(); m_buffer.reset(); @@ -207,6 +211,8 @@ QString QupZillaSchemeReply::aboutPage() aPage.replace("%CONTRIBUTORS-TEXT%", authorString("Mladen Pejaković", "pejakm@gmail.com") + "
    " + authorString("Alexander Samilov", "alexsamilovskih@gmail.com") + "
    " + + authorString("Seyyed Razi Alavizadeh", "s.r.alavizadeh@gmail.com") + "
    " + + authorString("Franz Fellner", "alpine.art.de@googlemail.com") + "
    " + authorString("Bryan M Dunsmore", "dunsmoreb@gmail.com") + "
    " + authorString("Mariusz Fik", "fisiu@opensuse.org") + "
    " + authorString("Jan Rajnoha", "honza.rajny@hotmail.com") + "
    " + @@ -239,7 +245,8 @@ QString QupZillaSchemeReply::aboutPage() authorString("Daiki Noda", "sys.pdr.pdm9@gmail.com") + " (Japanese)
    " + authorString("Gábor Oberle", "oberleg@myopera.com") + " (Hungarian)
    " + authorString("Piccoro McKay Lenz", "mckaygerhard@gmail.com") + " (Venezulean Spanish)
    " + - authorString("Stanislav Kuznietsov", "stanislav_kuznetsov@ukr.net") + " (Ukrainian)" + authorString("Stanislav Kuznietsov", "stanislav_kuznetsov@ukr.net") + " (Ukrainian)
    " + + authorString("Seyyed Razi Alavizadeh", "s.r.alavizadeh@gmail.com") + " (Persian)" ); aPage = qz_applyDirectionToPage(aPage); } @@ -304,6 +311,27 @@ QString QupZillaSchemeReply::speeddialPage() return page; } +QString QupZillaSchemeReply::restorePage() +{ + static QString rPage; + + if (rPage.isEmpty()) { + rPage.append(qz_readAllFileContents(":html/restore.html")); + rPage.replace("%FAVICON%", "qrc:icons/qupzilla.png"); + rPage.replace("%BOX-BORDER%", "qrc:html/box-border.png"); + rPage.replace("%IMAGE%", qz_pixmapToByteArray(qIconProvider->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(45, 45))); + + + rPage.replace("%TITLE%", tr("Restore Session")); + rPage.replace("%OOPS%", tr("Oops, QupZilla crashed.")); + rPage.replace("%APOLOGIZE%", tr("We apologize for this. Would you like to restore the last saved state?")); + rPage.replace("%TRY-REMOVING%", tr("Try removing one or more tabs that you think cause troubles")); + rPage.replace("%START-NEW%", tr("Or you can start completely new session")); + rPage = qz_applyDirectionToPage(rPage); + } + + return rPage; +} QString QupZillaSchemeReply::configPage() { diff --git a/src/lib/network/qupzillaschemehandler.h b/src/lib/network/qupzillaschemehandler.h index 9fd40b3f3..81d94e875 100644 --- a/src/lib/network/qupzillaschemehandler.h +++ b/src/lib/network/qupzillaschemehandler.h @@ -53,6 +53,7 @@ private: QString reportbugPage(); QString startPage(); QString speeddialPage(); + QString restorePage(); QString configPage(); QBuffer m_buffer; diff --git a/src/lib/session/recoverywidget.cpp b/src/lib/session/recoverywidget.cpp new file mode 100644 index 000000000..a52103a08 --- /dev/null +++ b/src/lib/session/recoverywidget.cpp @@ -0,0 +1,120 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 Franz Fellner +* David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +* ============================================================ */ +#include "recoverywidget.h" +#include "ui_recoverywidget.h" +#include "restoremanager.h" +#include "mainapplication.h" +#include "webview.h" +#include "qupzilla.h" + +RecoveryWidget::RecoveryWidget(WebView* view, QupZilla* mainClass) + : QWidget() + , ui(new Ui::RecoveryWidget) + , m_restoreManager(mApp->restoreManager()) + , m_view(view) + , p_QupZilla(mainClass) +{ + ui->setupUi(this); + + const RestoreData &data = m_restoreManager->restoreData(); + + for (int i = 0; i < data.size(); ++i) { + const RestoreManager::WindowData &wd = data.at(i); + + QTreeWidgetItem* root = new QTreeWidgetItem(ui->treeWidget); + root->setText(0, tr("Window %1").arg((i + 1))); + root->setCheckState(0, Qt::Checked); + + for (int tab = 0; tab < wd.tabsState.size(); ++tab) { + const WebTab::SavedTab &st = wd.tabsState.at(tab); + + QTreeWidgetItem* child = new QTreeWidgetItem(root); + child->setCheckState(0, Qt::Checked); + child->setIcon(0, st.icon); + child->setText(0, st.title); + } + } + + ui->treeWidget->expandAll(); + + connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onItemChanged(QTreeWidgetItem*, int))); + connect(ui->restoreSession, SIGNAL(clicked()), this, SLOT(restoreSession())); + connect(ui->newSession, SIGNAL(clicked()), this, SLOT(newSession())); +} + +void RecoveryWidget::onItemChanged(QTreeWidgetItem* item, int column) +{ + if (column != 0 || item->childCount() == 0) { + return; + } + + bool disabled = item->checkState(0) == Qt::Unchecked; + + for (int i = 0; i < item->childCount(); ++i) { + item->child(i)->setDisabled(disabled); + } +} + +void RecoveryWidget::restoreSession() +{ + RestoreData data = m_restoreManager->restoreData(); + + for (int win = ui->treeWidget->topLevelItemCount() - 1; win >= 0; --win) { + QTreeWidgetItem* root = ui->treeWidget->topLevelItem(win); + if (root->checkState(0) == Qt::Unchecked) { + data.removeAt(win); + continue; + } + + RestoreManager::WindowData &wd = data[win]; + for (int tab = root->childCount() - 1; tab >= 0; --tab) { + if (root->child(tab)->checkState(0) == Qt::Unchecked) { + wd.tabsState.removeAt(tab); + if (wd.currentTab >= tab) { + wd.currentTab--; + } + } + } + + if (wd.tabsState.isEmpty()) { + data.removeAt(win); + continue; + } + + if (wd.currentTab < 0) { + wd.currentTab = wd.tabsState.size() - 1; + } + } + + if (!mApp->restoreStateSlot(p_QupZilla, data)) { + newSession(); + } +} + +void RecoveryWidget::newSession() +{ + m_view->load(p_QupZilla->homepageUrl()); + + mApp->destroyRestoreManager(); +} + +RecoveryWidget::~RecoveryWidget() +{ + delete ui; +} diff --git a/src/lib/session/recoverywidget.h b/src/lib/session/recoverywidget.h new file mode 100644 index 000000000..66ce2470c --- /dev/null +++ b/src/lib/session/recoverywidget.h @@ -0,0 +1,57 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 Franz Fellner +* David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +* ============================================================ */ +#ifndef RECOVERYWIDGET_H +#define RECOVERYWIDGET_H + +#include + +namespace Ui +{ +class RecoveryWidget; +} + +class QTreeWidgetItem; + +class WebView; +class QupZilla; +class RestoreManager; + +class RecoveryWidget : public QWidget +{ + Q_OBJECT + +public: + explicit RecoveryWidget(WebView* view, QupZilla* mainClass); + ~RecoveryWidget(); + +private slots: + void onItemChanged(QTreeWidgetItem* item, int column); + + void restoreSession(); + void newSession(); + +private: + Ui::RecoveryWidget* ui; + + RestoreManager* m_restoreManager; + WebView* m_view; + QupZilla* p_QupZilla; +}; + +#endif // RECOVERYWIDGET_H diff --git a/src/lib/session/recoverywidget.ui b/src/lib/session/recoverywidget.ui new file mode 100644 index 000000000..e5e102dab --- /dev/null +++ b/src/lib/session/recoverywidget.ui @@ -0,0 +1,70 @@ + + + RecoveryWidget + + + + 0 + 0 + 500 + 300 + + + + + + + + Windows and Tabs + + + + + + + + + + + 0 + 30 + + + + Restore + + + + + + + + 0 + 30 + + + + Start New Session + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + diff --git a/src/lib/session/restoremanager.cpp b/src/lib/session/restoremanager.cpp new file mode 100644 index 000000000..8bb01b725 --- /dev/null +++ b/src/lib/session/restoremanager.cpp @@ -0,0 +1,87 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 Franz Fellner +* David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +* ============================================================ */ +#include "restoremanager.h" + +#include + +RestoreManager::RestoreManager(const QString &sessionFile) +{ + createFromFile(sessionFile); +} + +RestoreData RestoreManager::restoreData() const +{ + return m_data; +} + +// Version of session.dat file +static const int sessionVersion = 0x0003; + +void RestoreManager::createFromFile(const QString &file) +{ + if (!QFile::exists(file)) { + return; + } + + QFile recoveryFile(file); + recoveryFile.open(QIODevice::ReadOnly); + QDataStream stream(&recoveryFile); + + int version; + stream >> version; + if (version != sessionVersion) { + return; + } + + int windowCount; + stream >> windowCount; + + for (int win = 0; win < windowCount; ++win) { + QByteArray tabState; + QByteArray windowState; + stream >> tabState; + stream >> windowState; + + WindowData wd; + wd.windowState = windowState; + + { + QDataStream tabStream(tabState); + if (tabStream.atEnd()) { + continue; + } + + QList tabs; + int tabListCount = 0; + tabStream >> tabListCount; + for (int i = 0; i < tabListCount; ++i) { + WebTab::SavedTab tab; + tabStream >> tab; + tabs.append(tab); + } + wd.tabsState = tabs; + + int currentTab; + tabStream >> currentTab; + wd.currentTab = currentTab; + } + + m_data.append(wd); + } +} diff --git a/src/lib/session/restoremanager.h b/src/lib/session/restoremanager.h new file mode 100644 index 000000000..82b4d4fb5 --- /dev/null +++ b/src/lib/session/restoremanager.h @@ -0,0 +1,45 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2010-2012 Franz Fellner +* David Rosca +* +* 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 3 of the License, or +* (at your option) any later version. +* +* 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 . +* ============================================================ */ +#ifndef RESTOREMANAGER_H +#define RESTOREMANAGER_H + +#include "webtab.h" + +class RestoreManager +{ +public: + struct WindowData { + int currentTab; + QByteArray windowState; + QList tabsState; + }; + + RestoreManager(const QString &sessionFile); + + QList restoreData() const; + +private: + void createFromFile(const QString &file); + + QList m_data; +}; + +typedef QList RestoreData; + +#endif // RESTOREMANAGER_H diff --git a/src/lib/webview/tabwidget.cpp b/src/lib/webview/tabwidget.cpp index bf5ed4b7d..e4d35105e 100644 --- a/src/lib/webview/tabwidget.cpp +++ b/src/lib/webview/tabwidget.cpp @@ -342,7 +342,7 @@ int TabWidget::addView(QNetworkRequest req, const QString &title, const Qz::NewT return index; } -void TabWidget::closeTab(int index) +void TabWidget::closeTab(int index, bool force) { if (index == -1) { index = currentIndex(); @@ -356,7 +356,12 @@ void TabWidget::closeTab(int index) TabbedWebView* webView = webTab->view(); WebPage* webPage = webView->page(); - if (count() == 1) { + if (!force && webView->url() == QUrl("qupzilla:restore") && mApp->restoreManager()) { + // Don't close restore page! + return; + } + + if (!force && count() == 1) { if (m_dontQuitWithOneTab && mApp->windowCount() == 1) { webView->load(m_urlOnNewTab); return; @@ -775,30 +780,22 @@ QByteArray TabWidget::saveState() return data; } -bool TabWidget::restoreState(const QByteArray &state) +bool TabWidget::restoreState(const QList &tabs, int currentTab) { - QDataStream stream(state); - if (stream.atEnd()) { - return false; - } - - int tabListCount = 0; - int currentTab = 0; - - stream >> tabListCount; - m_isRestoringState = true; - for (int i = 0; i < tabListCount; ++i) { - WebTab::SavedTab tab; - stream >> tab; + foreach(WebTab * tab, allTabs()) { + int tabIndex = tab->tabIndex(); + closeTab(tabIndex, true); + } + + for (int i = 0; i < tabs.size(); ++i) { + WebTab::SavedTab tab = tabs.at(i); int index = addView(QUrl(), Qz::NT_CleanSelectedTab); weTab(index)->restoreTab(tab); } - stream >> currentTab; - m_isRestoringState = false; setCurrentIndex(currentTab); diff --git a/src/lib/webview/tabwidget.h b/src/lib/webview/tabwidget.h index 339aa3edb..c1dc339a4 100644 --- a/src/lib/webview/tabwidget.h +++ b/src/lib/webview/tabwidget.h @@ -24,6 +24,7 @@ #include "toolbutton.h" #include "qz_namespace.h" +#include "webtab.h" class QStackedWidget; class QMenu; @@ -32,7 +33,6 @@ class QupZilla; class TabbedWebView; class TabBar; class TabWidget; -class WebTab; class ClosedTabsManager; class QT_QUPZILLA_EXPORT AddTabButton : public ToolButton @@ -60,7 +60,7 @@ public: void loadSettings(); QByteArray saveState(); - bool restoreState(const QByteArray &state); + bool restoreState(const QList &tabs, int currentTab); void savePinnedTabs(); void restorePinnedTabs(); @@ -99,7 +99,7 @@ public slots: int duplicateTab(int index); - void closeTab(int index = -1); + void closeTab(int index = -1, bool force = false); void reloadTab(int index); void reloadAllTabs(); void stopTab(int index); diff --git a/src/lib/webview/webpage.cpp b/src/lib/webview/webpage.cpp index 50f22e53b..b2c5e84c7 100644 --- a/src/lib/webview/webpage.cpp +++ b/src/lib/webview/webpage.cpp @@ -35,6 +35,7 @@ #include "iconprovider.h" #include "qzsettings.h" #include "useragentmanager.h" +#include "recoverywidget.h" #ifdef NONBLOCK_JS_DIALOGS #include "ui_jsconfirm.h" @@ -495,8 +496,15 @@ QWebPage* WebPage::createWindow(QWebPage::WebWindowType type) QObject* WebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) { - qDebug() << Q_FUNC_INFO; - return pluginFactory()->create(classid, url, paramNames, paramValues); + Q_UNUSED(url) + Q_UNUSED(paramNames) + Q_UNUSED(paramValues) + + if (classid == "RecoveryWidget" && mApp->restoreManager()) { + return new RecoveryWidget(qobject_cast(view()), p_QupZilla); + } + + return 0; } void WebPage::addAdBlockRule(const AdBlockRule* rule, const QUrl &url) diff --git a/src/main/main.pro b/src/main/main.pro index bd4c0d074..b11972458 100644 --- a/src/main/main.pro +++ b/src/main/main.pro @@ -14,7 +14,9 @@ include(../install.pri) unix:!contains(DEFINES, "DISABLE_DBUS") QT += dbus INCLUDEPATH += ../lib/app\ - ../lib/3rdparty + ../lib/3rdparty\ + ../lib/session\ + ../lib/webview SOURCES = main.cpp OTHER_FILES += appicon.rc \ diff --git a/src/plugins.pri b/src/plugins.pri index 27050a2e7..3c28e6c4f 100644 --- a/src/plugins.pri +++ b/src/plugins.pri @@ -5,6 +5,7 @@ INCLUDEPATH += $$PWD/lib/3rdparty\ $$PWD/lib/autofill\ $$PWD/lib/bookmarks\ $$PWD/lib/cookies\ + $$PWD/lib/session\ $$PWD/lib/downloads\ $$PWD/lib/history\ $$PWD/lib/navigation\