1
mirror of https://invent.kde.org/network/falkon.git synced 2024-11-11 01:22:10 +01:00

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
This commit is contained in:
nowrep 2012-08-21 20:28:38 +02:00
parent 0b6bc74735
commit 80e89b2644
21 changed files with 532 additions and 82 deletions

View File

@ -7,6 +7,7 @@ Contributors:
Mladen Pejaković <pejakm@gmail.com> (webview context menu improvements, speed dial background) Mladen Pejaković <pejakm@gmail.com> (webview context menu improvements, speed dial background)
Alexander Samilov <alexsamilovskih@gmail.com> (tab previews) Alexander Samilov <alexsamilovskih@gmail.com> (tab previews)
Seyyed Razi Alavizadeh <s.r.alavizadeh@gmail.com> (fixed UI for RTL languages) Seyyed Razi Alavizadeh <s.r.alavizadeh@gmail.com> (fixed UI for RTL languages)
Franz Fellner <alpine.art.de@googlemail.com> (new restore session ui)
Bryan M Dunsmore <dunsmoreb@gmail.com> (opening background tabs, closing window when closing last tab) Bryan M Dunsmore <dunsmoreb@gmail.com> (opening background tabs, closing window when closing last tab)
Mariusz Fik <fisiu@opensuse.org> (fixed tab order in preferences dialog) Mariusz Fik <fisiu@opensuse.org> (fixed tab order in preferences dialog)
Daniele Cocca <jmc@chakra-project.org> (close tabs with middle click, initial work on speed dial) Daniele Cocca <jmc@chakra-project.org> (close tabs with middle click, initial work on speed dial)

View File

