mirror of
https://invent.kde.org/network/falkon.git
synced 2024-11-11 01:22:10 +01:00
History completely rewritten into Model/View architecture.
- much faster history loading (loading history entries only when needed - eg. expanding top level items) - less memory usage (sidebar and manager are using the same model) - searching is now performed on title and url - clear private data -> clear history is now working properly
This commit is contained in:
parent
bb4d981c31
commit
5b75c0e5a0
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -22,3 +22,4 @@ git_revision
|
||||||
*.exp
|
*.exp
|
||||||
*.zip
|
*.zip
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
tests/modeltest
|
||||||
|
|
2
src/lib/3rdparty/qtwin.cpp
vendored
2
src/lib/3rdparty/qtwin.cpp
vendored
|
@ -29,7 +29,7 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include "historymodel.h"
|
#include "history.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
|
|
||||||
#ifdef Q_WS_WIN
|
#ifdef Q_WS_WIN
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "cookiemanager.h"
|
#include "cookiemanager.h"
|
||||||
#include "cookiejar.h"
|
#include "cookiejar.h"
|
||||||
#include "browsinglibrary.h"
|
#include "browsinglibrary.h"
|
||||||
#include "historymodel.h"
|
#include "history.h"
|
||||||
#include "networkmanager.h"
|
#include "networkmanager.h"
|
||||||
#include "rssmanager.h"
|
#include "rssmanager.h"
|
||||||
#include "updater.h"
|
#include "updater.h"
|
||||||
|
@ -634,10 +634,10 @@ CookieManager* MainApplication::cookieManager()
|
||||||
return m_cookiemanager;
|
return m_cookiemanager;
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryModel* MainApplication::history()
|
History* MainApplication::history()
|
||||||
{
|
{
|
||||||
if (!m_historymodel) {
|
if (!m_historymodel) {
|
||||||
m_historymodel = new HistoryModel(getWindow());
|
m_historymodel = new History(this);
|
||||||
}
|
}
|
||||||
return m_historymodel;
|
return m_historymodel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ class QNetworkDiskCache;
|
||||||
class QupZilla;
|
class QupZilla;
|
||||||
class CookieManager;
|
class CookieManager;
|
||||||
class BrowsingLibrary;
|
class BrowsingLibrary;
|
||||||
class HistoryModel;
|
class History;
|
||||||
class NetworkManager;
|
class NetworkManager;
|
||||||
class CookieJar;
|
class CookieJar;
|
||||||
class RSSManager;
|
class RSSManager;
|
||||||
|
@ -83,7 +83,7 @@ public:
|
||||||
QupZilla* getWindow();
|
QupZilla* getWindow();
|
||||||
CookieManager* cookieManager();
|
CookieManager* cookieManager();
|
||||||
BrowsingLibrary* browsingLibrary();
|
BrowsingLibrary* browsingLibrary();
|
||||||
HistoryModel* history();
|
History* history();
|
||||||
QWebSettings* webSettings();
|
QWebSettings* webSettings();
|
||||||
NetworkManager* networkManager();
|
NetworkManager* networkManager();
|
||||||
CookieJar* cookieJar();
|
CookieJar* cookieJar();
|
||||||
|
@ -127,7 +127,7 @@ private:
|
||||||
|
|
||||||
CookieManager* m_cookiemanager;
|
CookieManager* m_cookiemanager;
|
||||||
BrowsingLibrary* m_browsingLibrary;
|
BrowsingLibrary* m_browsingLibrary;
|
||||||
HistoryModel* m_historymodel;
|
History* m_historymodel;
|
||||||
QWebSettings* m_websettings;
|
QWebSettings* m_websettings;
|
||||||
NetworkManager* m_networkmanager;
|
NetworkManager* m_networkmanager;
|
||||||
CookieJar* m_cookiejar;
|
CookieJar* m_cookiejar;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "webpage.h"
|
#include "webpage.h"
|
||||||
#include "tabbedwebview.h"
|
#include "tabbedwebview.h"
|
||||||
#include "lineedit.h"
|
#include "lineedit.h"
|
||||||
#include "historymodel.h"
|
#include "history.h"
|
||||||
#include "locationbar.h"
|
#include "locationbar.h"
|
||||||
#include "searchtoolbar.h"
|
#include "searchtoolbar.h"
|
||||||
#include "websearchbar.h"
|
#include "websearchbar.h"
|
||||||
|
@ -578,7 +578,7 @@ void QupZilla::loadSettings()
|
||||||
m_navigationBar->buttonNext()->setVisible(showBackForwardIcons);
|
m_navigationBar->buttonNext()->setVisible(showBackForwardIcons);
|
||||||
m_navigationBar->buttonAddTab()->setVisible(showAddTab);
|
m_navigationBar->buttonAddTab()->setVisible(showAddTab);
|
||||||
|
|
||||||
m_sideBarManager->showSideBar(activeSideBar);
|
m_sideBarManager->showSideBar(activeSideBar, false);
|
||||||
|
|
||||||
//Private browsing
|
//Private browsing
|
||||||
m_actionPrivateBrowsing->setChecked(mApp->webSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled));
|
m_actionPrivateBrowsing->setChecked(mApp->webSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled));
|
||||||
|
@ -1148,6 +1148,7 @@ void QupZilla::showCookieManager()
|
||||||
m->raise();
|
m->raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QupZilla::showHistoryManager()
|
void QupZilla::showHistoryManager()
|
||||||
{
|
{
|
||||||
mApp->browsingLibrary()->showHistory(this);
|
mApp->browsingLibrary()->showHistory(this);
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "bookmarksmodel.h"
|
#include "bookmarksmodel.h"
|
||||||
#include "iconprovider.h"
|
#include "iconprovider.h"
|
||||||
#include "historymodel.h"
|
#include "history.h"
|
||||||
#include "toolbutton.h"
|
#include "toolbutton.h"
|
||||||
#include "databasewriter.h"
|
#include "databasewriter.h"
|
||||||
#include "enhancedmenu.h"
|
#include "enhancedmenu.h"
|
||||||
|
|
|
@ -27,7 +27,7 @@ class QHBoxLayout;
|
||||||
|
|
||||||
class QupZilla;
|
class QupZilla;
|
||||||
class BookmarksModel;
|
class BookmarksModel;
|
||||||
class HistoryModel;
|
class History;
|
||||||
class ToolButton;
|
class ToolButton;
|
||||||
class Menu;
|
class Menu;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ private:
|
||||||
|
|
||||||
QupZilla* p_QupZilla;
|
QupZilla* p_QupZilla;
|
||||||
BookmarksModel* m_bookmarksModel;
|
BookmarksModel* m_bookmarksModel;
|
||||||
HistoryModel* m_historyModel;
|
History* m_historyModel;
|
||||||
Menu* m_menuMostVisited;
|
Menu* m_menuMostVisited;
|
||||||
ToolButton* m_mostVis;
|
ToolButton* m_mostVis;
|
||||||
QHBoxLayout* m_layout;
|
QHBoxLayout* m_layout;
|
||||||
|
|
289
src/lib/history/history.cpp
Normal file
289
src/lib/history/history.cpp
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
/* ============================================================
|
||||||
|
* QupZilla - WebKit based browser
|
||||||
|
* Copyright (C) 2010-2012 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 "history.h"
|
||||||
|
#include "historymodel.h"
|
||||||
|
#include "tabbedwebview.h"
|
||||||
|
#include "qupzilla.h"
|
||||||
|
#include "iconprovider.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
#include <QSqlDatabase>
|
||||||
|
#include <QSqlQuery>
|
||||||
|
|
||||||
|
History::History(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_isSaving(true)
|
||||||
|
, m_model(0)
|
||||||
|
{
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryModel* History::model()
|
||||||
|
{
|
||||||
|
if (!m_model) {
|
||||||
|
m_model = new HistoryModel(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void History::loadSettings()
|
||||||
|
{
|
||||||
|
Settings settings;
|
||||||
|
settings.beginGroup("Web-Browser-Settings");
|
||||||
|
m_isSaving = settings.value("allowHistory", true).toBool();
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddHistoryEntry
|
||||||
|
void History::addHistoryEntry(WebView* view)
|
||||||
|
{
|
||||||
|
if (!m_isSaving || view->loadingError()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUrl &url = view->url();
|
||||||
|
const QString &title = view->title();
|
||||||
|
|
||||||
|
addHistoryEntry(url, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void History::addHistoryEntry(const QUrl &url, QString title)
|
||||||
|
{
|
||||||
|
if (!m_isSaving) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (url.scheme() == "qupzilla" || url.scheme() == "about" || url.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (title == "") {
|
||||||
|
title = tr("No Named Page");
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query;
|
||||||
|
query.prepare("SELECT id, count, date, title FROM history WHERE url=?");
|
||||||
|
query.bindValue(0, url);
|
||||||
|
query.exec();
|
||||||
|
if (!query.next()) {
|
||||||
|
query.prepare("INSERT INTO history (count, date, url, title) VALUES (1,?,?,?)");
|
||||||
|
query.bindValue(0, QDateTime::currentMSecsSinceEpoch());
|
||||||
|
query.bindValue(1, url);
|
||||||
|
query.bindValue(2, title);
|
||||||
|
query.exec();
|
||||||
|
|
||||||
|
int id = query.lastInsertId().toInt();
|
||||||
|
HistoryEntry entry;
|
||||||
|
entry.id = id;
|
||||||
|
entry.count = 1;
|
||||||
|
entry.date = QDateTime::currentDateTime();
|
||||||
|
entry.url = url;
|
||||||
|
entry.urlString = url.toEncoded();
|
||||||
|
entry.title = title;
|
||||||
|
emit historyEntryAdded(entry);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int id = query.value(0).toInt();
|
||||||
|
int count = query.value(1).toInt();
|
||||||
|
QDateTime date = QDateTime::fromMSecsSinceEpoch(query.value(2).toLongLong());
|
||||||
|
QString oldTitle = query.value(3).toString();
|
||||||
|
|
||||||
|
query.prepare("UPDATE history SET count = count + 1, date=?, title=? WHERE url=?");
|
||||||
|
query.bindValue(0, QDateTime::currentMSecsSinceEpoch());
|
||||||
|
query.bindValue(1, title);
|
||||||
|
query.bindValue(2, url);
|
||||||
|
query.exec();
|
||||||
|
|
||||||
|
HistoryEntry before;
|
||||||
|
before.id = id;
|
||||||
|
before.count = count;
|
||||||
|
before.date = date;
|
||||||
|
before.url = url;
|
||||||
|
before.urlString = url.toEncoded();
|
||||||
|
before.title = oldTitle;
|
||||||
|
|
||||||
|
HistoryEntry after = before;
|
||||||
|
after.count = count + 1;
|
||||||
|
after.date = QDateTime::currentDateTime();
|
||||||
|
after.title = title;
|
||||||
|
|
||||||
|
emit historyEntryEdited(before, after);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteHistoryEntry
|
||||||
|
void History::deleteHistoryEntry(int index)
|
||||||
|
{
|
||||||
|
QList<int> list;
|
||||||
|
list.append(index);
|
||||||
|
|
||||||
|
deleteHistoryEntry(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void History::deleteHistoryEntry(const QList<int> &list)
|
||||||
|
{
|
||||||
|
QSqlDatabase db = QSqlDatabase::database();
|
||||||
|
db.transaction();
|
||||||
|
|
||||||
|
foreach(int index, list) {
|
||||||
|
QSqlQuery query;
|
||||||
|
query.prepare("SELECT count, date, url, title FROM history WHERE id=?");
|
||||||
|
query.addBindValue(index);
|
||||||
|
query.exec();
|
||||||
|
query.next();
|
||||||
|
|
||||||
|
HistoryEntry entry;
|
||||||
|
entry.id = index;
|
||||||
|
entry.count = query.value(0).toInt();
|
||||||
|
entry.date = QDateTime::fromMSecsSinceEpoch(query.value(1).toLongLong());
|
||||||
|
entry.url = query.value(2).toUrl();
|
||||||
|
entry.urlString = entry.url.toEncoded();
|
||||||
|
entry.title = query.value(3).toString();
|
||||||
|
|
||||||
|
query.prepare("DELETE FROM history WHERE id=?");
|
||||||
|
query.addBindValue(index);
|
||||||
|
query.exec();
|
||||||
|
|
||||||
|
query.prepare("DELETE FROM icons WHERE url=?");
|
||||||
|
query.addBindValue(entry.url.toEncoded(QUrl::RemoveFragment));
|
||||||
|
query.exec();
|
||||||
|
|
||||||
|
emit historyEntryDeleted(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void History::deleteHistoryEntry(const QString &url, const QString &title)
|
||||||
|
{
|
||||||
|
QSqlQuery query;
|
||||||
|
query.prepare("SELECT id FROM history WHERE url=? AND title=?");
|
||||||
|
query.bindValue(0, url);
|
||||||
|
query.bindValue(1, title);
|
||||||
|
query.exec();
|
||||||
|
if (query.next()) {
|
||||||
|
int id = query.value(0).toInt();
|
||||||
|
deleteHistoryEntry(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<int> History::indexesFromTimeRange(qint64 start, qint64 end)
|
||||||
|
{
|
||||||
|
QList<int> list;
|
||||||
|
|
||||||
|
if (start < 0 || end < 0) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query;
|
||||||
|
query.prepare("SELECT id FROM history WHERE date BETWEEN ? AND ?");
|
||||||
|
query.addBindValue(end);
|
||||||
|
query.addBindValue(start);
|
||||||
|
query.exec();
|
||||||
|
|
||||||
|
while (query.next()) {
|
||||||
|
list.append(query.value(0).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool History::urlIsStored(const QString &url)
|
||||||
|
{
|
||||||
|
QSqlQuery query;
|
||||||
|
query.prepare("SELECT id FROM history WHERE url=?");
|
||||||
|
query.bindValue(0, url);
|
||||||
|
query.exec();
|
||||||
|
return query.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<HistoryEntry> History::mostVisited(int count)
|
||||||
|
{
|
||||||
|
QList<HistoryEntry> list;
|
||||||
|
QSqlQuery query;
|
||||||
|
query.exec(QString("SELECT count, date, id, title, url FROM history ORDER BY count DESC LIMIT %1").arg(count));
|
||||||
|
while (query.next()) {
|
||||||
|
HistoryEntry entry;
|
||||||
|
entry.count = query.value(0).toInt();
|
||||||
|
entry.date = query.value(1).toDateTime();
|
||||||
|
entry.id = query.value(2).toInt();
|
||||||
|
entry.title = query.value(3).toString();
|
||||||
|
entry.url = query.value(4).toUrl();
|
||||||
|
list.append(entry);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool History::optimizeHistory()
|
||||||
|
{
|
||||||
|
QSqlQuery query;
|
||||||
|
return query.exec("VACUUM");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool History::clearHistory()
|
||||||
|
{
|
||||||
|
QSqlQuery query;
|
||||||
|
if (query.exec("DELETE FROM history")) {
|
||||||
|
emit resetHistory();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void History::setSaving(bool state)
|
||||||
|
{
|
||||||
|
m_isSaving = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool History::isSaving()
|
||||||
|
{
|
||||||
|
return m_isSaving;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString History::titleCaseLocalizedMonth(int month)
|
||||||
|
{
|
||||||
|
switch (month) {
|
||||||
|
case 1:
|
||||||
|
return tr("January");
|
||||||
|
case 2:
|
||||||
|
return tr("February");
|
||||||
|
case 3:
|
||||||
|
return tr("March");
|
||||||
|
case 4:
|
||||||
|
return tr("April");
|
||||||
|
case 5:
|
||||||
|
return tr("May");
|
||||||
|
case 6:
|
||||||
|
return tr("June");
|
||||||
|
case 7:
|
||||||
|
return tr("July");
|
||||||
|
case 8:
|
||||||
|
return tr("August");
|
||||||
|
case 9:
|
||||||
|
return tr("September");
|
||||||
|
case 10:
|
||||||
|
return tr("October");
|
||||||
|
case 11:
|
||||||
|
return tr("November");
|
||||||
|
case 12:
|
||||||
|
return tr("December");
|
||||||
|
default:
|
||||||
|
qWarning("Month number out of range!");
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
89
src/lib/history/history.h
Normal file
89
src/lib/history/history.h
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/* ============================================================
|
||||||
|
* QupZilla - WebKit based browser
|
||||||
|
* Copyright (C) 2010-2012 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 HISTORY_H
|
||||||
|
#define HISTORY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "qz_namespace.h"
|
||||||
|
|
||||||
|
class QIcon;
|
||||||
|
|
||||||
|
class QupZilla;
|
||||||
|
class WebView;
|
||||||
|
class HistoryModel;
|
||||||
|
|
||||||
|
class QT_QUPZILLA_EXPORT History : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
History(QObject* parent);
|
||||||
|
|
||||||
|
struct HistoryEntry {
|
||||||
|
int id;
|
||||||
|
int count;
|
||||||
|
QDateTime date;
|
||||||
|
QUrl url;
|
||||||
|
QString urlString;
|
||||||
|
QString title;
|
||||||
|
};
|
||||||
|
|
||||||
|
static QString titleCaseLocalizedMonth(int month);
|
||||||
|
|
||||||
|
HistoryModel* model();
|
||||||
|
|
||||||
|
void addHistoryEntry(WebView* view);
|
||||||
|
void addHistoryEntry(const QUrl &url, QString title);
|
||||||
|
|
||||||
|
void deleteHistoryEntry(int index);
|
||||||
|
void deleteHistoryEntry(const QList<int> &list);
|
||||||
|
void deleteHistoryEntry(const QString &url, const QString &title);
|
||||||
|
|
||||||
|
QList<int> indexesFromTimeRange(qint64 start, qint64 end);
|
||||||
|
|
||||||
|
bool urlIsStored(const QString &url);
|
||||||
|
|
||||||
|
QList<HistoryEntry> mostVisited(int count);
|
||||||
|
|
||||||
|
bool clearHistory();
|
||||||
|
bool optimizeHistory();
|
||||||
|
bool isSaving();
|
||||||
|
void setSaving(bool state);
|
||||||
|
|
||||||
|
void loadSettings();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void historyEntryAdded(const HistoryEntry &entry);
|
||||||
|
void historyEntryDeleted(const HistoryEntry &entry);
|
||||||
|
void historyEntryEdited(const HistoryEntry &before, const HistoryEntry &after);
|
||||||
|
|
||||||
|
void resetHistory();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_isSaving;
|
||||||
|
|
||||||
|
QupZilla* p_QupZilla;
|
||||||
|
HistoryModel* m_model;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef History::HistoryEntry HistoryEntry;
|
||||||
|
|
||||||
|
#endif // HISTORY_H
|
180
src/lib/history/historyitem.cpp
Normal file
180
src/lib/history/historyitem.cpp
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
/* ============================================================
|
||||||
|
* QupZilla - WebKit based browser
|
||||||
|
* Copyright (C) 2010-2012 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 "historyitem.h"
|
||||||
|
|
||||||
|
HistoryItem::HistoryItem(HistoryItem* parent)
|
||||||
|
: canFetchMore(false)
|
||||||
|
, m_parent(parent)
|
||||||
|
, m_iconLoaded(false)
|
||||||
|
, m_startTimestamp(0)
|
||||||
|
, m_endTimestamp(0)
|
||||||
|
{
|
||||||
|
if (m_parent) {
|
||||||
|
m_parent->appendChild(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::changeParent(HistoryItem* parent)
|
||||||
|
{
|
||||||
|
if (m_parent) {
|
||||||
|
m_parent->removeChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_parent = parent;
|
||||||
|
|
||||||
|
if (m_parent) {
|
||||||
|
m_parent->prependChild(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem* HistoryItem::parent() const
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::prependChild(HistoryItem* child)
|
||||||
|
{
|
||||||
|
if (m_children.contains(child)) {
|
||||||
|
m_children.removeAll(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
child->m_parent = this;
|
||||||
|
m_children.prepend(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::appendChild(HistoryItem* child)
|
||||||
|
{
|
||||||
|
if (m_children.contains(child)) {
|
||||||
|
m_children.removeAll(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
child->m_parent = this;
|
||||||
|
m_children.append(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::insertChild(int row, HistoryItem* child)
|
||||||
|
{
|
||||||
|
if (m_children.contains(child)) {
|
||||||
|
m_children.removeAll(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_children.count() >= row) {
|
||||||
|
child->m_parent = this;
|
||||||
|
m_children.insert(row, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::removeChild(int row)
|
||||||
|
{
|
||||||
|
if (m_children.count() > row) {
|
||||||
|
removeChild(m_children.at(row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::removeChild(HistoryItem* child)
|
||||||
|
{
|
||||||
|
int index = m_children.indexOf(child);
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
m_children.removeOne(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem* HistoryItem::child(int row) const
|
||||||
|
{
|
||||||
|
if (m_children.count() > row) {
|
||||||
|
return m_children.at(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HistoryItem::childCount() const
|
||||||
|
{
|
||||||
|
return m_children.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int HistoryItem::row()
|
||||||
|
{
|
||||||
|
return m_parent ? m_parent->indexOfChild(this) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HistoryItem::indexOfChild(HistoryItem* child)
|
||||||
|
{
|
||||||
|
return m_children.indexOf(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HistoryItem::isTopLevel() const
|
||||||
|
{
|
||||||
|
return (m_startTimestamp != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HistoryItem::iconLoaded() const
|
||||||
|
{
|
||||||
|
return m_iconLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon HistoryItem::icon() const
|
||||||
|
{
|
||||||
|
return m_icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::setIcon(const QIcon &icon)
|
||||||
|
{
|
||||||
|
m_icon = icon;
|
||||||
|
m_iconLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::refreshIcon()
|
||||||
|
{
|
||||||
|
m_iconLoaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::setStartTimestamp(qint64 start)
|
||||||
|
{
|
||||||
|
m_startTimestamp = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 HistoryItem::startTimestamp() const
|
||||||
|
{
|
||||||
|
if (m_startTimestamp == -1) {
|
||||||
|
return QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_startTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryItem::setEndTimestamp(qint64 end)
|
||||||
|
{
|
||||||
|
m_endTimestamp = end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 HistoryItem::endTimestamp() const
|
||||||
|
{
|
||||||
|
return m_endTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem::~HistoryItem()
|
||||||
|
{
|
||||||
|
if (m_parent) {
|
||||||
|
m_parent->removeChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
qDeleteAll(m_children);
|
||||||
|
}
|
76
src/lib/history/historyitem.h
Normal file
76
src/lib/history/historyitem.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/* ============================================================
|
||||||
|
* QupZilla - WebKit based browser
|
||||||
|
* Copyright (C) 2010-2012 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 HISTORYITEM_H
|
||||||
|
#define HISTORYITEM_H
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
#include "qz_namespace.h"
|
||||||
|
#include "history.h"
|
||||||
|
|
||||||
|
class QT_QUPZILLA_EXPORT HistoryItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit HistoryItem(HistoryItem* parent = 0);
|
||||||
|
~HistoryItem();
|
||||||
|
|
||||||
|
void changeParent(HistoryItem* parent);
|
||||||
|
HistoryItem* parent() const;
|
||||||
|
|
||||||
|
HistoryItem* child(int row) const;
|
||||||
|
int childCount() const;
|
||||||
|
|
||||||
|
void prependChild(HistoryItem* child);
|
||||||
|
void appendChild(HistoryItem* child);
|
||||||
|
void insertChild(int row, HistoryItem* child);
|
||||||
|
|
||||||
|
void removeChild(int row);
|
||||||
|
void removeChild(HistoryItem* child);
|
||||||
|
|
||||||
|
int row();
|
||||||
|
int indexOfChild(HistoryItem* child);
|
||||||
|
|
||||||
|
bool isTopLevel() const;
|
||||||
|
bool iconLoaded() const;
|
||||||
|
|
||||||
|
QIcon icon() const;
|
||||||
|
void setIcon(const QIcon &icon);
|
||||||
|
void refreshIcon();
|
||||||
|
|
||||||
|
void setStartTimestamp(qint64 start);
|
||||||
|
qint64 startTimestamp() const;
|
||||||
|
|
||||||
|
void setEndTimestamp(qint64 end);
|
||||||
|
qint64 endTimestamp() const;
|
||||||
|
|
||||||
|
HistoryEntry historyEntry;
|
||||||
|
QString title;
|
||||||
|
bool canFetchMore;
|
||||||
|
|
||||||
|
private:
|
||||||
|
HistoryItem* m_parent;
|
||||||
|
QList<HistoryItem*> m_children;
|
||||||
|
|
||||||
|
QIcon m_icon;
|
||||||
|
bool m_iconLoaded;
|
||||||
|
|
||||||
|
qint64 m_startTimestamp;
|
||||||
|
qint64 m_endTimestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HISTORYITEM_H
|
|
@ -19,45 +19,28 @@
|
||||||
#include "ui_historymanager.h"
|
#include "ui_historymanager.h"
|
||||||
#include "qupzilla.h"
|
#include "qupzilla.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "historymodel.h"
|
#include "history.h"
|
||||||
#include "iconprovider.h"
|
|
||||||
#include "browsinglibrary.h"
|
#include "browsinglibrary.h"
|
||||||
#include "globalfunctions.h"
|
|
||||||
#include "tabwidget.h"
|
#include "tabwidget.h"
|
||||||
|
#include "tabbedwebview.h"
|
||||||
|
#include "historymodel.h"
|
||||||
|
#include "headerview.h"
|
||||||
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QClipboard>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QSqlQuery>
|
|
||||||
|
|
||||||
HistoryManager::HistoryManager(QupZilla* mainClass, QWidget* parent)
|
HistoryManager::HistoryManager(QupZilla* mainClass, QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, ui(new Ui::HistoryManager)
|
, ui(new Ui::HistoryManager)
|
||||||
, p_QupZilla(mainClass)
|
, p_QupZilla(mainClass)
|
||||||
, m_historyModel(mApp->history())
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->historyTree->setDefaultItemShowMode(TreeWidget::ItemsCollapsed);
|
|
||||||
ui->historyTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
ui->deleteB->setShortcut(QKeySequence("Del"));
|
|
||||||
|
|
||||||
connect(ui->historyTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem*)));
|
connect(ui->historyTree, SIGNAL(openLink(QUrl, HistoryView::OpenBehavior)), this, SLOT(openLink(QUrl, HistoryView::OpenBehavior)));
|
||||||
connect(ui->historyTree, SIGNAL(itemMiddleButtonClicked(QTreeWidgetItem*)), this, SLOT(itemDoubleClicked(QTreeWidgetItem*)));
|
|
||||||
|
|
||||||
connect(ui->deleteB, SIGNAL(clicked()), this, SLOT(deleteItem()));
|
connect(ui->deleteB, SIGNAL(clicked()), ui->historyTree, SLOT(removeItems()));
|
||||||
connect(ui->clearAll, SIGNAL(clicked()), this, SLOT(clearHistory()));
|
connect(ui->clearAll, SIGNAL(clicked()), this, SLOT(clearHistory()));
|
||||||
connect(ui->historyTree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenuRequested(const QPoint &)));
|
|
||||||
|
|
||||||
connect(m_historyModel, SIGNAL(historyEntryAdded(HistoryEntry)), this, SLOT(historyEntryAdded(HistoryEntry)));
|
|
||||||
connect(m_historyModel, SIGNAL(historyEntryDeleted(HistoryEntry)), this, SLOT(historyEntryDeleted(HistoryEntry)));
|
|
||||||
connect(m_historyModel, SIGNAL(historyEntryEdited(HistoryEntry, HistoryEntry)), this, SLOT(historyEntryEdited(HistoryEntry, HistoryEntry)));
|
|
||||||
connect(m_historyModel, SIGNAL(historyClear()), ui->historyTree, SLOT(clear()));
|
|
||||||
|
|
||||||
connect(ui->optimizeDb, SIGNAL(clicked(QPoint)), this, SLOT(optimizeDb()));
|
connect(ui->optimizeDb, SIGNAL(clicked(QPoint)), this, SLOT(optimizeDb()));
|
||||||
|
|
||||||
//QTimer::singleShot(0, this, SLOT(refreshTable()));
|
|
||||||
|
|
||||||
ui->historyTree->setFocus();
|
ui->historyTree->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,165 +59,14 @@ void HistoryManager::setMainWindow(QupZilla* window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryManager::itemDoubleClicked(QTreeWidgetItem* item)
|
void HistoryManager::restoreState(const QByteArray &state)
|
||||||
{
|
{
|
||||||
if (!item || item->text(1).isEmpty()) {
|
ui->historyTree->header()->restoreState(state);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl url = QUrl::fromEncoded(item->text(1).toUtf8());
|
|
||||||
getQupZilla()->tabWidget()->addView(url, item->text(0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryManager::loadInNewTab()
|
QByteArray HistoryManager::saveState()
|
||||||
{
|
{
|
||||||
if (QAction* action = qobject_cast<QAction*>(sender())) {
|
return ui->historyTree->header()->saveState();
|
||||||
getQupZilla()->tabWidget()->addView(action->data().toUrl(), Qz::NT_NotSelectedTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryManager::contextMenuRequested(const QPoint &position)
|
|
||||||
{
|
|
||||||
if (!ui->historyTree->itemAt(position)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QUrl link = QUrl::fromEncoded(ui->historyTree->itemAt(position)->text(1).toUtf8());
|
|
||||||
if (link.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMenu menu;
|
|
||||||
menu.addAction(tr("Open link in current tab"), getQupZilla(), SLOT(loadActionUrl()))->setData(link);
|
|
||||||
menu.addAction(tr("Open link in new tab"), this, SLOT(loadInNewTab()))->setData(link);
|
|
||||||
menu.addSeparator();
|
|
||||||
menu.addAction(tr("Copy address"), this, SLOT(copyUrl()))->setData(link);
|
|
||||||
|
|
||||||
//Prevent choosing first option with double rightclick
|
|
||||||
QPoint pos = ui->historyTree->viewport()->mapToGlobal(position);
|
|
||||||
QPoint p(pos.x(), pos.y() + 1);
|
|
||||||
menu.exec(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryManager::copyUrl()
|
|
||||||
{
|
|
||||||
if (QAction* action = qobject_cast<QAction*>(sender())) {
|
|
||||||
QApplication::clipboard()->setText(action->data().toUrl().toEncoded());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryManager::deleteItem()
|
|
||||||
{
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
QList<int> list;
|
|
||||||
|
|
||||||
foreach(QTreeWidgetItem * item, ui->historyTree->selectedItems()) {
|
|
||||||
if (!item) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!item->parent()) {
|
|
||||||
QList<QTreeWidgetItem*> items;
|
|
||||||
|
|
||||||
for (int i = 0; i < item->childCount(); i++) {
|
|
||||||
QTreeWidgetItem* children = item->child(i);
|
|
||||||
if (children->isHidden()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int id = children->data(0, Qt::UserRole + 10).toInt();
|
|
||||||
|
|
||||||
list.append(id);
|
|
||||||
m_ignoredIds.append(id);
|
|
||||||
items.append(children);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item->childCount() == 0) {
|
|
||||||
items.append(item);
|
|
||||||
}
|
|
||||||
ui->historyTree->deleteItems(items);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int id = item->data(0, Qt::UserRole + 10).toInt();
|
|
||||||
|
|
||||||
list.append(id);
|
|
||||||
m_ignoredIds.append(id);
|
|
||||||
|
|
||||||
ui->historyTree->deleteItem(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_historyModel->deleteHistoryEntry(list);
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryManager::historyEntryAdded(const HistoryEntry &entry)
|
|
||||||
{
|
|
||||||
QDate todayDate = QDate::currentDate();
|
|
||||||
QDate startOfWeekDate = todayDate.addDays(1 - todayDate.dayOfWeek());
|
|
||||||
|
|
||||||
QDate date = entry.date.date();
|
|
||||||
QString localDate;
|
|
||||||
|
|
||||||
if (date == todayDate) {
|
|
||||||
localDate = tr("Today");
|
|
||||||
}
|
|
||||||
else if (date >= startOfWeekDate) {
|
|
||||||
localDate = tr("This Week");
|
|
||||||
}
|
|
||||||
else if (date.month() == todayDate.month()) {
|
|
||||||
localDate = tr("This Month");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
localDate = QString("%1 %2").arg(HistoryModel::titleCaseLocalizedMonth(date.month()), QString::number(date.year()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
|
||||||
QTreeWidgetItem* parentItem;
|
|
||||||
QList<QTreeWidgetItem*> findParent = ui->historyTree->findItems(localDate, 0);
|
|
||||||
if (findParent.count() == 1) {
|
|
||||||
parentItem = findParent.at(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parentItem = new QTreeWidgetItem();
|
|
||||||
parentItem->setText(0, localDate);
|
|
||||||
parentItem->setIcon(0, QIcon(":/icons/menu/history_entry.png"));
|
|
||||||
ui->historyTree->insertTopLevelItem(0, parentItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
item->setText(0, entry.title);
|
|
||||||
item->setText(1, entry.url.toEncoded());
|
|
||||||
item->setToolTip(0, entry.title);
|
|
||||||
item->setToolTip(1, entry.url.toEncoded());
|
|
||||||
|
|
||||||
item->setData(0, Qt::UserRole + 10, entry.id);
|
|
||||||
item->setIcon(0, _iconForUrl(entry.url));
|
|
||||||
ui->historyTree->prependToParentItem(parentItem, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryManager::historyEntryDeleted(const HistoryEntry &entry)
|
|
||||||
{
|
|
||||||
if (m_ignoredIds.contains(entry.id)) {
|
|
||||||
m_ignoredIds.removeOne(entry.id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QTreeWidgetItem*> list = ui->historyTree->allItems();
|
|
||||||
foreach(QTreeWidgetItem * item, list) {
|
|
||||||
if (!item) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (item->data(0, Qt::UserRole + 10).toInt() != entry.id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ui->historyTree->deleteItem(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryManager::historyEntryEdited(const HistoryEntry &before, const HistoryEntry &after)
|
|
||||||
{
|
|
||||||
historyEntryDeleted(before);
|
|
||||||
historyEntryAdded(after);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryManager::clearHistory()
|
void HistoryManager::clearHistory()
|
||||||
|
@ -245,89 +77,23 @@ void HistoryManager::clearHistory()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_historyModel->clearHistory();
|
mApp->history()->clearHistory();
|
||||||
m_historyModel->optimizeHistory();
|
mApp->history()->optimizeHistory();
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryManager::refreshTable()
|
|
||||||
{
|
|
||||||
QTimer::singleShot(0, this, SLOT(slotRefreshTable()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryManager::slotRefreshTable()
|
|
||||||
{
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
ui->historyTree->clear();
|
|
||||||
|
|
||||||
QDate todayDate = QDate::currentDate();
|
|
||||||
QDate startOfWeekDate = todayDate.addDays(1 - todayDate.dayOfWeek());
|
|
||||||
QSqlQuery query;
|
|
||||||
query.exec("SELECT title, url, id, date FROM history ORDER BY date DESC");
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
QWeakPointer<HistoryManager> guard = this;
|
|
||||||
QHash<QString, QTreeWidgetItem*> hash;
|
|
||||||
while (query.next()) {
|
|
||||||
const QString &title = query.value(0).toString();
|
|
||||||
const QUrl &url = query.value(1).toUrl();
|
|
||||||
int id = query.value(2).toInt();
|
|
||||||
const QDate &date = QDateTime::fromMSecsSinceEpoch(query.value(3).toLongLong()).date();
|
|
||||||
QString localDate;
|
|
||||||
|
|
||||||
if (date == todayDate) {
|
|
||||||
localDate = tr("Today");
|
|
||||||
}
|
|
||||||
else if (date >= startOfWeekDate) {
|
|
||||||
localDate = tr("This Week");
|
|
||||||
}
|
|
||||||
else if (date.month() == todayDate.month()) {
|
|
||||||
localDate = tr("This Month");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
localDate = QString("%1 %2").arg(HistoryModel::titleCaseLocalizedMonth(date.month()), QString::number(date.year()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeWidgetItem* item;
|
|
||||||
QTreeWidgetItem* findParent = hash[localDate];
|
|
||||||
if (findParent) {
|
|
||||||
item = new QTreeWidgetItem(findParent);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QTreeWidgetItem* newParent = new QTreeWidgetItem(ui->historyTree);
|
|
||||||
newParent->setText(0, localDate);
|
|
||||||
newParent->setIcon(0, QIcon(":/icons/menu/history_entry.png"));
|
|
||||||
ui->historyTree->addTopLevelItem(newParent);
|
|
||||||
hash[localDate] = newParent;
|
|
||||||
|
|
||||||
item = new QTreeWidgetItem(newParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
item->setText(0, title);
|
|
||||||
item->setText(1, url.toEncoded());
|
|
||||||
item->setToolTip(0, title);
|
|
||||||
item->setToolTip(1, url.toEncoded());
|
|
||||||
item->setData(0, Qt::UserRole + 10, id);
|
|
||||||
item->setIcon(0, _iconForUrl(url));
|
|
||||||
|
|
||||||
ui->historyTree->addTopLevelItem(item);
|
|
||||||
|
|
||||||
++counter;
|
|
||||||
if (counter > 200) {
|
|
||||||
QApplication::processEvents();
|
|
||||||
counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!guard) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryManager::search(const QString &searchText)
|
void HistoryManager::search(const QString &searchText)
|
||||||
{
|
{
|
||||||
ui->historyTree->filterString(searchText);
|
ui->historyTree->filterModel()->setFilterFixedString(searchText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryManager::openLink(const QUrl &url, HistoryView::OpenBehavior openIn)
|
||||||
|
{
|
||||||
|
if (openIn == HistoryView::OpenInNewTab) {
|
||||||
|
getQupZilla()->tabWidget()->addView(url, Qz::NT_NotSelectedTab);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getQupZilla()->weView()->load(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryManager::optimizeDb()
|
void HistoryManager::optimizeDb()
|
||||||
|
@ -339,7 +105,6 @@ void HistoryManager::optimizeDb()
|
||||||
b->optimizeDatabase();
|
b->optimizeDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HistoryManager::~HistoryManager()
|
HistoryManager::~HistoryManager()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <QWeakPointer>
|
#include <QWeakPointer>
|
||||||
|
|
||||||
#include "qz_namespace.h"
|
#include "qz_namespace.h"
|
||||||
#include "historymodel.h"
|
#include "historyview.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
|
@ -42,33 +42,23 @@ public:
|
||||||
~HistoryManager();
|
~HistoryManager();
|
||||||
|
|
||||||
void setMainWindow(QupZilla* window);
|
void setMainWindow(QupZilla* window);
|
||||||
void refreshTable();
|
|
||||||
|
void restoreState(const QByteArray &state);
|
||||||
|
QByteArray saveState();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void search(const QString &searchText);
|
void search(const QString &searchText);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void openLink(const QUrl &url, HistoryView::OpenBehavior openIn);
|
||||||
void optimizeDb();
|
void optimizeDb();
|
||||||
void itemDoubleClicked(QTreeWidgetItem* item);
|
|
||||||
void slotRefreshTable();
|
|
||||||
|
|
||||||
void deleteItem();
|
|
||||||
void clearHistory();
|
void clearHistory();
|
||||||
void contextMenuRequested(const QPoint &position);
|
|
||||||
void loadInNewTab();
|
|
||||||
void copyUrl();
|
|
||||||
|
|
||||||
void historyEntryAdded(const HistoryEntry &entry);
|
|
||||||
void historyEntryDeleted(const HistoryEntry &entry);
|
|
||||||
void historyEntryEdited(const HistoryEntry &before, const HistoryEntry &after);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QupZilla* getQupZilla();
|
QupZilla* getQupZilla();
|
||||||
|
|
||||||
Ui::HistoryManager* ui;
|
Ui::HistoryManager* ui;
|
||||||
QWeakPointer<QupZilla> p_QupZilla;
|
QWeakPointer<QupZilla> p_QupZilla;
|
||||||
HistoryModel* m_historyModel;
|
|
||||||
|
|
||||||
QList<int> m_ignoredIds;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HISTORYMANAGER_H
|
#endif // HISTORYMANAGER_H
|
||||||
|
|
|
@ -14,29 +14,6 @@
|
||||||
<string>History</string>
|
<string>History</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0" colspan="4">
|
|
||||||
<widget class="TreeWidget" name="historyTree">
|
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::CustomContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<property name="alternatingRowColors">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<attribute name="headerDefaultSectionSize">
|
|
||||||
<number>330</number>
|
|
||||||
</attribute>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Title</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Url</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QPushButton" name="deleteB">
|
<widget class="QPushButton" name="deleteB">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -77,19 +54,26 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0" colspan="4">
|
||||||
|
<widget class="HistoryView" name="historyTree">
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
|
||||||
<class>TreeWidget</class>
|
|
||||||
<extends>QTreeWidget</extends>
|
|
||||||
<header>treewidget.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>ClickableLabel</class>
|
<class>ClickableLabel</class>
|
||||||
<extends>QLabel</extends>
|
<extends>QLabel</extends>
|
||||||
<header>clickablelabel.h</header>
|
<header>clickablelabel.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>HistoryView</class>
|
||||||
|
<extends>QTreeView</extends>
|
||||||
|
<header>historyview.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
@ -16,231 +16,521 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
#include "historymodel.h"
|
#include "historymodel.h"
|
||||||
#include "tabbedwebview.h"
|
#include "historyitem.h"
|
||||||
#include "qupzilla.h"
|
|
||||||
#include "iconprovider.h"
|
#include "iconprovider.h"
|
||||||
#include "settings.h"
|
|
||||||
|
|
||||||
#include <QSqlDatabase>
|
#include <QApplication>
|
||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
HistoryModel::HistoryModel(QupZilla* mainClass)
|
QString dateTimeToString(const QDateTime &dateTime)
|
||||||
: QObject()
|
|
||||||
, m_isSaving(true)
|
|
||||||
, p_QupZilla(mainClass)
|
|
||||||
{
|
{
|
||||||
loadSettings();
|
const QDateTime ¤t = QDateTime::currentDateTime();
|
||||||
}
|
if (current.date() == dateTime.date()) {
|
||||||
|
return dateTime.time().toString("h:mm");
|
||||||
void HistoryModel::loadSettings()
|
|
||||||
{
|
|
||||||
Settings settings;
|
|
||||||
settings.beginGroup("Web-Browser-Settings");
|
|
||||||
m_isSaving = settings.value("allowHistory", true).toBool();
|
|
||||||
settings.endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddHistoryEntry
|
|
||||||
void HistoryModel::addHistoryEntry(WebView* view)
|
|
||||||
{
|
|
||||||
if (!m_isSaving || view->loadingError()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QUrl &url = view->url();
|
return dateTime.toString("d.M.yyyy h:mm");
|
||||||
const QString &title = view->title();
|
|
||||||
|
|
||||||
addHistoryEntry(url, title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryModel::addHistoryEntry(const QUrl &url, QString title)
|
HistoryModel::HistoryModel(History* history)
|
||||||
|
: QAbstractItemModel(history)
|
||||||
|
, m_rootItem(new HistoryItem(0))
|
||||||
|
, m_todayItem(0)
|
||||||
|
, m_history(history)
|
||||||
{
|
{
|
||||||
if (!m_isSaving) {
|
init();
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (url.scheme() == "qupzilla" || url.scheme() == "about" || url.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (title == "") {
|
|
||||||
title = tr("No Named Page");
|
|
||||||
}
|
|
||||||
|
|
||||||
QSqlQuery query;
|
connect(m_history, SIGNAL(resetHistory()), this, SLOT(resetHistory()));
|
||||||
query.prepare("SELECT id FROM history WHERE url=?");
|
connect(m_history, SIGNAL(historyEntryAdded(const HistoryEntry &)), this, SLOT(historyEntryAdded(const HistoryEntry &)));
|
||||||
query.bindValue(0, url);
|
connect(m_history, SIGNAL(historyEntryDeleted(const HistoryEntry &)), this, SLOT(historyEntryDeleted(const HistoryEntry &)));
|
||||||
query.exec();
|
connect(m_history, SIGNAL(historyEntryEdited(const HistoryEntry &, const HistoryEntry &)), this, SLOT(historyEntryEdited(const HistoryEntry &, const HistoryEntry &)));
|
||||||
if (!query.next()) {
|
|
||||||
query.prepare("INSERT INTO history (count, date, url, title) VALUES (1,?,?,?)");
|
|
||||||
query.bindValue(0, QDateTime::currentMSecsSinceEpoch());
|
|
||||||
query.bindValue(1, url);
|
|
||||||
query.bindValue(2, title);
|
|
||||||
query.exec();
|
|
||||||
|
|
||||||
int id = query.lastInsertId().toInt();
|
|
||||||
HistoryEntry entry;
|
|
||||||
entry.id = id;
|
|
||||||
entry.count = 1;
|
|
||||||
entry.date = QDateTime::currentDateTime();
|
|
||||||
entry.url = url;
|
|
||||||
entry.title = title;
|
|
||||||
emit historyEntryAdded(entry);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int id = query.value(0).toInt();
|
|
||||||
query.prepare("UPDATE history SET count = count + 1, date=?, title=? WHERE url=?");
|
|
||||||
query.bindValue(0, QDateTime::currentMSecsSinceEpoch());
|
|
||||||
query.bindValue(1, title);
|
|
||||||
query.bindValue(2, url);
|
|
||||||
query.exec();
|
|
||||||
|
|
||||||
HistoryEntry before;
|
|
||||||
before.id = id;
|
|
||||||
|
|
||||||
HistoryEntry after;
|
|
||||||
after.id = id;
|
|
||||||
after.date = QDateTime::currentDateTime();
|
|
||||||
after.url = url;
|
|
||||||
after.title = title;
|
|
||||||
emit historyEntryEdited(before, after);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteHistoryEntry
|
QVariant HistoryModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
void HistoryModel::deleteHistoryEntry(int index)
|
|
||||||
{
|
{
|
||||||
QList<int> list;
|
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||||
list.append(index);
|
switch (section) {
|
||||||
|
case 0:
|
||||||
deleteHistoryEntry(list);
|
return tr("Title");
|
||||||
}
|
case 1:
|
||||||
|
return tr("Address");
|
||||||
void HistoryModel::deleteHistoryEntry(const QList<int> &list)
|
case 2:
|
||||||
{
|
return tr("Visit Date");
|
||||||
QSqlDatabase db = QSqlDatabase::database();
|
case 3:
|
||||||
db.transaction();
|
return tr("Visit Count");
|
||||||
|
}
|
||||||
foreach(int index, list) {
|
|
||||||
QSqlQuery query;
|
|
||||||
query.prepare("SELECT id, count, date, url, title FROM history WHERE id=?");
|
|
||||||
query.addBindValue(index);
|
|
||||||
query.exec();
|
|
||||||
|
|
||||||
query.next();
|
|
||||||
HistoryEntry entry;
|
|
||||||
entry.id = query.value(0).toInt();
|
|
||||||
entry.count = query.value(1).toInt();
|
|
||||||
entry.date = QDateTime::fromMSecsSinceEpoch(query.value(2).toLongLong());
|
|
||||||
entry.url = query.value(3).toUrl();
|
|
||||||
entry.title = query.value(4).toString();
|
|
||||||
|
|
||||||
query.prepare("DELETE FROM history WHERE id=?");
|
|
||||||
query.addBindValue(index);
|
|
||||||
query.exec();
|
|
||||||
|
|
||||||
query.prepare("DELETE FROM icons WHERE url=?");
|
|
||||||
query.addBindValue(entry.url.toEncoded(QUrl::RemoveFragment));
|
|
||||||
query.exec();
|
|
||||||
|
|
||||||
emit historyEntryDeleted(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db.commit();
|
return QAbstractItemModel::headerData(section, orientation, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryModel::deleteHistoryEntry(const QString &url, const QString &title)
|
QVariant HistoryModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
QSqlQuery query;
|
HistoryItem* item = itemFromIndex(index);
|
||||||
query.prepare("SELECT id FROM history WHERE url=? AND title=?");
|
|
||||||
query.bindValue(0, url);
|
if (index.row() < 0 || !item) {
|
||||||
query.bindValue(1, title);
|
return QVariant();
|
||||||
query.exec();
|
|
||||||
if (query.next()) {
|
|
||||||
int id = query.value(0).toInt();
|
|
||||||
deleteHistoryEntry(id);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool HistoryModel::urlIsStored(const QString &url)
|
if (item->isTopLevel()) {
|
||||||
{
|
switch (role) {
|
||||||
QSqlQuery query;
|
case IsTopLevelRole:
|
||||||
query.prepare("SELECT id FROM history WHERE url=?");
|
return true;
|
||||||
query.bindValue(0, url);
|
case TimestampStartRole:
|
||||||
query.exec();
|
return item->startTimestamp();
|
||||||
return query.next();
|
case TimestampEndRole:
|
||||||
}
|
return item->endTimestamp();
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
return index.column() == 0 ? item->title : QVariant();
|
||||||
|
case Qt::DecorationRole:
|
||||||
|
return index.column() == 0 ? QIcon(":/icons/menu/history_entry.png") : QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
QList<HistoryEntry> HistoryModel::mostVisited(int count)
|
return QVariant();
|
||||||
{
|
|
||||||
QList<HistoryEntry> list;
|
|
||||||
QSqlQuery query;
|
|
||||||
query.exec(QString("SELECT count, date, id, title, url FROM history ORDER BY count DESC LIMIT %1").arg(count));
|
|
||||||
while (query.next()) {
|
|
||||||
HistoryEntry entry;
|
|
||||||
entry.count = query.value(0).toInt();
|
|
||||||
entry.date = query.value(1).toDateTime();
|
|
||||||
entry.id = query.value(2).toInt();
|
|
||||||
entry.title = query.value(3).toString();
|
|
||||||
entry.url = query.value(4).toUrl();
|
|
||||||
list.append(entry);
|
|
||||||
}
|
}
|
||||||
return list;
|
|
||||||
|
const HistoryEntry &entry = item->historyEntry;
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case IdRole:
|
||||||
|
return entry.id;
|
||||||
|
case TitleRole:
|
||||||
|
return entry.title;
|
||||||
|
case UrlRole:
|
||||||
|
return entry.url;
|
||||||
|
case UrlStringRole:
|
||||||
|
return entry.urlString;
|
||||||
|
case IconRole:
|
||||||
|
return item->icon();
|
||||||
|
case IconLoadedRole:
|
||||||
|
return item->iconLoaded();
|
||||||
|
case IsTopLevelRole:
|
||||||
|
return false;
|
||||||
|
case TimestampStartRole:
|
||||||
|
return -1;
|
||||||
|
case TimestampEndRole:
|
||||||
|
return -1;
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
if (index.column() == 0) {
|
||||||
|
return QString("%1\n%2").arg(entry.title, entry.urlString);
|
||||||
|
}
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0:
|
||||||
|
return entry.title;
|
||||||
|
case 1:
|
||||||
|
return entry.urlString;
|
||||||
|
case 2:
|
||||||
|
return dateTimeToString(entry.date);
|
||||||
|
case 3:
|
||||||
|
return entry.count;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Qt::DecorationRole:
|
||||||
|
if (index.column() == 0) {
|
||||||
|
return item->icon().isNull() ? qIconProvider->emptyWebIcon() : item->icon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryModel::optimizeHistory()
|
bool HistoryModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
{
|
{
|
||||||
QSqlQuery query;
|
HistoryItem* item = itemFromIndex(index);
|
||||||
return query.exec("VACUUM");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HistoryModel::clearHistory()
|
if (index.row() < 0 || !item || item->isTopLevel()) {
|
||||||
{
|
return false;
|
||||||
QSqlQuery query;
|
}
|
||||||
if (query.exec("DELETE FROM history")) {
|
|
||||||
emit historyClear();
|
if (role == IconRole) {
|
||||||
|
item->setIcon(value.value<QIcon>());
|
||||||
|
emit dataChanged(index, index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryModel::setSaving(bool state)
|
QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
m_isSaving = state;
|
if (!hasIndex(row, column, parent)) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem* parentItem = itemFromIndex(parent);
|
||||||
|
HistoryItem* childItem = parentItem->child(row);
|
||||||
|
|
||||||
|
return childItem ? createIndex(row, column, childItem) : QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryModel::isSaving()
|
QModelIndex HistoryModel::parent(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
return m_isSaving;
|
if (!index.isValid()) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem* childItem = itemFromIndex(index);
|
||||||
|
HistoryItem* parentItem = childItem->parent();
|
||||||
|
|
||||||
|
if (!parentItem || parentItem == m_rootItem) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
return createIndex(parentItem->row(), 0, parentItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HistoryModel::titleCaseLocalizedMonth(int month)
|
Qt::ItemFlags HistoryModel::flags(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
switch (month) {
|
if (!index.isValid()) {
|
||||||
case 1:
|
return 0;
|
||||||
return tr("January");
|
}
|
||||||
case 2:
|
|
||||||
return tr("February");
|
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
case 3:
|
}
|
||||||
return tr("March");
|
|
||||||
case 4:
|
int HistoryModel::rowCount(const QModelIndex &parent) const
|
||||||
return tr("April");
|
{
|
||||||
case 5:
|
if (parent.column() > 0) {
|
||||||
return tr("May");
|
return 0;
|
||||||
case 6:
|
}
|
||||||
return tr("June");
|
|
||||||
case 7:
|
HistoryItem* parentItem = itemFromIndex(parent);
|
||||||
return tr("July");
|
|
||||||
case 8:
|
return parentItem->childCount();
|
||||||
return tr("August");
|
}
|
||||||
case 9:
|
|
||||||
return tr("September");
|
int HistoryModel::columnCount(const QModelIndex &parent) const
|
||||||
case 10:
|
{
|
||||||
return tr("October");
|
Q_UNUSED(parent)
|
||||||
case 11:
|
|
||||||
return tr("November");
|
return 4;
|
||||||
case 12:
|
}
|
||||||
return tr("December");
|
|
||||||
default:
|
bool HistoryModel::hasChildren(const QModelIndex &parent) const
|
||||||
qWarning("Month number out of range!");
|
{
|
||||||
return QString();
|
if (!parent.isValid()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem* item = itemFromIndex(parent);
|
||||||
|
|
||||||
|
return item ? item->isTopLevel() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem* HistoryModel::itemFromIndex(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (index.isValid()) {
|
||||||
|
HistoryItem* item = static_cast<HistoryItem*>(index.internalPointer());
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_rootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryModel::resetHistory()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
delete m_rootItem;
|
||||||
|
m_rootItem = new HistoryItem(0);
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HistoryModel::canFetchMore(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
HistoryItem* parentItem = itemFromIndex(parent);
|
||||||
|
|
||||||
|
return parentItem ? parentItem->canFetchMore : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryModel::fetchMore(const QModelIndex &parent)
|
||||||
|
{
|
||||||
|
HistoryItem* parentItem = itemFromIndex(parent);
|
||||||
|
|
||||||
|
if (!parent.isValid() || !parentItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parentItem->canFetchMore = false;
|
||||||
|
|
||||||
|
QList<int> idList;
|
||||||
|
for (int i = 0; i < parentItem->childCount(); ++i) {
|
||||||
|
idList.append(parentItem->child(i)->historyEntry.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query;
|
||||||
|
query.prepare("SELECT id, count, title, url, date FROM history WHERE date BETWEEN ? AND ? ORDER BY date DESC");
|
||||||
|
query.addBindValue(parentItem->endTimestamp());
|
||||||
|
query.addBindValue(parentItem->startTimestamp());
|
||||||
|
query.exec();
|
||||||
|
|
||||||
|
QList<HistoryEntry> list;
|
||||||
|
|
||||||
|
while (query.next()) {
|
||||||
|
HistoryEntry entry;
|
||||||
|
entry.id = query.value(0).toInt();
|
||||||
|
entry.count = query.value(1).toInt();
|
||||||
|
entry.title = query.value(2).toString();
|
||||||
|
entry.url = query.value(3).toUrl();
|
||||||
|
entry.date = QDateTime::fromMSecsSinceEpoch(query.value(4).toLongLong());
|
||||||
|
entry.urlString = entry.url.toEncoded();
|
||||||
|
|
||||||
|
if (!idList.contains(entry.id)) {
|
||||||
|
list.append(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginInsertRows(parent, 0, list.size() - 1);
|
||||||
|
|
||||||
|
foreach(const HistoryEntry & entry, list) {
|
||||||
|
HistoryItem* newItem = new HistoryItem(parentItem);
|
||||||
|
newItem->historyEntry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryModel::historyEntryAdded(const HistoryEntry &entry)
|
||||||
|
{
|
||||||
|
if (!m_todayItem) {
|
||||||
|
beginInsertRows(QModelIndex(), 0, 0);
|
||||||
|
|
||||||
|
m_todayItem = new HistoryItem(0);
|
||||||
|
m_todayItem->setStartTimestamp(-1);
|
||||||
|
m_todayItem->setEndTimestamp(QDateTime(QDate::currentDate()).toMSecsSinceEpoch());
|
||||||
|
m_todayItem->title = tr("Today");
|
||||||
|
|
||||||
|
m_rootItem->prependChild(m_todayItem);
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
beginInsertRows(createIndex(0, 0, m_todayItem), 0, 0);
|
||||||
|
|
||||||
|
HistoryItem* item = new HistoryItem();
|
||||||
|
item->historyEntry = entry;
|
||||||
|
|
||||||
|
m_todayItem->prependChild(item);
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryModel::historyEntryDeleted(const HistoryEntry &entry)
|
||||||
|
{
|
||||||
|
HistoryItem* item = findHistoryItem(entry);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem* parentItem = item->parent();
|
||||||
|
int row = item->row();
|
||||||
|
|
||||||
|
beginRemoveRows(createIndex(parentItem->row(), 0, parentItem), row, row);
|
||||||
|
delete item;
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
checkEmptyParentItem(parentItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryModel::historyEntryEdited(const HistoryEntry &before, const HistoryEntry &after)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
HistoryItem* item = findHistoryItem(before);
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
HistoryItem* parentItem = item->parent();
|
||||||
|
const QModelIndex &sourceParent = createIndex(parentItem->row(), 0, parentItem);
|
||||||
|
const QModelIndex &destinationParent = createIndex(m_todayItem->row(), 0, m_todayItem);
|
||||||
|
int row = item->row();
|
||||||
|
|
||||||
|
beginMoveRows(sourceParent, row, row, destinationParent, 0);
|
||||||
|
item->historyEntry = after;
|
||||||
|
item->refreshIcon();
|
||||||
|
item->changeParent(m_todayItem);
|
||||||
|
endMoveRows(); // This line sometimes throw "std::bad_alloc" ... I don't know why ?!
|
||||||
|
|
||||||
|
checkEmptyParentItem(parentItem);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
historyEntryAdded(after);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
historyEntryDeleted(before);
|
||||||
|
historyEntryAdded(after);
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryItem* HistoryModel::findHistoryItem(const HistoryEntry &entry)
|
||||||
|
{
|
||||||
|
HistoryItem* parentItem = 0;
|
||||||
|
qint64 timestamp = entry.date.toMSecsSinceEpoch();
|
||||||
|
|
||||||
|
for (int i = 0; i < m_rootItem->childCount(); ++i) {
|
||||||
|
HistoryItem* item = m_rootItem->child(i);
|
||||||
|
|
||||||
|
if (item->endTimestamp() < timestamp) {
|
||||||
|
parentItem = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parentItem) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < parentItem->childCount(); ++i) {
|
||||||
|
HistoryItem* item = parentItem->child(i);
|
||||||
|
if (item->historyEntry.id == entry.id) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryModel::checkEmptyParentItem(HistoryItem* item)
|
||||||
|
{
|
||||||
|
if (item->childCount() == 0 && item->isTopLevel()) {
|
||||||
|
int row = item->row();
|
||||||
|
|
||||||
|
beginRemoveRows(QModelIndex(), row, row);
|
||||||
|
delete item;
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
if (item == m_todayItem) {
|
||||||
|
m_todayItem = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryModel::init()
|
||||||
|
{
|
||||||
|
QSqlQuery query;
|
||||||
|
query.exec("SELECT MIN(date) FROM history");
|
||||||
|
if (!query.next()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QDate &today = QDate::currentDate();
|
||||||
|
const QDate &week = today.addDays(1 - today.dayOfWeek());
|
||||||
|
const QDate &month = QDate(today.year(), today.month(), 1);
|
||||||
|
|
||||||
|
const qint64 &minTimestamp = query.value(0).toLongLong();
|
||||||
|
const qint64 ¤tTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
|
||||||
|
qint64 timestamp = currentTimestamp;
|
||||||
|
while (timestamp > minTimestamp) {
|
||||||
|
QDate timestampDate = QDateTime::fromMSecsSinceEpoch(timestamp).date();
|
||||||
|
qint64 endTimestamp;
|
||||||
|
QString itemName;
|
||||||
|
|
||||||
|
if (timestampDate == today) {
|
||||||
|
endTimestamp = QDateTime(today).toMSecsSinceEpoch();
|
||||||
|
|
||||||
|
itemName = tr("Today");
|
||||||
|
}
|
||||||
|
else if (timestampDate >= week) {
|
||||||
|
endTimestamp = QDateTime(week).toMSecsSinceEpoch();
|
||||||
|
|
||||||
|
itemName = tr("This Week");
|
||||||
|
}
|
||||||
|
else if (timestampDate.month() == month.month() && timestampDate.year() == month.year()) {
|
||||||
|
endTimestamp = QDateTime(month).toMSecsSinceEpoch();
|
||||||
|
|
||||||
|
itemName = tr("This Month");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QDate startDate(timestampDate.year(), timestampDate.month(), timestampDate.daysInMonth());
|
||||||
|
QDate endDate(startDate.year(), startDate.month(), 1);
|
||||||
|
|
||||||
|
timestamp = QDateTime(startDate, QTime(23, 59, 59)).toMSecsSinceEpoch();
|
||||||
|
endTimestamp = QDateTime(endDate).toMSecsSinceEpoch();
|
||||||
|
itemName = QString("%1 %2").arg(History::titleCaseLocalizedMonth(timestampDate.month()), QString::number(timestampDate.year()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query;
|
||||||
|
query.prepare("SELECT id FROM history WHERE date BETWEEN ? AND ? LIMIT 1");
|
||||||
|
query.addBindValue(endTimestamp);
|
||||||
|
query.addBindValue(timestamp);
|
||||||
|
query.exec();
|
||||||
|
|
||||||
|
if (query.next()) {
|
||||||
|
HistoryItem* item = new HistoryItem(m_rootItem);
|
||||||
|
item->setStartTimestamp(timestamp == currentTimestamp ? -1 : timestamp);
|
||||||
|
item->setEndTimestamp(endTimestamp);
|
||||||
|
item->title = itemName;
|
||||||
|
item->canFetchMore = true;
|
||||||
|
|
||||||
|
if (timestamp == currentTimestamp) {
|
||||||
|
m_todayItem = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp = endTimestamp - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryFilterModel::HistoryFilterModel(QAbstractItemModel* parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
setSourceModel(parent);
|
||||||
|
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
|
||||||
|
m_filterTimer = new QTimer(this);
|
||||||
|
m_filterTimer->setSingleShot(true);
|
||||||
|
m_filterTimer->setInterval(500);
|
||||||
|
|
||||||
|
connect(m_filterTimer, SIGNAL(timeout()), this, SLOT(startFiltering()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryFilterModel::setFilterFixedString(const QString &pattern)
|
||||||
|
{
|
||||||
|
m_pattern = pattern;
|
||||||
|
|
||||||
|
m_filterTimer->stop();
|
||||||
|
m_filterTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryFilterModel::startFiltering()
|
||||||
|
{
|
||||||
|
if (m_pattern.isEmpty()) {
|
||||||
|
emit collapseAllItems();
|
||||||
|
QSortFilterProxyModel::setFilterFixedString(m_pattern);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
|
// Expand all items also calls fetchmore
|
||||||
|
emit expandAllItems();
|
||||||
|
|
||||||
|
QSortFilterProxyModel::setFilterFixedString(m_pattern);
|
||||||
|
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HistoryFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||||
|
{
|
||||||
|
const QModelIndex &index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||||
|
|
||||||
|
if (index.data(HistoryModel::IsTopLevelRole).toBool()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (index.data(HistoryModel::UrlStringRole).toString().contains(filterRegExp()) ||
|
||||||
|
index.data(HistoryModel::TitleRole).toString().contains(filterRegExp()));
|
||||||
|
}
|
||||||
|
|
|
@ -18,67 +18,95 @@
|
||||||
#ifndef HISTORYMODEL_H
|
#ifndef HISTORYMODEL_H
|
||||||
#define HISTORYMODEL_H
|
#define HISTORYMODEL_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QAbstractItemModel>
|
||||||
#include <QList>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QDateTime>
|
|
||||||
#include <QUrl>
|
|
||||||
|
|
||||||
#include "qz_namespace.h"
|
#include "qz_namespace.h"
|
||||||
|
#include "history.h"
|
||||||
|
|
||||||
class QIcon;
|
class QTimer;
|
||||||
|
|
||||||
class QupZilla;
|
class History;
|
||||||
class WebView;
|
class HistoryItem;
|
||||||
|
|
||||||
class QT_QUPZILLA_EXPORT HistoryModel : public QObject
|
class QT_QUPZILLA_EXPORT HistoryModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
HistoryModel(QupZilla* mainClass);
|
enum Roles {
|
||||||
|
IdRole = Qt::UserRole + 1,
|
||||||
struct HistoryEntry {
|
TitleRole = Qt::UserRole + 2,
|
||||||
int id;
|
UrlRole = Qt::UserRole + 3,
|
||||||
int count;
|
UrlStringRole = Qt::UserRole + 4,
|
||||||
QDateTime date;
|
IconRole = Qt::UserRole + 5,
|
||||||
QUrl url;
|
IconLoadedRole = Qt::UserRole + 6,
|
||||||
QString title;
|
IsTopLevelRole = Qt::UserRole + 7,
|
||||||
|
TimestampStartRole = Qt::UserRole + 8,
|
||||||
|
TimestampEndRole = Qt::UserRole + 9,
|
||||||
|
MaxRole = TimestampEndRole
|
||||||
};
|
};
|
||||||
|
|
||||||
static QString titleCaseLocalizedMonth(int month);
|
explicit HistoryModel(History* history);
|
||||||
|
|
||||||
void addHistoryEntry(WebView* view);
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
void addHistoryEntry(const QUrl &url, QString title);
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||||
|
|
||||||
void deleteHistoryEntry(int index);
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
|
||||||
void deleteHistoryEntry(const QList<int> &list);
|
QModelIndex parent(const QModelIndex &child) const;
|
||||||
void deleteHistoryEntry(const QString &url, const QString &title);
|
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
|
|
||||||
bool urlIsStored(const QString &url);
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
|
||||||
QList<HistoryEntry> mostVisited(int count);
|
bool canFetchMore(const QModelIndex &parent) const;
|
||||||
|
void fetchMore(const QModelIndex &parent);
|
||||||
|
|
||||||
bool clearHistory();
|
bool hasChildren(const QModelIndex &parent) const;
|
||||||
bool optimizeHistory();
|
|
||||||
bool isSaving();
|
|
||||||
void setSaving(bool state);
|
|
||||||
|
|
||||||
void loadSettings();
|
HistoryItem* itemFromIndex(const QModelIndex &index) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void historyEntryAdded(HistoryEntry entry);
|
|
||||||
void historyEntryDeleted(HistoryEntry entry);
|
|
||||||
void historyEntryEdited(HistoryEntry before, HistoryEntry after);
|
|
||||||
//WARNING: Incomplete HistoryEntry structs are passed to historyEntryEdited!
|
|
||||||
void historyClear();
|
|
||||||
|
|
||||||
void signalAddHistoryEntry(QUrl url, QString title);
|
private slots:
|
||||||
void signalDeleteHistoryEntry(QList<int> list);
|
void resetHistory();
|
||||||
|
|
||||||
|
void historyEntryAdded(const HistoryEntry &entry);
|
||||||
|
void historyEntryDeleted(const HistoryEntry &entry);
|
||||||
|
void historyEntryEdited(const HistoryEntry &before, const HistoryEntry &after);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_isSaving;
|
HistoryItem* findHistoryItem(const HistoryEntry &entry);
|
||||||
QupZilla* p_QupZilla;
|
void checkEmptyParentItem(HistoryItem* item);
|
||||||
|
void init();
|
||||||
|
|
||||||
|
HistoryItem* m_rootItem;
|
||||||
|
HistoryItem* m_todayItem;
|
||||||
|
History* m_history;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef HistoryModel::HistoryEntry HistoryEntry;
|
class QT_QUPZILLA_EXPORT HistoryFilterModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit HistoryFilterModel(QAbstractItemModel* parent);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setFilterFixedString(const QString &pattern);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void expandAllItems();
|
||||||
|
void collapseAllItems();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void startFiltering();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_pattern;
|
||||||
|
QTimer* m_filterTimer;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // HISTORYMODEL_H
|
#endif // HISTORYMODEL_H
|
||||||
|
|
191
src/lib/history/historyview.cpp
Normal file
191
src/lib/history/historyview.cpp
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
/* ============================================================
|
||||||
|
* QupZilla - WebKit based browser
|
||||||
|
* Copyright (C) 2010-2012 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 "historyview.h"
|
||||||
|
#include "historymodel.h"
|
||||||
|
#include "historyitem.h"
|
||||||
|
#include "headerview.h"
|
||||||
|
#include "mainapplication.h"
|
||||||
|
#include "iconprovider.h"
|
||||||
|
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
HistoryView::HistoryView(QWidget* parent)
|
||||||
|
: QTreeView(parent)
|
||||||
|
, m_history(mApp->history())
|
||||||
|
, m_filterModel(new HistoryFilterModel(m_history->model()))
|
||||||
|
{
|
||||||
|
setModel(m_filterModel);
|
||||||
|
|
||||||
|
setAllColumnsShowFocus(true);
|
||||||
|
setUniformRowHeights(true);
|
||||||
|
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
|
||||||
|
m_header = new HeaderView(this);
|
||||||
|
setHeader(m_header);
|
||||||
|
|
||||||
|
m_header->setDefaultSectionSizes(QList<double>() << 0.4 << 0.35 << 0.10 << 0.08);
|
||||||
|
m_header->setSectionHidden(4, true);
|
||||||
|
|
||||||
|
connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(itemActivated(QModelIndex)));
|
||||||
|
connect(this, SIGNAL(pressed(QModelIndex)), this, SLOT(itemPressed(QModelIndex)));
|
||||||
|
|
||||||
|
connect(m_filterModel, SIGNAL(expandAllItems()), this, SLOT(expandAll()));
|
||||||
|
connect(m_filterModel, SIGNAL(collapseAllItems()), this, SLOT(collapseAll()));
|
||||||
|
}
|
||||||
|
|
||||||
|
HeaderView* HistoryView::header() const
|
||||||
|
{
|
||||||
|
return m_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryFilterModel* HistoryView::filterModel() const
|
||||||
|
{
|
||||||
|
return m_filterModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::removeItems()
|
||||||
|
{
|
||||||
|
QList<int> list;
|
||||||
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
|
foreach(const QModelIndex & index, selectedIndexes()) {
|
||||||
|
if (index.column() > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index.data(HistoryModel::IsTopLevelRole).toBool()) {
|
||||||
|
qint64 start = index.data(HistoryModel::TimestampStartRole).toLongLong();
|
||||||
|
qint64 end = index.data(HistoryModel::TimestampEndRole).toLongLong();
|
||||||
|
|
||||||
|
list.append(m_history->indexesFromTimeRange(start, end));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int id = index.data(HistoryModel::IdRole).toInt();
|
||||||
|
if (!list.contains(id)) {
|
||||||
|
list.append(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_history->deleteHistoryEntry(list);
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::itemActivated(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.data(HistoryModel::IsTopLevelRole).toBool()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit openLink(index.data(HistoryModel::UrlRole).toUrl(), OpenInCurrentTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::itemPressed(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.data(HistoryModel::IsTopLevelRole).toBool()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((selectionMode() == QAbstractItemView::SingleSelection && QApplication::keyboardModifiers() & Qt::ControlModifier)
|
||||||
|
|| (QApplication::mouseButtons() & Qt::MiddleButton)) {
|
||||||
|
emit openLink(index.data(HistoryModel::UrlRole).toUrl(), OpenInNewTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::openLinkInCurrentTab()
|
||||||
|
{
|
||||||
|
if (m_clickedIndex.isValid()) {
|
||||||
|
emit openLink(m_clickedIndex.data(HistoryModel::UrlRole).toUrl(), OpenInCurrentTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::openLinkInNewTab()
|
||||||
|
{
|
||||||
|
if (m_clickedIndex.isValid()) {
|
||||||
|
emit openLink(m_clickedIndex.data(HistoryModel::UrlRole).toUrl(), OpenInNewTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::copyTitle()
|
||||||
|
{
|
||||||
|
if (m_clickedIndex.isValid()) {
|
||||||
|
QApplication::clipboard()->setText(m_clickedIndex.data(HistoryModel::TitleRole).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::copyAddress()
|
||||||
|
{
|
||||||
|
if (m_clickedIndex.isValid()) {
|
||||||
|
QApplication::clipboard()->setText(m_clickedIndex.data(HistoryModel::UrlStringRole).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::contextMenuEvent(QContextMenuEvent* event)
|
||||||
|
{
|
||||||
|
const QModelIndex &index = indexAt(event->pos());
|
||||||
|
if (!index.isValid() || index.data(HistoryModel::IsTopLevelRole).toBool()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_clickedIndex = index;
|
||||||
|
|
||||||
|
QMenu menu;
|
||||||
|
menu.addAction(tr("Open link in current tab"), this, SLOT(openLinkInCurrentTab()));
|
||||||
|
menu.addAction(tr("Open link in new tab"), this, SLOT(openLinkInNewTab()));
|
||||||
|
menu.addSeparator();
|
||||||
|
menu.addAction(tr("Copy title"), this, SLOT(copyTitle()));
|
||||||
|
menu.addAction(tr("Copy address"), this, SLOT(copyAddress()));
|
||||||
|
menu.addSeparator();
|
||||||
|
menu.addAction(tr("Remove"), this, SLOT(removeItems()));
|
||||||
|
|
||||||
|
// Prevent choosing first option with double rightclick
|
||||||
|
QPoint pos = viewport()->mapToGlobal(event->pos());
|
||||||
|
QPoint p(pos.x(), pos.y() + 1);
|
||||||
|
menu.exec(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::keyPressEvent(QKeyEvent* event)
|
||||||
|
{
|
||||||
|
if (event->key() == Qt::Key_Delete) {
|
||||||
|
removeItems();
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
QTreeView::keyPressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryView::drawRow(QPainter* painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
bool itemTopLevel = index.data(HistoryModel::IsTopLevelRole).toBool();
|
||||||
|
bool iconLoaded = index.data(HistoryModel::IconLoadedRole).toBool();
|
||||||
|
|
||||||
|
if (index.isValid() && !itemTopLevel && !iconLoaded) {
|
||||||
|
QImage image = qIconProvider->iconForUrl(index.data(HistoryModel::UrlRole).toUrl());
|
||||||
|
if (image == qIconProvider->emptyWebImage()) {
|
||||||
|
model()->setData(index, QIcon(), HistoryModel::IconRole);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
model()->setData(index, QIcon(QPixmap::fromImage(image)), HistoryModel::IconRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTreeView::drawRow(painter, options, index);
|
||||||
|
}
|
66
src/lib/history/historyview.h
Normal file
66
src/lib/history/historyview.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* ============================================================
|
||||||
|
* QupZilla - WebKit based browser
|
||||||
|
* Copyright (C) 2010-2012 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 HISTORYVIEW_H
|
||||||
|
#define HISTORYVIEW_H
|
||||||
|
|
||||||
|
#include <QTreeView>
|
||||||
|
|
||||||
|
class History;
|
||||||
|
class HistoryFilterModel;
|
||||||
|
class HeaderView;
|
||||||
|
|
||||||
|
class HistoryView : public QTreeView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum OpenBehavior { OpenInCurrentTab, OpenInNewTab };
|
||||||
|
|
||||||
|
explicit HistoryView(QWidget* parent = 0);
|
||||||
|
|
||||||
|
HeaderView* header() const;
|
||||||
|
HistoryFilterModel* filterModel() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void openLink(const QUrl &, HistoryView::OpenBehavior);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void removeItems();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void itemActivated(const QModelIndex &index);
|
||||||
|
void itemPressed(const QModelIndex &index);
|
||||||
|
|
||||||
|
void openLinkInCurrentTab();
|
||||||
|
void openLinkInNewTab();
|
||||||
|
void copyTitle();
|
||||||
|
void copyAddress();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void contextMenuEvent(QContextMenuEvent* event);
|
||||||
|
void keyPressEvent(QKeyEvent* event);
|
||||||
|
void drawRow(QPainter* painter, const QStyleOptionViewItem &options, const QModelIndex &index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
History* m_history;
|
||||||
|
HistoryFilterModel* m_filterModel;
|
||||||
|
HeaderView* m_header;
|
||||||
|
|
||||||
|
QModelIndex m_clickedIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HISTORYVIEW_H
|
|
@ -17,7 +17,7 @@
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
#include "webhistoryinterface.h"
|
#include "webhistoryinterface.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "historymodel.h"
|
#include "history.h"
|
||||||
|
|
||||||
WebHistoryInterface::WebHistoryInterface(QObject* parent)
|
WebHistoryInterface::WebHistoryInterface(QObject* parent)
|
||||||
: QWebHistoryInterface(parent)
|
: QWebHistoryInterface(parent)
|
||||||
|
|
|
@ -8,6 +8,7 @@ DEFINES *= QUPZILLA_SHAREDLIBRARY
|
||||||
include(3rdparty/qtsingleapplication.pri)
|
include(3rdparty/qtsingleapplication.pri)
|
||||||
include(../defines.pri)
|
include(../defines.pri)
|
||||||
include(../../translations/translations.pri)
|
include(../../translations/translations.pri)
|
||||||
|
#include(../../tests/modeltest/modeltest.pri)
|
||||||
|
|
||||||
INCLUDEPATH += 3rdparty\
|
INCLUDEPATH += 3rdparty\
|
||||||
app\
|
app\
|
||||||
|
@ -47,7 +48,6 @@ SOURCES += \
|
||||||
cookies/cookiemanager.cpp \
|
cookies/cookiemanager.cpp \
|
||||||
cookies/cookiejar.cpp \
|
cookies/cookiejar.cpp \
|
||||||
downloads/downloadmanager.cpp \
|
downloads/downloadmanager.cpp \
|
||||||
history/historymodel.cpp \
|
|
||||||
history/historymanager.cpp \
|
history/historymanager.cpp \
|
||||||
navigation/websearchbar.cpp \
|
navigation/websearchbar.cpp \
|
||||||
navigation/locationbar.cpp \
|
navigation/locationbar.cpp \
|
||||||
|
@ -172,7 +172,12 @@ SOURCES += \
|
||||||
navigation/completer/locationcompleterdelegate.cpp \
|
navigation/completer/locationcompleterdelegate.cpp \
|
||||||
navigation/completer/locationcompleter.cpp \
|
navigation/completer/locationcompleter.cpp \
|
||||||
navigation/completer/locationcompletermodel.cpp \
|
navigation/completer/locationcompletermodel.cpp \
|
||||||
navigation/completer/locationcompleterview.cpp
|
navigation/completer/locationcompleterview.cpp \
|
||||||
|
history/history.cpp \
|
||||||
|
history/historymodel.cpp \
|
||||||
|
history/historyview.cpp \
|
||||||
|
history/historyitem.cpp \
|
||||||
|
tools/headerview.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
webview/tabpreview.h \
|
webview/tabpreview.h \
|
||||||
|
@ -188,7 +193,6 @@ HEADERS += \
|
||||||
cookies/cookiemanager.h \
|
cookies/cookiemanager.h \
|
||||||
cookies/cookiejar.h \
|
cookies/cookiejar.h \
|
||||||
downloads/downloadmanager.h \
|
downloads/downloadmanager.h \
|
||||||
history/historymodel.h \
|
|
||||||
history/historymanager.h \
|
history/historymanager.h \
|
||||||
navigation/websearchbar.h \
|
navigation/websearchbar.h \
|
||||||
navigation/locationbar.h \
|
navigation/locationbar.h \
|
||||||
|
@ -317,7 +321,12 @@ HEADERS += \
|
||||||
navigation/completer/locationcompleterdelegate.h \
|
navigation/completer/locationcompleterdelegate.h \
|
||||||
navigation/completer/locationcompleter.h \
|
navigation/completer/locationcompleter.h \
|
||||||
navigation/completer/locationcompletermodel.h \
|
navigation/completer/locationcompletermodel.h \
|
||||||
navigation/completer/locationcompleterview.h
|
navigation/completer/locationcompleterview.h \
|
||||||
|
history/history.h \
|
||||||
|
history/historymodel.h \
|
||||||
|
history/historyview.h \
|
||||||
|
history/historyitem.h \
|
||||||
|
tools/headerview.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
preferences/autofillmanager.ui \
|
preferences/autofillmanager.ui \
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "downloaditem.h"
|
#include "downloaditem.h"
|
||||||
#include "globalfunctions.h"
|
#include "globalfunctions.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "history.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
@ -35,7 +36,6 @@ BrowsingLibrary::BrowsingLibrary(QupZilla* mainClass, QWidget* parent)
|
||||||
, m_historyManager(new HistoryManager(mainClass))
|
, m_historyManager(new HistoryManager(mainClass))
|
||||||
, m_bookmarksManager(new BookmarksManager(mainClass))
|
, m_bookmarksManager(new BookmarksManager(mainClass))
|
||||||
, m_rssManager(mApp->rssManager())
|
, m_rssManager(mApp->rssManager())
|
||||||
, m_historyLoaded(false)
|
|
||||||
, m_bookmarksLoaded(false)
|
, m_bookmarksLoaded(false)
|
||||||
, m_rssLoaded(false)
|
, m_rssLoaded(false)
|
||||||
{
|
{
|
||||||
|
@ -44,6 +44,7 @@ BrowsingLibrary::BrowsingLibrary(QupZilla* mainClass, QWidget* parent)
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.beginGroup("BrowsingLibrary");
|
settings.beginGroup("BrowsingLibrary");
|
||||||
resize(settings.value("size", QSize(760, 470)).toSize());
|
resize(settings.value("size", QSize(760, 470)).toSize());
|
||||||
|
m_historyManager->restoreState(settings.value("historyState", QByteArray()).toByteArray());
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
qz_centerWidgetOnScreen(this);
|
qz_centerWidgetOnScreen(this);
|
||||||
|
@ -63,10 +64,6 @@ void BrowsingLibrary::currentIndexChanged(int index)
|
||||||
{
|
{
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
if (!m_historyLoaded) {
|
|
||||||
m_historyManager->refreshTable();
|
|
||||||
m_historyLoaded = true;
|
|
||||||
}
|
|
||||||
ui->searchLine->show();
|
ui->searchLine->show();
|
||||||
search();
|
search();
|
||||||
break;
|
break;
|
||||||
|
@ -109,11 +106,6 @@ void BrowsingLibrary::showHistory(QupZilla* mainClass)
|
||||||
show();
|
show();
|
||||||
m_historyManager->setMainWindow(mainClass);
|
m_historyManager->setMainWindow(mainClass);
|
||||||
|
|
||||||
if (!m_historyLoaded) {
|
|
||||||
m_historyManager->refreshTable();
|
|
||||||
m_historyLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
raise();
|
raise();
|
||||||
activateWindow();
|
activateWindow();
|
||||||
}
|
}
|
||||||
|
@ -161,6 +153,7 @@ void BrowsingLibrary::closeEvent(QCloseEvent* e)
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.beginGroup("BrowsingLibrary");
|
settings.beginGroup("BrowsingLibrary");
|
||||||
settings.setValue("size", size());
|
settings.setValue("size", size());
|
||||||
|
settings.setValue("historyState", m_historyManager->saveState());
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
e->accept();
|
e->accept();
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ private:
|
||||||
HistoryManager* m_historyManager;
|
HistoryManager* m_historyManager;
|
||||||
BookmarksManager* m_bookmarksManager;
|
BookmarksManager* m_bookmarksManager;
|
||||||
RSSManager* m_rssManager;
|
RSSManager* m_rssManager;
|
||||||
bool m_historyLoaded;
|
|
||||||
bool m_bookmarksLoaded;
|
bool m_bookmarksLoaded;
|
||||||
bool m_rssLoaded;
|
bool m_rssLoaded;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "qupzilla.h"
|
#include "qupzilla.h"
|
||||||
#include "tabwidget.h"
|
#include "tabwidget.h"
|
||||||
#include "cookiejar.h"
|
#include "cookiejar.h"
|
||||||
|
#include "history.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "networkmanager.h"
|
#include "networkmanager.h"
|
||||||
|
@ -108,29 +109,34 @@ void ClearPrivateData::dialogAccepted()
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
if (ui->history->isChecked()) {
|
if (ui->history->isChecked()) {
|
||||||
QDateTime dateTime = QDateTime::currentDateTime();
|
qint64 start = QDateTime::currentMSecsSinceEpoch();
|
||||||
qint64 nowMS = QDateTime::currentMSecsSinceEpoch();
|
qint64 end = 0;
|
||||||
qint64 date = 0;
|
|
||||||
|
const QDate &today = QDate::currentDate();
|
||||||
|
const QDate &week = today.addDays(1 - today.dayOfWeek());
|
||||||
|
const QDate &month = QDate(today.year(), today.month(), 1);
|
||||||
|
|
||||||
switch (ui->historyLength->currentIndex()) {
|
switch (ui->historyLength->currentIndex()) {
|
||||||
case 0: //Later Today
|
case 0: //Later Today
|
||||||
dateTime.setTime(QTime(0, 0));
|
end = QDateTime(today).toMSecsSinceEpoch();
|
||||||
date = dateTime.toMSecsSinceEpoch();
|
|
||||||
break;
|
break;
|
||||||
case 1: //Week
|
case 1: //Week
|
||||||
date = nowMS - 60u * 60u * 24u * 7u * 1000u;
|
end = QDateTime(week).toMSecsSinceEpoch();
|
||||||
break;
|
break;
|
||||||
case 2: //Month
|
case 2: //Month
|
||||||
date = nowMS - 60u * 60u * 24u * 30u * 1000u;
|
end = QDateTime(month).toMSecsSinceEpoch();
|
||||||
break;
|
break;
|
||||||
case 3: //All
|
case 3: //All
|
||||||
date = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSqlQuery query;
|
if (end == 0) {
|
||||||
query.exec("DELETE FROM history WHERE date > " + QString::number(date));
|
mApp->history()->clearHistory();
|
||||||
query.exec("VACUUM");
|
}
|
||||||
|
else {
|
||||||
|
const QList<int> &indexes = mApp->history()->indexesFromTimeRange(start, end);
|
||||||
|
mApp->history()->deleteHistoryEntry(indexes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ui->cookies->isChecked()) {
|
if (ui->cookies->isChecked()) {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "ui_preferences.h"
|
#include "ui_preferences.h"
|
||||||
#include "qupzilla.h"
|
#include "qupzilla.h"
|
||||||
#include "bookmarkstoolbar.h"
|
#include "bookmarkstoolbar.h"
|
||||||
#include "historymodel.h"
|
#include "history.h"
|
||||||
#include "tabwidget.h"
|
#include "tabwidget.h"
|
||||||
#include "cookiejar.h"
|
#include "cookiejar.h"
|
||||||
#include "locationbar.h"
|
#include "locationbar.h"
|
||||||
|
|
|
@ -19,226 +19,34 @@
|
||||||
#include "ui_historysidebar.h"
|
#include "ui_historysidebar.h"
|
||||||
#include "qupzilla.h"
|
#include "qupzilla.h"
|
||||||
#include "tabwidget.h"
|
#include "tabwidget.h"
|
||||||
|
#include "tabbedwebview.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "historymodel.h"
|
#include "historymodel.h"
|
||||||
#include "iconprovider.h"
|
|
||||||
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QClipboard>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QSqlQuery>
|
|
||||||
|
|
||||||
HistorySideBar::HistorySideBar(QupZilla* mainClass, QWidget* parent)
|
HistorySideBar::HistorySideBar(QupZilla* mainClass, QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, ui(new Ui::HistorySideBar)
|
, ui(new Ui::HistorySideBar)
|
||||||
, p_QupZilla(mainClass)
|
, p_QupZilla(mainClass)
|
||||||
, m_historyModel(mApp->history())
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
connect(ui->historyTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem*)));
|
|
||||||
connect(ui->historyTree, SIGNAL(itemControlClicked(QTreeWidgetItem*)), this, SLOT(itemControlClicked(QTreeWidgetItem*)));
|
|
||||||
connect(ui->historyTree, SIGNAL(itemMiddleButtonClicked(QTreeWidgetItem*)), this, SLOT(itemControlClicked(QTreeWidgetItem*)));
|
|
||||||
|
|
||||||
connect(ui->historyTree, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(contextMenuRequested(const QPoint &)));
|
ui->historyTree->setColumnHidden(1, true);
|
||||||
connect(ui->search, SIGNAL(textEdited(QString)), ui->historyTree, SLOT(filterString(QString)));
|
ui->historyTree->setColumnHidden(2, true);
|
||||||
|
ui->historyTree->setColumnHidden(3, true);
|
||||||
|
ui->historyTree->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
|
||||||
connect(m_historyModel, SIGNAL(historyEntryAdded(HistoryEntry)), this, SLOT(historyEntryAdded(HistoryEntry)));
|
connect(ui->historyTree, SIGNAL(openLink(QUrl, HistoryView::OpenBehavior)), this, SLOT(openLink(QUrl, HistoryView::OpenBehavior)));
|
||||||
connect(m_historyModel, SIGNAL(historyEntryDeleted(HistoryEntry)), this, SLOT(historyEntryDeleted(HistoryEntry)));
|
connect(ui->search, SIGNAL(textEdited(QString)), ui->historyTree->filterModel(), SLOT(setFilterFixedString(QString)));
|
||||||
connect(m_historyModel, SIGNAL(historyEntryEdited(HistoryEntry, HistoryEntry)), this, SLOT(historyEntryEdited(HistoryEntry, HistoryEntry)));
|
|
||||||
connect(m_historyModel, SIGNAL(historyClear()), ui->historyTree, SLOT(clear()));
|
|
||||||
|
|
||||||
QTimer::singleShot(0, this, SLOT(slotRefreshTable()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistorySideBar::itemDoubleClicked(QTreeWidgetItem* item)
|
void HistorySideBar::openLink(const QUrl &url, HistoryView::OpenBehavior openIn)
|
||||||
{
|
{
|
||||||
if (!item || item->text(1).isEmpty()) {
|
if (openIn == HistoryView::OpenInNewTab) {
|
||||||
return;
|
p_QupZilla->tabWidget()->addView(url, Qz::NT_NotSelectedTab);
|
||||||
}
|
|
||||||
|
|
||||||
QUrl url = QUrl::fromEncoded(item->text(1).toUtf8());
|
|
||||||
p_QupZilla->loadAddress(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistorySideBar::itemControlClicked(QTreeWidgetItem* item)
|
|
||||||
{
|
|
||||||
if (!item || item->text(1).isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl url = QUrl::fromEncoded(item->text(1).toUtf8());
|
|
||||||
p_QupZilla->tabWidget()->addView(url, item->text(0), Qz::NT_NotSelectedTab);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistorySideBar::loadInNewTab()
|
|
||||||
{
|
|
||||||
if (QAction* action = qobject_cast<QAction*>(sender())) {
|
|
||||||
p_QupZilla->tabWidget()->addView(action->data().toUrl(), Qz::NT_NotSelectedTab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistorySideBar::copyAddress()
|
|
||||||
{
|
|
||||||
if (QAction* action = qobject_cast<QAction*>(sender())) {
|
|
||||||
QApplication::clipboard()->setText(action->data().toUrl().toEncoded());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistorySideBar::contextMenuRequested(const QPoint &position)
|
|
||||||
{
|
|
||||||
if (!ui->historyTree->itemAt(position)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUrl link = QUrl::fromEncoded(ui->historyTree->itemAt(position)->text(1).toUtf8());
|
|
||||||
if (link.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMenu menu;
|
|
||||||
menu.addAction(tr("Open link in current tab"), p_QupZilla, SLOT(loadActionUrl()))->setData(link);
|
|
||||||
menu.addAction(tr("Open link in new tab"), this, SLOT(loadInNewTab()))->setData(link);
|
|
||||||
menu.addSeparator();
|
|
||||||
menu.addAction(tr("Copy address"), this, SLOT(copyAddress()))->setData(link);
|
|
||||||
|
|
||||||
//Prevent choosing first option with double rightclick
|
|
||||||
QPoint pos = ui->historyTree->viewport()->mapToGlobal(position);
|
|
||||||
QPoint p(pos.x(), pos.y() + 1);
|
|
||||||
menu.exec(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistorySideBar::historyEntryAdded(const HistoryEntry &entry)
|
|
||||||
{
|
|
||||||
QDate todayDate = QDate::currentDate();
|
|
||||||
QDate startOfWeekDate = todayDate.addDays(1 - todayDate.dayOfWeek());
|
|
||||||
|
|
||||||
QDate date = entry.date.date();
|
|
||||||
QString localDate;
|
|
||||||
|
|
||||||
if (date == todayDate) {
|
|
||||||
localDate = tr("Today");
|
|
||||||
}
|
|
||||||
else if (date >= startOfWeekDate) {
|
|
||||||
localDate = tr("This Week");
|
|
||||||
}
|
|
||||||
else if (date.month() == todayDate.month()) {
|
|
||||||
localDate = tr("This Month");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
localDate = QString("%1 %2").arg(HistoryModel::titleCaseLocalizedMonth(date.month()), QString::number(date.year()));
|
p_QupZilla->weView()->load(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
|
||||||
QTreeWidgetItem* parentItem;
|
|
||||||
QList<QTreeWidgetItem*> findParent = ui->historyTree->findItems(localDate, 0);
|
|
||||||
if (findParent.count() == 1) {
|
|
||||||
parentItem = findParent.at(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parentItem = new QTreeWidgetItem();
|
|
||||||
parentItem->setText(0, localDate);
|
|
||||||
parentItem->setIcon(0, QIcon(":/icons/menu/history_entry.png"));
|
|
||||||
ui->historyTree->insertTopLevelItem(0, parentItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
item->setText(0, entry.title);
|
|
||||||
item->setText(1, entry.url.toEncoded());
|
|
||||||
item->setToolTip(0, entry.url.toEncoded());
|
|
||||||
|
|
||||||
item->setData(0, Qt::UserRole + 10, entry.id);
|
|
||||||
item->setIcon(0, _iconForUrl(entry.url));
|
|
||||||
ui->historyTree->prependToParentItem(parentItem, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistorySideBar::historyEntryDeleted(const HistoryEntry &entry)
|
|
||||||
{
|
|
||||||
QList<QTreeWidgetItem*> list = ui->historyTree->allItems();
|
|
||||||
foreach(QTreeWidgetItem * item, list) {
|
|
||||||
if (!item) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (item->data(0, Qt::UserRole + 10).toInt() != entry.id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ui->historyTree->deleteItem(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistorySideBar::historyEntryEdited(const HistoryEntry &before, const HistoryEntry &after)
|
|
||||||
{
|
|
||||||
historyEntryDeleted(before);
|
|
||||||
historyEntryAdded(after);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistorySideBar::slotRefreshTable()
|
|
||||||
{
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
ui->historyTree->clear();
|
|
||||||
|
|
||||||
QDate todayDate = QDate::currentDate();
|
|
||||||
QDate startOfWeekDate = todayDate.addDays(1 - todayDate.dayOfWeek());
|
|
||||||
QSqlQuery query;
|
|
||||||
query.exec("SELECT title, url, id, date FROM history ORDER BY date DESC");
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
QWeakPointer<HistorySideBar> guard = this;
|
|
||||||
QHash<QString, QTreeWidgetItem*> hash;
|
|
||||||
while (query.next()) {
|
|
||||||
const QString &title = query.value(0).toString();
|
|
||||||
const QUrl &url = query.value(1).toUrl();
|
|
||||||
int id = query.value(2).toInt();
|
|
||||||
const QDate &date = QDateTime::fromMSecsSinceEpoch(query.value(3).toLongLong()).date();
|
|
||||||
QString localDate;
|
|
||||||
|
|
||||||
if (date == todayDate) {
|
|
||||||
localDate = tr("Today");
|
|
||||||
}
|
|
||||||
else if (date >= startOfWeekDate) {
|
|
||||||
localDate = tr("This Week");
|
|
||||||
}
|
|
||||||
else if (date.month() == todayDate.month()) {
|
|
||||||
localDate = tr("This Month");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
localDate = QString("%1 %2").arg(HistoryModel::titleCaseLocalizedMonth(date.month()), QString::number(date.year()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QTreeWidgetItem* item;
|
|
||||||
QTreeWidgetItem* findParent = hash[localDate];
|
|
||||||
if (findParent) {
|
|
||||||
item = new QTreeWidgetItem(findParent);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QTreeWidgetItem* newParent = new QTreeWidgetItem(ui->historyTree);
|
|
||||||
newParent->setText(0, localDate);
|
|
||||||
newParent->setIcon(0, QIcon(":/icons/menu/history_entry.png"));
|
|
||||||
ui->historyTree->addTopLevelItem(newParent);
|
|
||||||
hash[localDate] = newParent;
|
|
||||||
|
|
||||||
item = new QTreeWidgetItem(newParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
item->setText(0, title);
|
|
||||||
item->setText(1, url.toEncoded());
|
|
||||||
item->setToolTip(0, url.toEncoded());
|
|
||||||
|
|
||||||
item->setData(0, Qt::UserRole + 10, id);
|
|
||||||
item->setIcon(0, _iconForUrl(url));
|
|
||||||
ui->historyTree->addTopLevelItem(item);
|
|
||||||
|
|
||||||
++counter;
|
|
||||||
if (counter > 200) {
|
|
||||||
QApplication::processEvents();
|
|
||||||
counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!guard) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HistorySideBar::~HistorySideBar()
|
HistorySideBar::~HistorySideBar()
|
||||||
|
|
|
@ -21,15 +21,13 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "qz_namespace.h"
|
#include "qz_namespace.h"
|
||||||
#include "historymodel.h"
|
#include "historyview.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
class HistorySideBar;
|
class HistorySideBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
class QTreeWidgetItem;
|
|
||||||
|
|
||||||
class QupZilla;
|
class QupZilla;
|
||||||
|
|
||||||
class QT_QUPZILLA_EXPORT HistorySideBar : public QWidget
|
class QT_QUPZILLA_EXPORT HistorySideBar : public QWidget
|
||||||
|
@ -41,22 +39,11 @@ public:
|
||||||
~HistorySideBar();
|
~HistorySideBar();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void itemDoubleClicked(QTreeWidgetItem* item);
|
void openLink(const QUrl &url, HistoryView::OpenBehavior openIn);
|
||||||
void contextMenuRequested(const QPoint &position);
|
|
||||||
void loadInNewTab();
|
|
||||||
void itemControlClicked(QTreeWidgetItem* item);
|
|
||||||
void copyAddress();
|
|
||||||
|
|
||||||
void slotRefreshTable();
|
|
||||||
|
|
||||||
void historyEntryAdded(const HistoryEntry &entry);
|
|
||||||
void historyEntryDeleted(const HistoryEntry &entry);
|
|
||||||
void historyEntryEdited(const HistoryEntry &before, const HistoryEntry &after);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::HistorySideBar* ui;
|
Ui::HistorySideBar* ui;
|
||||||
QupZilla* p_QupZilla;
|
QupZilla* p_QupZilla;
|
||||||
HistoryModel* m_historyModel;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HISTORYSIDEBAR_H
|
#endif // HISTORYSIDEBAR_H
|
||||||
|
|
|
@ -34,33 +34,22 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="TreeWidget" name="historyTree">
|
<widget class="HistoryView" name="historyTree">
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::CustomContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="headerHidden">
|
<property name="headerHidden">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="headerDefaultSectionSize">
|
|
||||||
<number>330</number>
|
|
||||||
</attribute>
|
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Title</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>TreeWidget</class>
|
<class>HistoryView</class>
|
||||||
<extends>QTreeWidget</extends>
|
<extends>QTreeView</extends>
|
||||||
<header>treewidget.h</header>
|
<header>historyview.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|
|
@ -162,7 +162,7 @@ void SideBarManager::updateActions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SideBarManager::showSideBar(const QString &id)
|
void SideBarManager::showSideBar(const QString &id, bool toggle)
|
||||||
{
|
{
|
||||||
if (id == "None") {
|
if (id == "None") {
|
||||||
return;
|
return;
|
||||||
|
@ -173,9 +173,14 @@ void SideBarManager::showSideBar(const QString &id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == m_activeBar) {
|
if (id == m_activeBar) {
|
||||||
|
if (!toggle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_sideBar.data()->close();
|
m_sideBar.data()->close();
|
||||||
|
|
||||||
m_activeBar = "None";
|
m_activeBar = "None";
|
||||||
|
|
||||||
|
Settings settings;
|
||||||
|
settings.setValue("Browser-View-Settings/SideBar", m_activeBar);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +204,7 @@ void SideBarManager::showSideBar(const QString &id)
|
||||||
m_activeBar = id;
|
m_activeBar = id;
|
||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.setValue("Browser-View-Settings/SideBar", id);
|
settings.setValue("Browser-View-Settings/SideBar", m_activeBar);
|
||||||
|
|
||||||
updateActions();
|
updateActions();
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
void setSideBarMenu(QMenu* menu);
|
void setSideBarMenu(QMenu* menu);
|
||||||
void refreshMenu();
|
void refreshMenu();
|
||||||
|
|
||||||
void showSideBar(const QString &id);
|
void showSideBar(const QString &id, bool toggle = true);
|
||||||
void sideBarRemoved(const QString &id);
|
void sideBarRemoved(const QString &id);
|
||||||
void closeSideBar();
|
void closeSideBar();
|
||||||
|
|
||||||
|
|
94
src/lib/tools/headerview.cpp
Normal file
94
src/lib/tools/headerview.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/* ============================================================
|
||||||
|
* QupZilla - WebKit based browser
|
||||||
|
* Copyright (C) 2010-2012 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 "headerview.h"
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QContextMenuEvent>
|
||||||
|
|
||||||
|
HeaderView::HeaderView(QAbstractItemView* parent)
|
||||||
|
: QHeaderView(Qt::Horizontal, parent)
|
||||||
|
, m_parent(parent)
|
||||||
|
, m_menu(0)
|
||||||
|
{
|
||||||
|
setMovable(true);
|
||||||
|
setStretchLastSection(true);
|
||||||
|
setDefaultAlignment(Qt::AlignLeft);
|
||||||
|
setMinimumSectionSize(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeaderView::setDefaultSectionSizes(const QList<double> &sizes)
|
||||||
|
{
|
||||||
|
m_sectionSizes = sizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<double> HeaderView::defaultSectionSizes() const
|
||||||
|
{
|
||||||
|
return m_sectionSizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HeaderView::restoreState(const QByteArray &state)
|
||||||
|
{
|
||||||
|
m_resizeOnShow = !QHeaderView::restoreState(state);
|
||||||
|
|
||||||
|
return !m_resizeOnShow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeaderView::showEvent(QShowEvent* event)
|
||||||
|
{
|
||||||
|
if (m_resizeOnShow) {
|
||||||
|
for (int i = 0; i < m_sectionSizes.count(); ++i) {
|
||||||
|
int size = m_parent->width() * m_sectionSizes.at(i);
|
||||||
|
resizeSection(i, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QHeaderView::showEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeaderView::contextMenuEvent(QContextMenuEvent* event)
|
||||||
|
{
|
||||||
|
if (!m_menu) {
|
||||||
|
m_menu = new QMenu(this);
|
||||||
|
|
||||||
|
for (int i = 0; i < count(); ++i) {
|
||||||
|
QAction* act = new QAction(model()->headerData(i, Qt::Horizontal).toString(), m_menu);
|
||||||
|
act->setCheckable(true);
|
||||||
|
act->setData(i);
|
||||||
|
|
||||||
|
connect(act, SIGNAL(triggered()), this, SLOT(toggleSectionVisibility()));
|
||||||
|
m_menu->addAction(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < m_menu->actions().count(); ++i) {
|
||||||
|
QAction* act = m_menu->actions().at(i);
|
||||||
|
act->setEnabled(i > 0);
|
||||||
|
act->setChecked(!isSectionHidden(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_menu->popup(event->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeaderView::toggleSectionVisibility()
|
||||||
|
{
|
||||||
|
if (QAction* act = qobject_cast<QAction*>(sender())) {
|
||||||
|
int index = act->data().toInt();
|
||||||
|
|
||||||
|
setSectionHidden(index, !isSectionHidden(index));
|
||||||
|
}
|
||||||
|
}
|
53
src/lib/tools/headerview.h
Normal file
53
src/lib/tools/headerview.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/* ============================================================
|
||||||
|
* QupZilla - WebKit based browser
|
||||||
|
* Copyright (C) 2010-2012 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 HEADERVIEW_H
|
||||||
|
#define HEADERVIEW_H
|
||||||
|
|
||||||
|
#include <QHeaderView>
|
||||||
|
|
||||||
|
class QContextMenuEvent;
|
||||||
|
|
||||||
|
#include "qz_namespace.h"
|
||||||
|
|
||||||
|
class QT_QUPZILLA_EXPORT HeaderView : public QHeaderView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit HeaderView(QAbstractItemView* parent);
|
||||||
|
|
||||||
|
void setDefaultSectionSizes(const QList<double> &sizes);
|
||||||
|
QList<double> defaultSectionSizes() const;
|
||||||
|
|
||||||
|
bool restoreState(const QByteArray &state);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void toggleSectionVisibility();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void showEvent(QShowEvent* event);
|
||||||
|
void contextMenuEvent(QContextMenuEvent* event);
|
||||||
|
|
||||||
|
QAbstractItemView* m_parent;
|
||||||
|
QMenu* m_menu;
|
||||||
|
|
||||||
|
bool m_resizeOnShow;
|
||||||
|
QList<double> m_sectionSizes;
|
||||||
|
QByteArray m_restoreData;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HEADERVIEW_H
|
|
@ -20,7 +20,7 @@
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "globalfunctions.h"
|
#include "globalfunctions.h"
|
||||||
#include "iconprovider.h"
|
#include "iconprovider.h"
|
||||||
#include "historymodel.h"
|
#include "history.h"
|
||||||
#include "autofillmodel.h"
|
#include "autofillmodel.h"
|
||||||
#include "downloadmanager.h"
|
#include "downloadmanager.h"
|
||||||
#include "sourceviewer.h"
|
#include "sourceviewer.h"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user