Skip to content

Commit 0b65d56

Browse files
committed
Implement HTML bookmark import job for QtWebEngine
1 parent fd0ac56 commit 0b65d56

File tree

2 files changed

+208
-0
lines changed

2 files changed

+208
-0
lines changed

src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp

+183
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "QtWebEngineTransfer.h"
2424
#include "QtWebEngineUrlRequestInterceptor.h"
2525
#include "QtWebEngineWebWidget.h"
26+
#include "../../../../core/BookmarksManager.h"
2627
#include "../../../../core/ContentFiltersManager.h"
2728
#include "../../../../core/HandlersManager.h"
2829
#include "../../../../core/NetworkManagerFactory.h"
@@ -276,6 +277,11 @@ WebWidget* QtWebEngineWebBackend::createWidget(const QVariantMap &parameters, Co
276277
return new QtWebEngineWebWidget(parameters, this, parent);
277278
}
278279

280+
BookmarksImportJob *QtWebEngineWebBackend::createBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed)
281+
{
282+
return new QtWebEngineBookmarksImportJob(folder, path, areDuplicatesAllowed, this);
283+
}
284+
279285
QString QtWebEngineWebBackend::getName() const
280286
{
281287
return QLatin1String("qtwebengine");
@@ -344,4 +350,181 @@ WebBackend::BackendCapabilities QtWebEngineWebBackend::getCapabilities() const
344350
return (UserScriptsCapability | GlobalCookiesPolicyCapability | GlobalContentFilteringCapability | GlobalDoNotTrackCapability | GlobalProxyCapability | GlobalReferrerCapability | GlobalUserAgentCapability);
345351
}
346352