@ -65,7 +65,7 @@ static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;
QHash<QWidget *, bool> widgetsBlurState = QHash<QWidget *, bool>(); QHash<QWidget*, bool> widgetsBlurState = QHash<QWidget*, bool>();
/* /*
* Internal helper class that notifies windows if the * Internal helper class that notifies windows if the
@ -261,8 +261,7 @@ bool WindowNotifier::winEvent(MSG* message, long* result)
if (widget) { if (widget) {
widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
bool isBlur = widgetsBlurState.value(widget, false); bool isBlur = widgetsBlurState.value(widget, false);
if (compositionEnabled && isBlur) if (compositionEnabled && isBlur) {
{
// hack for fixing black background when enabling composition // hack for fixing black background when enabling composition
QtWin::enableBlurBehindWindow(widget, false); QtWin::enableBlurBehindWindow(widget, false);
QtWin::extendFrameIntoClientArea(widget); QtWin::extendFrameIntoClientArea(widget);

View File

@ -48,6 +48,7 @@
#include "clearprivatedata.h" #include "clearprivatedata.h"
#include "commandlineoptions.h" #include "commandlineoptions.h"
#include "useragentmanager.h" #include "useragentmanager.h"
#include "restoremanager.h"
#ifdef Q_WS_MAC #ifdef Q_WS_MAC
#include <QFileOpenEvent> #include <QFileOpenEvent>
@ -81,6 +82,7 @@ MainApplication::MainApplication(int &argc, char** argv)
, m_networkCache(0) , m_networkCache(0)
, m_desktopNotifications(0) , m_desktopNotifications(0)
, m_searchEnginesManager(0) , m_searchEnginesManager(0)
, m_restoreManager(0)
, m_dbWriter(new DatabaseWriter(this)) , m_dbWriter(new DatabaseWriter(this))
, m_uaManager(new UserAgentManager) , m_uaManager(new UserAgentManager)
, m_isPrivateSession(false) , m_isPrivateSession(false)
@ -109,7 +111,6 @@ MainApplication::MainApplication(int &argc, char** argv)
TRANSLATIONSDIR = DATADIR + "locale/"; TRANSLATIONSDIR = DATADIR + "locale/";
THEMESDIR = DATADIR + "themes/"; THEMESDIR = DATADIR + "themes/";
setOverrideCursor(Qt::WaitCursor);
setWindowIcon(QIcon(":icons/exeicons/qupzilla-window.png")); setWindowIcon(QIcon(":icons/exeicons/qupzilla-window.png"));
bool noAddons = false; bool noAddons = false;
QUrl startUrl; QUrl startUrl;
@ -234,11 +235,16 @@ MainApplication::MainApplication(int &argc, char** argv)
Settings settings; Settings settings;
m_startingAfterCrash = settings.value("SessionRestore/isRunning", false).toBool(); m_startingAfterCrash = settings.value("SessionRestore/isRunning", false).toBool();
bool checkUpdates = settings.value("Web-Browser-Settings/CheckUpdates", DEFAULT_CHECK_UPDATES).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); settings.setValue("SessionRestore/isRunning", true);
if (checkUpdates) { if (checkUpdates) {
new Updater(qupzilla); new Updater(qupzilla);
} }
if (m_startingAfterCrash || afterLaunch == 3) {
m_restoreManager = new RestoreManager(m_activeProfil + "session.dat");
}
} }
QTimer::singleShot(0, this, SLOT(postLaunch())); QTimer::singleShot(0, this, SLOT(postLaunch()));
@ -816,12 +822,12 @@ void MainApplication::aboutToCloseWindow(QupZilla* window)
m_mainWindows.removeOne(window); m_mainWindows.removeOne(window);
} }
//Version of session.dat file // Version of session.dat file
static const int sessionVersion = 0x0003; static const int sessionVersion = 0x0003;
bool MainApplication::saveStateSlot() 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; return false;
} }
@ -858,7 +864,7 @@ bool MainApplication::saveStateSlot()
return true; return true;
} }
bool MainApplication::restoreStateSlot(QupZilla* window) bool MainApplication::restoreStateSlot(QupZilla* window, const RestoreData &recoveryData)
{ {
if (m_isPrivateSession) { if (m_isPrivateSession) {
return false; return false;
@ -866,47 +872,34 @@ bool MainApplication::restoreStateSlot(QupZilla* window)
m_isRestoring = true; m_isRestoring = true;
if (!QFile::exists(m_activeProfil + "session.dat")) { if (recoveryData.isEmpty()) {
m_isRestoring = false; m_isRestoring = false;
return false; return false;
} }
QFile file(m_activeProfil + "session.dat"); int windowCount = recoveryData.size();
file.open(QIODevice::ReadOnly); int currentWindow = 0;
QDataStream stream(&file);
QByteArray tabState; while (window) {
QByteArray windowState; const RestoreManager::WindowData &wd = recoveryData.at(currentWindow);
int version; window->restoreWindowState(wd);
int windowCount; window->show();
stream >> version; ++currentWindow;
if (version != sessionVersion) {
m_isRestoring = false;
return false;
}
stream >> windowCount;
stream >> tabState;
stream >> windowState;
window->restoreWindowState(windowState, tabState); if (currentWindow < windowCount) {
window = new QupZilla(Qz::BW_OtherRestoredWindow);
if (windowCount > 1) {
for (int i = 1; i < windowCount; i++) {
stream >> tabState;
stream >> windowState;
QupZilla* window = new QupZilla(Qz::BW_OtherRestoredWindow);
m_mainWindows.append(window); m_mainWindows.append(window);
}
window->restoreWindowState(windowState, tabState); else {
window = 0;
window->show();
} }
} }
file.close();
destroyRestoreManager();
m_isRestoring = false; m_isRestoring = false;
return true; return true;
} }
@ -959,6 +952,12 @@ bool MainApplication::checkSettingsDir()
return dir.isReadable(); return dir.isReadable();
} }
void MainApplication::destroyRestoreManager()
{
delete m_restoreManager;
m_restoreManager = 0;
}
MainApplication::~MainApplication() MainApplication::~MainApplication()
{ {
delete m_uaManager; delete m_uaManager;

View File

@ -24,6 +24,7 @@
#include <QUrl> #include <QUrl>
#include <QWeakPointer> #include <QWeakPointer>
#include "restoremanager.h"
#include "qtsingleapplication.h" #include "qtsingleapplication.h"
#include "qz_namespace.h" #include "qz_namespace.h"
@ -64,7 +65,7 @@ public:
void connectDatabase(); void connectDatabase();
void loadSettings(); void loadSettings();
void reloadSettings(); void reloadSettings();
bool restoreStateSlot(QupZilla* window); bool restoreStateSlot(QupZilla* window, const RestoreData &recoveryData);
QupZilla* makeNewWindow(Qz::BrowserWindow type, const QUrl &startUrl = QUrl()); QupZilla* makeNewWindow(Qz::BrowserWindow type, const QUrl &startUrl = QUrl());
void aboutToCloseWindow(QupZilla* window); void aboutToCloseWindow(QupZilla* window);
bool isStateChanged(); bool isStateChanged();
@ -80,6 +81,7 @@ public:
inline int windowCount() { return m_mainWindows.count(); } inline int windowCount() { return m_mainWindows.count(); }
bool checkSettingsDir(); bool checkSettingsDir();
void destroyRestoreManager();
QupZilla* getWindow(); QupZilla* getWindow();
CookieManager* cookieManager(); CookieManager* cookieManager();
@ -99,6 +101,7 @@ public:
DatabaseWriter* dbWriter() { return m_dbWriter; } DatabaseWriter* dbWriter() { return m_dbWriter; }
UserAgentManager* uaManager() { return m_uaManager; } UserAgentManager* uaManager() { return m_uaManager; }
RestoreManager* restoreManager() { return m_restoreManager; }
#ifdef Q_WS_MAC #ifdef Q_WS_MAC
bool event(QEvent* e); bool event(QEvent* e);
@ -147,6 +150,7 @@ private:
QNetworkDiskCache* m_networkCache; QNetworkDiskCache* m_networkCache;
DesktopNotificationsFactory* m_desktopNotifications; DesktopNotificationsFactory* m_desktopNotifications;
SearchEnginesManager* m_searchEnginesManager; SearchEnginesManager* m_searchEnginesManager;
RestoreManager* m_restoreManager;
DatabaseWriter* m_dbWriter; DatabaseWriter* m_dbWriter;
UserAgentManager* m_uaManager; UserAgentManager* m_uaManager;

View File

@ -162,19 +162,12 @@ void QupZilla::postLaunch()
switch (m_startBehaviour) { switch (m_startBehaviour) {
case Qz::BW_FirstAppWindow: case Qz::BW_FirstAppWindow:
if (afterLaunch == 3) { if (mApp->isStartingAfterCrash()) {
addTab = !mApp->restoreStateSlot(this); addTab = true;
startUrl = QUrl("qupzilla:restore");
} }
else if (mApp->isStartingAfterCrash()) { else if (afterLaunch == 3 && mApp->restoreManager()) {
QMessageBox::StandardButton button = QMessageBox::warning(this, tr("Last session crashed"), addTab = !mApp->restoreStateSlot(this, mApp->restoreManager()->restoreData());
tr("<b>QupZilla crashed :-(</b><br/>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);
}
} }
break; 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); QMainWindow::restoreState(d.windowState);
m_tabWidget->restoreState(tabs); m_tabWidget->restoreState(d.tabsState, d.currentTab);
} }
void QupZilla::aboutQupZilla() void QupZilla::aboutQupZilla()

View File

@ -22,6 +22,7 @@
#include <QUrl> #include <QUrl>
#include "qwebkitversion.h" #include "qwebkitversion.h"
#include "restoremanager.h"
#include "qz_namespace.h" #include "qz_namespace.h"
class QMenuBar; class QMenuBar;
@ -48,6 +49,7 @@ class NavigationBar;
class ClickableLabel; class ClickableLabel;
class WebInspectorDockWidget; class WebInspectorDockWidget;
class LocationBar; class LocationBar;
class QT_QUPZILLA_EXPORT QupZilla : public QMainWindow class QT_QUPZILLA_EXPORT QupZilla : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
@ -74,7 +76,7 @@ public:
void addBookmark(const QUrl &url, const QString &title, const QIcon &icon); void addBookmark(const QUrl &url, const QString &title, const QIcon &icon);
void addDeleteOnCloseWidget(QWidget* widget); void addDeleteOnCloseWidget(QWidget* widget);
void restoreWindowState(const QByteArray &window, const QByteArray &tabs); void restoreWindowState(const RestoreManager::WindowData &d);
SideBar* addSideBar(); SideBar* addSideBar();
virtual QMenuBar* menuBar() const; virtual QMenuBar* menuBar() const;

View File

@ -22,5 +22,6 @@
<file>html/broken-page.png</file> <file>html/broken-page.png</file>
<file>html/setting.png</file> <file>html/setting.png</file>
<file>html/config.html</file> <file>html/config.html</file>
<file>html/restore.html</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -0,0 +1,29 @@
<html><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="icon" href="%FAVICON%" type="image/x-icon" />
<title>%TITLE%</title>
<style>
html {background: #eeeeee;font: 14px/22px "Helvetica Neue", Helvetica, Arial, sans-serif;color: #525c66;}
html * {font-size: 100%;line-height: 1.6;}
#box {max-width:650px;min-width:400px;overflow:auto;margin: 25px auto 10px auto;padding: 10px 40px;border-width: 20px;text-align: %LEFT_STR%;-webkit-border-image: url(%BOX-BORDER%) 25;direction: %DIRECTION%;}
hr {color: lightgray;width: 100%;}
img {float: %LEFT_STR%;margin-%LEFT_STR%: -20px;margin-top: 15px;}
h1 {font-size: 150%;font-weight: bold;border-bottom: 1px solid #f4f4f4;margin-%LEFT_STR%: 48px;margin-%RIGHT_STR%: 50px;}
h2 {font-size: 100%;font-weight: normal;border-bottom: 1px solid #f4f4f4;margin-%LEFT_STR%: 48px;padding: 5px 0px 10px 2px;margin-%RIGHT_STR%: 50px;}
ul {font-size: 90%;padding-%LEFT_STR%: 48px;margin: 20px 0;max-width:600px;}
li {padding: 5px;}
</style>
</head>
<body>
<div id="box">
<img src="data:image/png;base64,%IMAGE%" >
<h1>%OOPS%</h1>
<h2>%APOLOGIZE%</h2>
<ul>
<li>%TRY-REMOVING%</li>
<li>%START-NEW%</li>
<object type="application/x-qt-plugin" classid="RecoveryWidget" name="recovery-widget" height="250" width="500">
</ul>
</div>
</body></html>

View File

@ -16,6 +16,7 @@ INCLUDEPATH += 3rdparty\
autofill\ autofill\
bookmarks\ bookmarks\
cookies\ cookies\
session\
downloads\ downloads\
history\ history\
navigation\ navigation\
@ -182,7 +183,9 @@ SOURCES += \
preferences/pluginsmanager.cpp \ preferences/pluginsmanager.cpp \
other/qzsettings.cpp \ other/qzsettings.cpp \
other/useragentmanager.cpp \ other/useragentmanager.cpp \
preferences/useragentdialog.cpp preferences/useragentdialog.cpp \
session/recoverywidget.cpp \
session/restoremanager.cpp
HEADERS += \ HEADERS += \
webview/tabpreview.h \ webview/tabpreview.h \
@ -336,7 +339,9 @@ HEADERS += \
preferences/pluginsmanager.h \ preferences/pluginsmanager.h \
other/qzsettings.h \ other/qzsettings.h \
other/useragentmanager.h \ other/useragentmanager.h \
preferences/useragentdialog.h preferences/useragentdialog.h \
session/recoverywidget.h \
session/restoremanager.h
FORMS += \ FORMS += \
preferences/autofillmanager.ui \ preferences/autofillmanager.ui \
@ -380,7 +385,8 @@ FORMS += \
other/checkboxdialog.ui \ other/checkboxdialog.ui \
other/iconchooser.ui \ other/iconchooser.ui \
adblock/adblockaddsubscriptiondialog.ui \ adblock/adblockaddsubscriptiondialog.ui \
preferences/useragentdialog.ui preferences/useragentdialog.ui \
session/recoverywidget.ui
RESOURCES += \ RESOURCES += \
data/icons.qrc \ data/icons.qrc \

View File

@ -25,6 +25,7 @@
#include "pluginproxy.h" #include "pluginproxy.h"
#include "plugininterface.h" #include "plugininterface.h"
#include "settings.h" #include "settings.h"
#include "iconprovider.h"
#include <QTextDocument> #include <QTextDocument>
#include <QTextStream> #include <QTextStream>
@ -61,7 +62,7 @@ QupZillaSchemeReply::QupZillaSchemeReply(const QNetworkRequest &req, QObject* pa
m_pageName = req.url().path(); m_pageName = req.url().path();
QStringList knownPages; QStringList knownPages;
knownPages << "about" << "reportbug" << "start" << "speeddial" << "config"; knownPages << "about" << "reportbug" << "start" << "speeddial" << "config" << "restore";
if (knownPages.contains(m_pageName)) { if (knownPages.contains(m_pageName)) {
m_buffer.open(QIODevice::ReadWrite); m_buffer.open(QIODevice::ReadWrite);
@ -96,6 +97,9 @@ void QupZillaSchemeReply::loadPage()
else if (m_pageName == "config") { else if (m_pageName == "config") {
stream << configPage(); stream << configPage();
} }
else if (m_pageName == "restore") {
stream << restorePage();
}
stream.flush(); stream.flush();
m_buffer.reset(); m_buffer.reset();
@ -207,6 +211,8 @@ QString QupZillaSchemeReply::aboutPage()
aPage.replace("%CONTRIBUTORS-TEXT%", aPage.replace("%CONTRIBUTORS-TEXT%",
authorString("Mladen Pejaković", "pejakm@gmail.com") + "<br/>" + authorString("Mladen Pejaković", "pejakm@gmail.com") + "<br/>" +
authorString("Alexander Samilov", "alexsamilovskih@gmail.com") + "<br/>" + authorString("Alexander Samilov", "alexsamilovskih@gmail.com") + "<br/>" +
authorString("Seyyed Razi Alavizadeh", "s.r.alavizadeh@gmail.com") + "<br/>" +
authorString("Franz Fellner", "alpine.art.de@googlemail.com") + "<br/>" +
authorString("Bryan M Dunsmore", "dunsmoreb@gmail.com") + "<br/>" + authorString("Bryan M Dunsmore", "dunsmoreb@gmail.com") + "<br/>" +
authorString("Mariusz Fik", "fisiu@opensuse.org") + "<br/>" + authorString("Mariusz Fik", "fisiu@opensuse.org") + "<br/>" +
authorString("Jan Rajnoha", "honza.rajny@hotmail.com") + "<br/>" + authorString("Jan Rajnoha", "honza.rajny@hotmail.com") + "<br/>" +
@ -239,7 +245,8 @@ QString QupZillaSchemeReply::aboutPage()
authorString("Daiki Noda", "sys.pdr.pdm9@gmail.com") + " (Japanese)<br/>" + authorString("Daiki Noda", "sys.pdr.pdm9@gmail.com") + " (Japanese)<br/>" +
authorString("Gábor Oberle", "oberleg@myopera.com") + " (Hungarian)<br/>" + authorString("Gábor Oberle", "oberleg@myopera.com") + " (Hungarian)<br/>" +
authorString("Piccoro McKay Lenz", "mckaygerhard@gmail.com") + " (Venezulean Spanish)<br/>" + authorString("Piccoro McKay Lenz", "mckaygerhard@gmail.com") + " (Venezulean Spanish)<br/>" +
authorString("Stanislav Kuznietsov", "stanislav_kuznetsov@ukr.net") + " (Ukrainian)" authorString("Stanislav Kuznietsov", "stanislav_kuznetsov@ukr.net") + " (Ukrainian)<br/>" +
authorString("Seyyed Razi Alavizadeh", "s.r.alavizadeh@gmail.com") + " (Persian)"
); );
aPage = qz_applyDirectionToPage(aPage); aPage = qz_applyDirectionToPage(aPage);
} }
@ -304,6 +311,27 @@ QString QupZillaSchemeReply::speeddialPage()
return page; 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() QString QupZillaSchemeReply::configPage()
{ {

View File

@ -53,6 +53,7 @@ private:
QString reportbugPage(); QString reportbugPage();
QString startPage(); QString startPage();
QString speeddialPage(); QString speeddialPage();
QString restorePage();
QString configPage(); QString configPage();
QBuffer m_buffer; QBuffer m_buffer;

View File

@ -0,0 +1,120 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2012 Franz Fellner <alpine.art.de@googlemail.com>
* David Rosca <nowrep@gmail.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 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 <http://www.gnu.org/licenses/>.
* ============================================================ */
#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;
}

