1
mirror of https://invent.kde.org/network/falkon.git synced 2024-12-20 10:46:35 +01:00

Various enhancements in Bookmark Importing.

- when importing from Html file, also bookmark folders are imported
- bookmark tree now shows folder structure
- fixed importing from UTF8 files
- loading icons in own thread = dialog won't freeze anymore
This commit is contained in:
nowrep 2012-03-06 15:28:52 +01:00
parent 63ed2573f4
commit eb7de9a104
13 changed files with 326 additions and 105 deletions

View File

@ -63,6 +63,16 @@ void BookmarksModel::setShowingOnlyIconsInToolbar(bool state)
m_showOnlyIconsInToolbar = state;
}
bool BookmarksModel::isFolder(const QString &name)
{
QSqlQuery query;
query.prepare("SELECT name FROM folders WHERE name = ?");
query.bindValue(0, name);
query.exec();
return query.next();
}
void BookmarksModel::setLastFolder(const QString &folder)
{
Settings settings;
@ -154,6 +164,10 @@ bool BookmarksModel::saveBookmark(const QUrl &url, const QString &title, const Q
image = QWebSettings::webGraphic(QWebSettings::DefaultFrameIconGraphic).toImage();
}
if (!isFolder(folder)) {
createFolder(folder);
}
QSqlQuery query;
query.prepare("INSERT INTO bookmarks (url, title, folder, icon) VALUES (?,?,?,?)");
query.bindValue(0, url.toString());
@ -292,14 +306,11 @@ bool BookmarksModel::editBookmark(int id, const QString &title, const QUrl &url,
bool BookmarksModel::createFolder(const QString &name)
{
QSqlQuery query;
query.prepare("SELECT name FROM folders WHERE name = ?");
query.bindValue(0, name);
query.exec();
if (query.next()) {
if (isFolder(name)) {
return false;
}
QSqlQuery query;
query.prepare("INSERT INTO folders (name, subfolder) VALUES (?, 'no')");
query.bindValue(0, name);
if (!query.exec()) {
@ -397,14 +408,11 @@ QList<Bookmark> BookmarksModel::folderBookmarks(const QString &name)
bool BookmarksModel::createSubfolder(const QString &name)
{
QSqlQuery query;
query.prepare("SELECT name FROM folders WHERE name = ?");
query.bindValue(0, name);
query.exec();
if (query.next()) {
if (isFolder(name)) {
return false;
}
QSqlQuery query;
query.prepare("INSERT INTO folders (name, subfolder) VALUES (?, 'yes')");
query.bindValue(0, name);
if (!query.exec()) {

View File

@ -68,6 +68,7 @@ public:
bool isShowingOnlyIconsInToolbar() { return m_showOnlyIconsInToolbar; }
void setShowingOnlyIconsInToolbar(bool state);
bool isFolder(const QString &name);
QString lastFolder() { return m_lastFolder; }
void setLastFolder(const QString &folder);

View File

@ -22,18 +22,21 @@
#include "operaimporter.h"
#include "htmlimporter.h"
#include "mainapplication.h"
#include "iconfetcher.h"
#include "bookmarksimporticonfetcher.h"
#include "iconprovider.h"
#include "networkmanager.h"
#include <QWebSettings>
#include <QMessageBox>
#include <QFileDialog>
#include <QThread>
BookmarksImportDialog::BookmarksImportDialog(QWidget* parent)
: QDialog(parent)
, ui(new Ui::BookmarksImportDialog)
, m_currentPage(0)
, m_fetcher(0)
, m_fetcherThread(0)
{
setAttribute(Qt::WA_DeleteOnClose);
ui->setupUi(this);
@ -96,28 +99,53 @@ void BookmarksImportDialog::startFetchingIcons()
ui->progressBar->setValue(0);
ui->progressBar->setMaximum(m_exportedBookmarks.count());
int i = 0;
m_fetcherThread = new QThread();
m_fetcher = new BookmarksImportIconFetcher();
m_fetcher->moveToThread(m_fetcherThread);
QIcon defaultIcon = QIcon(QWebSettings::globalSettings()->webGraphic(QWebSettings::DefaultFrameIconGraphic));
QIcon folderIcon = style()->standardIcon(QStyle::SP_DirIcon);
QHash<QString, QTreeWidgetItem*> hash;
foreach(const Bookmark & b, m_exportedBookmarks) {
QTreeWidgetItem* item = new QTreeWidgetItem();
QTreeWidgetItem* item;
QTreeWidgetItem* findParent = hash[b.folder];
if (findParent) {
item = new QTreeWidgetItem(findParent);
}
else {
QTreeWidgetItem* newParent = new QTreeWidgetItem(ui->treeWidget);
newParent->setText(0, b.folder);
newParent->setIcon(0, folderIcon);
ui->treeWidget->addTopLevelItem(newParent);
hash[b.folder] = newParent;
item = new QTreeWidgetItem(newParent);
}
QVariant bookmarkVariant = qVariantFromValue(b);
item->setText(0, b.title);
item->setIcon(0, QWebSettings::globalSettings()->webGraphic(QWebSettings::DefaultFrameIconGraphic));
if (b.image.isNull()) {
item->setIcon(0, defaultIcon);
}
else {
item->setIcon(0, QIcon(QPixmap::fromImage(b.image)));
}
item->setText(1, b.url.toString());
item->setWhatsThis(0, QString::number(i));
item->setData(0, Qt::UserRole + 10, bookmarkVariant);
ui->treeWidget->addTopLevelItem(item);
i++;
IconFetcher* fetcher = new IconFetcher(this);
fetcher->setNetworkAccessManager(mApp->networkManager());
connect(fetcher, SIGNAL(finished()), this, SLOT(loadFinished()));
connect(fetcher, SIGNAL(iconFetched(QIcon)), this, SLOT(iconFetched(QIcon)));
fetcher->fetchIcon(b.url);
QPair<IconFetcher*, QUrl> pair;
pair.first = fetcher;
pair.second = b.url;
m_fetchers.append(pair);
m_fetcher->addEntry(b.url, item);
}
ui->treeWidget->expandAll();
connect(m_fetcher, SIGNAL(iconFetched(QImage, QTreeWidgetItem*)), this, SLOT(iconFetched(QImage, QTreeWidgetItem*)));
connect(m_fetcher, SIGNAL(oneFinished()), this, SLOT(loadFinished()));
m_fetcherThread->start();
m_fetcher->startFetching();
}
void BookmarksImportDialog::stopDownloading()
@ -139,43 +167,15 @@ void BookmarksImportDialog::loadFinished()
}
}
void BookmarksImportDialog::iconFetched(const QIcon &icon)
void BookmarksImportDialog::iconFetched(const QImage &image, QTreeWidgetItem* item)
{
IconFetcher* fetcher = qobject_cast<IconFetcher*>(sender());
if (!fetcher) {
return;
}
item->setIcon(0, QIcon(QPixmap::fromImage(image)));
QUrl url;
for (int i = 0; i < m_fetchers.count(); i++) {
QPair<IconFetcher*, QUrl> pair = m_fetchers.at(i);
if (pair.first == fetcher) {
url = pair.second;
break;
}
}
Bookmark b = item->data(0, Qt::UserRole + 10).value<Bookmark>();
if (url.isEmpty()) {
return;
}
QList<QTreeWidgetItem*> items = ui->treeWidget->findItems(url.toString(), Qt::MatchExactly, 1);
if (items.count() == 0) {
return;
}
foreach(QTreeWidgetItem * item, items) {
item->setIcon(0, icon);
foreach(Bookmark b, m_exportedBookmarks) {
if (b.url == url) {
m_exportedBookmarks.removeOne(b);
b.image = icon.pixmap(16, 16).toImage();
b.image = image;
m_exportedBookmarks.append(b);
break;
}
}
}
}
bool BookmarksImportDialog::exportedOK()
@ -263,10 +263,6 @@ void BookmarksImportDialog::addExportedBookmarks()
BookmarksModel* model = mApp->bookmarksModel();
if (m_exportedBookmarks.count() > 0) {
model->createFolder(m_exportedBookmarks.at(0).folder);
}
foreach(const Bookmark & b, m_exportedBookmarks) {
model->saveBookmark(b.url, b.title, IconProvider::iconFromImage(b.image), b.folder);
}
@ -349,13 +345,13 @@ void BookmarksImportDialog::setupBrowser(Browser browser)
BookmarksImportDialog::~BookmarksImportDialog()
{
if (m_fetchers.count() > 0) {
for (int i = 0; i < m_fetchers.count(); i++) {
tr("");
IconFetcher* fetcher = m_fetchers.at(i).first;
fetcher->deleteLater();
}
}
delete ui;
if (m_fetcherThread) {
m_fetcherThread->exit();
m_fetcherThread->wait();
m_fetcherThread->deleteLater();
m_fetcher->deleteLater();
}
}

View File

@ -29,7 +29,11 @@ namespace Ui
class BookmarksImportDialog;
}
class IconFetcher;
class QTreeWidgetItem;
class QThread;
class BookmarksImportIconFetcher;
class QT_QUPZILLA_EXPORT BookmarksImportDialog : public QDialog
{
Q_OBJECT
@ -43,7 +47,7 @@ private slots:
void setFile();
void stopDownloading();
void iconFetched(const QIcon &icon);
void iconFetched(const QImage &image, QTreeWidgetItem* item);
void loadFinished();
private:
@ -68,7 +72,8 @@ private:
QList<BookmarksModel::Bookmark> m_exportedBookmarks;
QList<QPair<IconFetcher*, QUrl> > m_fetchers;
BookmarksImportIconFetcher* m_fetcher;
QThread* m_fetcherThread;
};
#endif // BOOKMARKSIMPORTDIALOG_H

View File

@ -0,0 +1,84 @@
/* ============================================================
* 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 "bookmarksimporticonfetcher.h"
#include "iconfetcher.h"
#include <QTimer>
#include <QNetworkAccessManager>
BookmarksImportIconFetcher::BookmarksImportIconFetcher(QObject* parent)
: QObject(parent)
{
}
void BookmarksImportIconFetcher::addEntry(const QUrl &url, QTreeWidgetItem* item)
{
Pair pair;
pair.url = url;
pair.item = item;
m_pairs.append(pair);
}
void BookmarksImportIconFetcher::startFetching()
{
QTimer::singleShot(0, this, SLOT(slotStartFetching()));
}
void BookmarksImportIconFetcher::slotIconFetched(const QImage &image)
{
IconFetcher* fetcher = qobject_cast<IconFetcher*>(sender());
if (!fetcher) {
return;
}
QTreeWidgetItem* itemPointer = static_cast<QTreeWidgetItem*>(fetcher->data().value<void*>());
emit iconFetched(image, itemPointer);
}
void BookmarksImportIconFetcher::slotFetcherFinished()
{
IconFetcher* fetcher = qobject_cast<IconFetcher*>(sender());
if (!fetcher) {
return;
}
m_fetchers.removeOne(fetcher);
emit oneFinished();
}
void BookmarksImportIconFetcher::slotStartFetching()
{
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
foreach(const Pair & pair, m_pairs) {
QVariant itemPointer = qVariantFromValue((void*) pair.item);
IconFetcher* fetcher = new IconFetcher(this);
fetcher->setNetworkAccessManager(manager);
fetcher->setData(itemPointer);
fetcher->fetchIcon(pair.url);
connect(fetcher, SIGNAL(iconFetched(QImage)), this, SLOT(slotIconFetched(QImage)));
connect(fetcher, SIGNAL(finished()), this, SLOT(slotFetcherFinished()));
m_fetchers.append(fetcher);
}
}

View File

@ -0,0 +1,63 @@
/* ============================================================
* 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 BOOKMARKSIMPORTICONFETCHER_H
#define BOOKMARKSIMPORTICONFETCHER_H
#include <QObject>
#include <QUrl>
#include <QList>
#include "qz_namespace.h"
class QNetworkAccessManager;
class QTreeWidgetItem;
class QImage;
class IconFetcher;
class QT_QUPZILLA_EXPORT BookmarksImportIconFetcher : public QObject
{
Q_OBJECT
public:
struct Pair {
QUrl url;
QTreeWidgetItem* item;
};
explicit BookmarksImportIconFetcher(QObject* parent = 0);
void addEntry(const QUrl &url, QTreeWidgetItem* item);
void startFetching();
signals:
void iconFetched(const QImage &image, QTreeWidgetItem* item);
void oneFinished();
private slots:
void slotStartFetching();
void slotIconFetched(const QImage &image);
void slotFetcherFinished();
private:
QList<Pair> m_pairs;
QList<IconFetcher*> m_fetchers;
};
#endif // BOOKMARKSIMPORTICONFETCHER_H

View File

@ -53,7 +53,7 @@ QList<BookmarksModel::Bookmark> ChromeImporter::exportBookmarks()
{
QList<BookmarksModel::Bookmark> list;
QString bookmarks = m_file.readAll();
QString bookmarks = QString::fromUtf8(m_file.readAll());
m_file.close();
QStringList parsedBookmarks;

View File

@ -45,41 +45,92 @@ bool HtmlImporter::openFile()
return true;
}
int qzMin(int a, int b)
{
if (a > -1 && b > -1) {
return qMin(a, b);
}
if (a > -1) {
return a;
}
else {
return b;
}
}
QList<BookmarksModel::Bookmark> HtmlImporter::exportBookmarks()
{
QList<BookmarksModel::Bookmark> list;
QString bookmarks = m_file.readAll();
QString bookmarks = QString::fromUtf8(m_file.readAll());
m_file.close();
QRegExp rx("<a (.*)</a>", Qt::CaseInsensitive);
bookmarks = bookmarks.mid(0, bookmarks.lastIndexOf("</DL><p>"));
int start = bookmarks.indexOf("<DL><p>", Qt::CaseInsensitive);
QStringList folders("Html Import");
while (start > 0) {
QString string = bookmarks.mid(start);
int posOfFolder = string.indexOf("<DT><H3", Qt::CaseInsensitive);
int posOfEndFolder = string.indexOf("</DL><p>", Qt::CaseInsensitive);
int posOfLink = string.indexOf("<DT><A", Qt::CaseInsensitive);
int nearest = qzMin(posOfLink, qzMin(posOfFolder, posOfEndFolder));
if (nearest == -1) {
break;
}
if (nearest == posOfFolder) {
// Next is folder
QRegExp rx("<DT><H3(.*)>(.*)</H3>", Qt::CaseInsensitive);
rx.setMinimal(true);
rx.indexIn(string);
int pos = 0;
while ((pos = rx.indexIn(bookmarks, pos)) != -1) {
QString string = rx.cap(0);
pos += rx.matchedLength();
// QString arguments = rx.cap(1);
QString folderName = rx.cap(2);
QRegExp rx2(">(.*)</a>", Qt::CaseInsensitive);
folders.append(folderName);
start += posOfFolder + rx.cap(0).size();
}
else if (nearest == posOfEndFolder) {
// Next is end of folder
folders.removeLast();
start += posOfEndFolder + 8;
}
else {
// Next is link
QRegExp rx("<DT><A(.*)>(.*)</A>", Qt::CaseInsensitive);
rx.setMinimal(true);
rx.indexIn(string);
QString arguments = rx.cap(1);
QString linkName = rx.cap(2);
QRegExp rx2("HREF=\"(.*)\"", Qt::CaseInsensitive);
rx2.setMinimal(true);
rx2.indexIn(string);
QString name = rx2.cap(1);
rx2.indexIn(arguments);
rx2.setPattern("href=\"(.*)\"");
rx2.indexIn(string);
QUrl url = QUrl::fromEncoded(rx2.cap(1).toUtf8());
if (name.isEmpty() || url.isEmpty() || url.scheme() == "place" || url.scheme() == "about") {
start += posOfLink + rx.cap(0).size();
if (linkName.isEmpty() || url.isEmpty() || url.scheme() == "place" || url.scheme() == "about") {
continue;
}
BookmarksModel::Bookmark b;
b.folder = "Html Import";
b.title = name;
b.folder = folders.last();
b.title = linkName;
b.url = url;
list.append(b);
}
}
return list;
}

View File

@ -47,7 +47,7 @@ QList<BookmarksModel::Bookmark> OperaImporter::exportBookmarks()
{
QList<BookmarksModel::Bookmark> list;
QString bookmarks = m_file.readAll();
QString bookmarks = QString::fromUtf8(m_file.readAll());
m_file.close();
QRegExp rx("#URL(.*)CREATED", Qt::CaseSensitive);

View File

@ -164,7 +164,8 @@ SOURCES += \
webview/webviewsettings.cpp \
preferences/pluginlistdelegate.cpp \
popupwindow/popupstatusbarmessage.cpp \
other/licenseviewer.cpp
other/licenseviewer.cpp \
bookmarksimport/bookmarksimporticonfetcher.cpp
HEADERS += \
3rdparty/qtwin.h \
@ -300,7 +301,8 @@ HEADERS += \
webview/webviewsettings.h \
preferences/pluginlistdelegate.h \
popupwindow/popupstatusbarmessage.h \
other/licenseviewer.h
other/licenseviewer.h \
bookmarksimport/bookmarksimporticonfetcher.h
FORMS += \
preferences/autofillmanager.ui \

View File

@ -76,7 +76,7 @@ QSize PluginListDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo
{
const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0) + 1;
QSize size = QItemDelegate::sizeHint(option, index);
QSize size;
size.setWidth(m_listWidget->width() - 10);
// ( height of font * 3 = 3 lines ) + ( text margins ) + ( 2 free lines = every line is 3px )

View File

@ -33,6 +33,8 @@ void IconFetcher::fetchIcon(const QUrl &url)
FollowRedirectReply* reply = new FollowRedirectReply(url, m_manager);
connect(reply, SIGNAL(finished()), this, SLOT(pageDownloaded()));
m_url = url;
}
void IconFetcher::pageDownloaded()
@ -95,9 +97,8 @@ void IconFetcher::iconDownloaded()
if (!response.isEmpty()) {
QImage image;
image.loadFromData(response);
QIcon icon = QIcon(QPixmap::fromImage(image));
if (!icon.isNull()) {
emit iconFetched(icon);
if (!image.isNull()) {
emit iconFetched(image);
}
}

View File

@ -22,6 +22,8 @@
#include <QObject>
#include <QIcon>
#include <QVariant>
#include <QUrl>
class QNetworkAccessManager;
class QUrl;
@ -36,8 +38,13 @@ public:
void setNetworkAccessManager(QNetworkAccessManager* manager) { m_manager = manager; }
void fetchIcon(const QUrl &url);
void setData(const QVariant &data) { m_data = data; }
QVariant data() { return m_data; }
QUrl url() { return m_url; }
signals:
void iconFetched(QIcon);
void iconFetched(QImage);
void finished();
public slots:
@ -49,6 +56,9 @@ private slots:
private:
QNetworkAccessManager* m_manager;
QVariant m_data;
QUrl m_url;
};
#endif // ICONFETCHER_H