353+
QtWebEngineBookmarksImportJob::QtWebEngineBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent) : BookmarksImportJob(folder, areDuplicatesAllowed, parent),
354+
m_path(path),
355+
m_currentAmount(0),
356+
m_totalAmount(-1),
357+
m_isRunning(false)
358+
{
359+
}
360+
361+
void QtWebEngineBookmarksImportJob::start()
362+
{
363+
QFile file(m_path);
364+
365+
if (!file.open(QIODevice::ReadOnly))
366+
{
367+
emit importFinished(Importer::BookmarksImport, Importer::FailedImport, 0);
368+
emit jobFinished(false);
369+
370+
deleteLater();
371+
372+
return;
373+
}
374+
375+
m_isRunning = true;
376+
377+
QEventLoop loop;
378+
QWebEnginePage page;
379+
380+
connect(&page, &QWebEnginePage::loadFinished,
381+
[this, &page, &loop](bool ok) {
382+
383+
if (!ok)
384+
{
385+
m_totalAmount = 0;
386+
loop.exit();
387+
return;
388+
}
389+
390+
QVariant jsResult;
391+
392+
jsResult = execJavascript(page, "document.getElementsByTagName('DT').length");
393+
m_totalAmount = jsResult.toInt(&ok);
394+
if (!ok)
395+
{
396+
m_totalAmount = 0;
397+
loop.exit();
398+
return;
399+
}
400+
401+
emit importStarted(Importer::BookmarksImport, m_totalAmount);
402+
403+
jsResult = execJavascript(page, "document.querySelectorAll('a,hr').length");
404+
const int numLinks = jsResult.toInt(&ok);
405+
406+
BookmarksManager::getModel()->beginImport(getImportFolder(), numLinks, numLinks);
407+
408+
jsResult = execJavascript(page, "var nodes=[];document.querySelectorAll('h3,a,hr').forEach(function(node){if(node.tagName.toUpperCase()=='A'){nodes.push({'type':'anchor','title':node.innerHTML,'url':node.getAttribute('href'),'add_date':node.getAttribute('add_date'),'last_modified':node.getAttribute('last_modified')})}else if(node.tagName.toUpperCase()=='HR'){nodes.push({'type':'separator'})}else if(node.tagName.toUpperCase()=='H3'){sibling=node.parentNode.querySelector('dl');numChildren=sibling.querySelectorAll(':scope > dt').length;nodes.push({'type':'folder','title':node.innerHTML,'numChildren':numChildren,'add_date':node.getAttribute('add_date'),'last_modified':node.getAttribute('last_modified')})}});nodes");
409+
QList<QVariant> items = jsResult.toList();
410+
411+
processBookmarkItems(items, getImportFolder(), -1);
412+
BookmarksManager::getModel()->endImport();
413+
414+
loop.exit();
415+
});
416+
417+
page.setHtml(QString::fromLatin1(file.readAll()));
418+
loop.exec();
419+
420+
emit importFinished(Importer::BookmarksImport, Importer::SuccessfullImport, m_totalAmount);
421+
422+
file.close();
423+
424+
m_isRunning = false;
425+
426+
deleteLater();
427+
}
428+
429+
QVariant QtWebEngineBookmarksImportJob::execJavascript(QWebEnginePage &page, const QString &script)
430+
{
431+
QVariant jsResult;
432+
QEventLoop loop;
433+
434+
page.runJavaScript(script, [&loop, &jsResult](const QVariant &result) {
435+
jsResult = result;
436+
loop.exit(0);
437+
});
438+
loop.exec();
439+
440+
return jsResult;
441+
}
442+
443+
void QtWebEngineBookmarksImportJob::processBookmarkItems(QList<QVariant> &items, BookmarksModel::Bookmark *importFolder, int numChildren)
444+
{
445+
while (numChildren != 0 && m_currentAmount < m_totalAmount)
446+
{
447+
const QVariant &item = items.at(m_currentAmount++);
448+
-- numChildren;
449+
450+
const QMap<QString, QVariant> itemMap = item.toMap();
451+
const QString typeString = itemMap["type"].toString();
452+
const QString title = itemMap["title"].toString();
453+
454+
BookmarksModel::BookmarkType type(BookmarksModel::UnknownBookmark);
455+
QMap<int, QVariant> metaData({{BookmarksModel::TitleRole, title}});
456+
457+
if (typeString == "folder" || typeString == "anchor")
458+
{
459+
const QDateTime addDate(getDateTime(itemMap["add_date"]));
460+
const QDateTime lastModified(getDateTime(itemMap["last_modified"]));
461+
462+
if (addDate.isValid())
463+
{
464+
metaData[BookmarksModel::TimeAddedRole] = addDate;
465+
}
466+
467+
if (lastModified.isValid())
468+
{
469+
metaData[BookmarksModel::TimeAddedRole] = lastModified;
470+
}
471+
}
472+
473+
if (typeString == "folder")
474+
{
475+
processBookmarkItems(items,
476+
BookmarksManager::addBookmark(BookmarksModel::FolderBookmark, metaData, importFolder),
477+
itemMap["numChildren"].toInt());
478+
}
479+
else
480+
{
481+
if (typeString == "anchor")
482+
{
483+
type = BookmarksModel::UrlBookmark;
484+
const QString url = itemMap["url"].toString();
485+
486+
if (!areDuplicatesAllowed() && BookmarksManager::hasBookmark(url))
487+
{
488+
continue;
489+
}
490+
491+
metaData[BookmarksModel::UrlRole] = url;
492+
}
493+
else if (typeString == "separator")
494+
{
495+
type = BookmarksModel::SeparatorBookmark;
496+
}
497+
498+
if (type != BookmarksModel::UnknownBookmark)
499+
{
500+
BookmarksManager::addBookmark(type, metaData, importFolder);
501+
}
502+
}
503+
504+
emit importProgress(Importer::BookmarksImport, m_totalAmount, m_currentAmount);
505+
}
506+
}
507+
508+
void QtWebEngineBookmarksImportJob::cancel()
509+
{
510+
}
511+
512+
QDateTime QtWebEngineBookmarksImportJob::getDateTime(const QVariant &attribute)
513+
{
514+
#if QT_VERSION < 0x050800
515+
const uint seconds(attribute.toUInt());
516+
517+
return ((seconds > 0) ? QDateTime::fromTime_t(seconds) : QDateTime());
518+
#else
519+
const qint64 seconds(attribute.toLongLong());
520+
521+
return ((seconds != 0) ? QDateTime::fromSecsSinceEpoch(seconds) : QDateTime());
522+
#endif
523+
}
524+
525+
bool QtWebEngineBookmarksImportJob::isRunning() const
526+
{
527+
return m_isRunning;
528+
}
529+
347530
}

src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.h

+25
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class QtWebEngineWebBackend final : public WebBackend
4545
explicit QtWebEngineWebBackend(QObject *parent = nullptr);
4646

4747
WebWidget* createWidget(const QVariantMap &parameters, ContentsWidget *parent = nullptr) override;
48+
BookmarksImportJob* createBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed) override;
4849
QString getName() const override;
4950
QString getTitle() const override;
5051
QString getDescription() const override;
@@ -80,6 +81,30 @@ protected slots:
8081
friend class QtWebEnginePage;
8182
};
8283

84+
class QtWebEngineBookmarksImportJob final : public BookmarksImportJob
85+
{
86+
Q_OBJECT
87+
88+
public:
89+
explicit QtWebEngineBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent = nullptr);
90+
bool isRunning() const override;
91+
92+
public slots:
93+
void start() override;
94+
void cancel() override;
95+
96+
protected:
97+
QVariant execJavascript(QWebEnginePage &page, const QString &script);
98+
void processBookmarkItems(QList<QVariant> &items, BookmarksModel::Bookmark *importFolder, int numChildren);
99+
static QDateTime getDateTime(const QVariant &attribute);
100+
101+
private:
102+
QString m_path;
103+
int m_currentAmount;
104+
int m_totalAmount;
105+
bool m_isRunning;
106+
};
107+
83108
}
84109

85110
#endif

0 commit comments

Comments
 (0)