View File

@ -0,0 +1,57 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2012 Franz Fellner <alpine.art.de@googlemail.com>
* David Rosca <nowrep@gmail.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 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 <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef RECOVERYWIDGET_H
#define RECOVERYWIDGET_H
#include <QWidget>
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

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RecoveryWidget</class>
<widget class="QWidget" name="RecoveryWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>300</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="treeWidget">
<column>
<property name="text">
<string notr="true">Windows and Tabs</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="restoreSession">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Restore</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="newSession">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Start New Session</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,87 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2012 Franz Fellner <alpine.art.de@googlemail.com>
* David Rosca <nowrep@gmail.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 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 <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "restoremanager.h"
#include <QFile>
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<WebTab::SavedTab> 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);
}
}

View File

@ -0,0 +1,45 @@
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2010-2012 Franz Fellner <alpine.art.de@googlemail.com>
* David Rosca <nowrep@gmail.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 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 <http://www.gnu.org/licenses/>.
* ============================================================ */
#ifndef RESTOREMANAGER_H
#define RESTOREMANAGER_H
#include "webtab.h"
class RestoreManager
{
public:
struct WindowData {
int currentTab;
QByteArray windowState;
QList<WebTab::SavedTab> tabsState;
};
RestoreManager(const QString &sessionFile);
QList<RestoreManager::WindowData> restoreData() const;
private:
void createFromFile(const QString &file);
QList<RestoreManager::WindowData> m_data;
};
typedef QList<RestoreManager::WindowData> RestoreData;
#endif // RESTOREMANAGER_H

View File

@ -342,7 +342,7 @@ int TabWidget::addView(QNetworkRequest req, const QString &title, const Qz::NewT
return index; return index;
} }
void TabWidget::closeTab(int index) void TabWidget::closeTab(int index, bool force)
{ {
if (index == -1) { if (index == -1) {
index = currentIndex(); index = currentIndex();
@ -356,7 +356,12 @@ void TabWidget::closeTab(int index)
TabbedWebView* webView = webTab->view(); TabbedWebView* webView = webTab->view();
WebPage* webPage = webView->page(); 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) { if (m_dontQuitWithOneTab && mApp->windowCount() == 1) {
webView->load(m_urlOnNewTab); webView->load(m_urlOnNewTab);
return; return;
@ -775,30 +780,22 @@ QByteArray TabWidget::saveState()
return data; return data;
} }
bool TabWidget::restoreState(const QByteArray &state) bool TabWidget::restoreState(const QList<WebTab::SavedTab> &tabs, int currentTab)
{ {
QDataStream stream(state);
if (stream.atEnd()) {
return false;
}
int tabListCount = 0;
int currentTab = 0;
stream >> tabListCount;
m_isRestoringState = true; m_isRestoringState = true;
for (int i = 0; i < tabListCount; ++i) { foreach(WebTab * tab, allTabs()) {
WebTab::SavedTab tab; int tabIndex = tab->tabIndex();
stream >> tab; closeTab(tabIndex, true);
}
for (int i = 0; i < tabs.size(); ++i) {
WebTab::SavedTab tab = tabs.at(i);
int index = addView(QUrl(), Qz::NT_CleanSelectedTab); int index = addView(QUrl(), Qz::NT_CleanSelectedTab);
weTab(index)->restoreTab(tab); weTab(index)->restoreTab(tab);
} }
stream >> currentTab;
m_isRestoringState = false; m_isRestoringState = false;
setCurrentIndex(currentTab); setCurrentIndex(currentTab);

View File

@ -24,6 +24,7 @@
#include "toolbutton.h" #include "toolbutton.h"
#include "qz_namespace.h" #include "qz_namespace.h"
#include "webtab.h"
class QStackedWidget; class QStackedWidget;
class QMenu; class QMenu;
@ -32,7 +33,6 @@ class QupZilla;
class TabbedWebView; class TabbedWebView;
class TabBar; class TabBar;
class TabWidget; class TabWidget;
class WebTab;
class ClosedTabsManager; class ClosedTabsManager;
class QT_QUPZILLA_EXPORT AddTabButton : public ToolButton class QT_QUPZILLA_EXPORT AddTabButton : public ToolButton
@ -60,7 +60,7 @@ public:
void loadSettings(); void loadSettings();
QByteArray saveState(); QByteArray saveState();
bool restoreState(const QByteArray &state); bool restoreState(const QList<WebTab::SavedTab> &tabs, int currentTab);
void savePinnedTabs(); void savePinnedTabs();
void restorePinnedTabs(); void restorePinnedTabs();
@ -99,7 +99,7 @@ public slots:
int duplicateTab(int index); int duplicateTab(int index);
void closeTab(int index = -1); void closeTab(int index = -1, bool force = false);
void reloadTab(int index); void reloadTab(int index);
void reloadAllTabs(); void reloadAllTabs();
void stopTab(int index); void stopTab(int index);

View File

@ -35,6 +35,7 @@
#include "iconprovider.h" #include "iconprovider.h"
#include "qzsettings.h" #include "qzsettings.h"
#include "useragentmanager.h" #include "useragentmanager.h"
#include "recoverywidget.h"
#ifdef NONBLOCK_JS_DIALOGS #ifdef NONBLOCK_JS_DIALOGS
#include "ui_jsconfirm.h" #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 &paramNames, const QStringList &paramValues) QObject* WebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
{ {
qDebug() << Q_FUNC_INFO; Q_UNUSED(url)
return pluginFactory()->create(classid, url, paramNames, paramValues); Q_UNUSED(paramNames)
Q_UNUSED(paramValues)
if (classid == "RecoveryWidget" && mApp->restoreManager()) {
return new RecoveryWidget(qobject_cast<WebView*>(view()), p_QupZilla);
}
return 0;
} }
void WebPage::addAdBlockRule(const AdBlockRule* rule, const QUrl &url) void WebPage::addAdBlockRule(const AdBlockRule* rule, const QUrl &url)

View File

@ -14,7 +14,9 @@ include(../install.pri)
unix:!contains(DEFINES, "DISABLE_DBUS") QT += dbus unix:!contains(DEFINES, "DISABLE_DBUS") QT += dbus
INCLUDEPATH += ../lib/app\ INCLUDEPATH += ../lib/app\
../lib/3rdparty ../lib/3rdparty\
../lib/session\
../lib/webview
SOURCES = main.cpp SOURCES = main.cpp
OTHER_FILES += appicon.rc \ OTHER_FILES += appicon.rc \

View File

@ -5,6 +5,7 @@ INCLUDEPATH += $$PWD/lib/3rdparty\
$$PWD/lib/autofill\ $$PWD/lib/autofill\
$$PWD/lib/bookmarks\ $$PWD/lib/bookmarks\
$$PWD/lib/cookies\ $$PWD/lib/cookies\
$$PWD/lib/session\
$$PWD/lib/downloads\ $$PWD/lib/downloads\
$$PWD/lib/history\ $$PWD/lib/history\
$$PWD/lib/navigation\ $$PWD/lib/navigation\