Advance Wayland and KDE package bring-up

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-14 10:51:06 +01:00
parent 51f3c21121
commit cf12defd28
15214 changed files with 20594243 additions and 269 deletions
@@ -0,0 +1,107 @@
add_subdirectory(widgets)
add_library(KF6Bookmarks)
add_library(KF6::Bookmarks ALIAS KF6Bookmarks)
set_target_properties(KF6Bookmarks PROPERTIES
VERSION ${KBOOKMARKS_VERSION}
SOVERSION ${KBOOKMARKS_SOVERSION}
EXPORT_NAME Bookmarks
)
ecm_create_qm_loader(KF6Bookmarks kbookmarks6_qt)
target_sources(KF6Bookmarks PRIVATE
kbookmarkaction.cpp
kbookmarkaction.h
kbookmarkactioninterface.cpp
kbookmarkactioninterface.h
kbookmark.cpp
kbookmark.h
kbookmarkmanager.cpp
kbookmarkmanager.h
kbookmarkowner.cpp
kbookmarkowner.h
keditbookmarks_p.h
keditbookmarks.cpp
kbookmarksettings.cpp
)
ecm_qt_declare_logging_category(KF6Bookmarks
HEADER kbookmarks_debug.h
IDENTIFIER KBOOKMARKS_LOG
CATEGORY_NAME kf.bookmarks
OLD_CATEGORY_NAMES kf5.kbookmarks
DESCRIPTION "KBookmarks"
EXPORT KBOOKMARKS
)
ecm_generate_export_header(KF6Bookmarks
BASE_NAME KBookmarks
GROUP_BASE_NAME KF
VERSION ${KF_VERSION}
USE_VERSION_HEADER
DEPRECATED_BASE_VERSION 0
DEPRECATION_VERSIONS
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
)
target_include_directories(KF6Bookmarks INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KBookmarks>")
target_link_libraries(KF6Bookmarks PUBLIC Qt6::Gui Qt6::Xml)
target_link_libraries(KF6Bookmarks PRIVATE
KF6::CoreAddons # for KStringHandler
KF6::ConfigCore # for KConfigGroup
)
ecm_generate_headers(KBookmarks_HEADERS
HEADER_NAMES
KBookmark
KBookmarkAction
KBookmarkActionInterface
KBookmarkManager
KBookmarkOwner
REQUIRED_HEADERS KBookmarks_HEADERS
)
install(TARGETS KF6Bookmarks EXPORT KF6BookmarksTargets ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/kbookmarks_export.h
${KBookmarks_HEADERS}
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KBookmarks COMPONENT Devel
)
ecm_qt_install_logging_categories(
EXPORT KBOOKMARKS
FILE kbookmarks.categories
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
)
if(BUILD_QCH)
ecm_add_qch(
KF6Bookmarks_QCH
NAME KBookmarks
BASE_NAME KF6Bookmarks
VERSION ${KF_VERSION}
ORG_DOMAIN org.kde
SOURCES # using only public headers, to cover only public API
${KBookmarks_HEADERS}
MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md"
LINK_QCHS
Qt6Widgets_QCH
Qt6Xml_QCH
KF6WidgetsAddons_QCH
INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}
BLANK_MACROS
KBOOKMARKS_EXPORT
KBOOKMARKS_DEPRECATED
KBOOKMARKS_DEPRECATED_EXPORT
"KBOOKMARKS_DEPRECATED_VERSION(x, y, t)"
TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
COMPONENT Devel
)
endif()
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
# Extract strings from all source files.
# EXTRACT_TR_STRINGS extracts strings with lupdate and convert them to .pot with
# lconvert.
$EXTRACT_TR_STRINGS `find . -name \*.cpp -o -name \*.h -o -name \*.ui -o -name \*.qml` -o $podir/kbookmarks6_qt.pot
@@ -0,0 +1,725 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
SPDX-FileCopyrightText: 2003 Alexander Kellett <lypanov@kde.org>
SPDX-FileCopyrightText: 2008 Norbert Frese <nf2@scheinwelt.at>
SPDX-License-Identifier: LGPL-2.0-only
*/
#include "kbookmark.h"
#include <KStringHandler>
#include <kurlmimedata.h>
#include <QCoreApplication>
#include <QMimeDatabase>
#include <QStack>
#include <QDateTime>
#include <QMimeData>
namespace
{
namespace Strings
{
QString metaDataKDEOwner()
{
return QStringLiteral("http://www.kde.org");
}
QString metaDataFreedesktopOwner()
{
return QStringLiteral("http://freedesktop.org");
}
QString metaDataMimeOwner()
{
return QStringLiteral("http://www.freedesktop.org/standards/shared-mime-info");
}
QString xbelMimeType()
{
return QStringLiteral("application/x-xbel");
}
}
}
////// utility functions
static QDomNode cd(QDomNode node, const QString &name, bool create)
{
QDomNode subnode = node.namedItem(name);
if (create && subnode.isNull()) {
subnode = node.ownerDocument().createElement(name);
node.appendChild(subnode);
}
return subnode;
}
static QDomNode cd_or_create(const QDomNode &node, const QString &name)
{
return cd(node, name, true);
}
static QDomText get_or_create_text(QDomNode node)
{
QDomNode subnode = node.firstChild();
if (subnode.isNull()) {
subnode = node.ownerDocument().createTextNode(QLatin1String(""));
node.appendChild(subnode);
}
return subnode.toText();
}
static QDomNode findMetadata(const QString &forOwner, QDomNode &parent, bool create)
{
const bool forOwnerIsKDE = (forOwner == Strings::metaDataKDEOwner());
QDomElement metadataElement;
for (QDomNode _node = parent.firstChild(); !_node.isNull(); _node = _node.nextSibling()) {
QDomElement elem = _node.toElement();
if (!elem.isNull() && elem.tagName() == QLatin1String("metadata")) {
const QString owner = elem.attribute(QStringLiteral("owner"));
if (owner == forOwner) {
return elem;
}
if (owner.isEmpty() && forOwnerIsKDE) {
metadataElement = elem;
}
}
}
if (create && metadataElement.isNull()) {
metadataElement = parent.ownerDocument().createElement(QStringLiteral("metadata"));
parent.appendChild(metadataElement);
metadataElement.setAttribute(QStringLiteral("owner"), forOwner);
} else if (!metadataElement.isNull() && forOwnerIsKDE) {
// i'm not sure if this is good, we shouldn't take over foreign metadata
metadataElement.setAttribute(QStringLiteral("owner"), Strings::metaDataKDEOwner());
}
return metadataElement;
}
//////
KBookmarkGroup::KBookmarkGroup()
: KBookmark(QDomElement())
{
}
KBookmarkGroup::KBookmarkGroup(const QDomElement &elem)
: KBookmark(elem)
{
}
bool KBookmarkGroup::isOpen() const
{
return element.attribute(QStringLiteral("folded")) == QLatin1String("no"); // default is: folded
}
KBookmark KBookmarkGroup::first() const
{
return KBookmark(nextKnownTag(element.firstChildElement(), true));
}
KBookmark KBookmarkGroup::previous(const KBookmark &current) const
{
return KBookmark(nextKnownTag(current.element.previousSiblingElement(), false));
}
KBookmark KBookmarkGroup::next(const KBookmark &current) const
{
return KBookmark(nextKnownTag(current.element.nextSiblingElement(), true));
}
int KBookmarkGroup::indexOf(const KBookmark &child) const
{
int counter = 0;
for (KBookmark bk = first(); !bk.isNull(); bk = next(bk), ++counter) {
if (bk.element == child.element) {
return counter;
}
}
return -1;
}
QDomElement KBookmarkGroup::nextKnownTag(const QDomElement &start, bool goNext) const
{
for (QDomElement elem = start; !elem.isNull();) {
QString tag = elem.tagName();
if (tag == QLatin1String("folder") || tag == QLatin1String("bookmark") || tag == QLatin1String("separator")) {
return elem;
}
if (goNext) {
elem = elem.nextSiblingElement();
} else {
elem = elem.previousSiblingElement();
}
}
return QDomElement();
}
KBookmarkGroup KBookmarkGroup::createNewFolder(const QString &text)
{
if (isNull()) {
return KBookmarkGroup();
}
QDomDocument doc = element.ownerDocument();
QDomElement groupElem = doc.createElement(QStringLiteral("folder"));
element.appendChild(groupElem);
QDomElement textElem = doc.createElement(QStringLiteral("title"));
groupElem.appendChild(textElem);
textElem.appendChild(doc.createTextNode(text));
return KBookmarkGroup(groupElem);
}
KBookmark KBookmarkGroup::createNewSeparator()
{
if (isNull()) {
return KBookmark();
}
QDomDocument doc = element.ownerDocument();
Q_ASSERT(!doc.isNull());
QDomElement sepElem = doc.createElement(QStringLiteral("separator"));
element.appendChild(sepElem);
return KBookmark(sepElem);
}
bool KBookmarkGroup::moveBookmark(const KBookmark &item, const KBookmark &after)
{
QDomNode n;
if (!after.isNull()) {
n = element.insertAfter(item.element, after.element);
} else { // first child
if (element.firstChild().isNull()) { // Empty element -> set as real first child
n = element.insertBefore(item.element, QDomElement());
}
// we have to skip everything up to the first valid child
QDomElement firstChild = nextKnownTag(element.firstChild().toElement(), true);
if (!firstChild.isNull()) {
if (firstChild == item.element) { // item is already the first child, done
return true;
}
n = element.insertBefore(item.element, firstChild);
} else {
// No real first child -> append after the <title> etc.
n = element.appendChild(item.element);
}
}
return (!n.isNull());
}
KBookmark KBookmarkGroup::addBookmark(const KBookmark &bm)
{
element.appendChild(bm.internalElement());
return bm;
}
KBookmark KBookmarkGroup::addBookmark(const QString &text, const QUrl &url, const QString &icon)
{
if (isNull()) {
return KBookmark();
}
QDomDocument doc = element.ownerDocument();
QDomElement elem = doc.createElement(QStringLiteral("bookmark"));
elem.setAttribute(QStringLiteral("href"), url.toString(QUrl::FullyEncoded));
QDomElement textElem = doc.createElement(QStringLiteral("title"));
elem.appendChild(textElem);
textElem.appendChild(doc.createTextNode(text));
KBookmark newBookmark = addBookmark(KBookmark(elem));
// as icons are moved to metadata, we have to use the KBookmark API for this
newBookmark.setIcon(icon);
return newBookmark;
}
void KBookmarkGroup::deleteBookmark(const KBookmark &bk)
{
element.removeChild(bk.element);
}
bool KBookmarkGroup::isToolbarGroup() const
{
return (element.attribute(QStringLiteral("toolbar")) == QLatin1String("yes"));
}
QDomElement KBookmarkGroup::findToolbar() const
{
if (element.attribute(QStringLiteral("toolbar")) == QLatin1String("yes")) {
return element;
}
for (QDomElement e = element.firstChildElement(QStringLiteral("folder")); !e.isNull(); e = e.nextSiblingElement(QStringLiteral("folder"))) {
QDomElement result = KBookmarkGroup(e).findToolbar();
if (!result.isNull()) {
return result;
}
}
return QDomElement();
}
QList<QUrl> KBookmarkGroup::groupUrlList() const
{
QList<QUrl> urlList;
for (KBookmark bm = first(); !bm.isNull(); bm = next(bm)) {
if (bm.isSeparator() || bm.isGroup()) {
continue;
}
urlList << bm.url();
}
return urlList;
}
//////
KBookmark::KBookmark()
{
}
KBookmark::KBookmark(const QDomElement &elem)
: element(elem)
{
}
bool KBookmark::isGroup() const
{
QString tag = element.tagName();
return tag == QLatin1String("folder") //
|| tag == QLatin1String("xbel"); // don't forget the toplevel group
}
bool KBookmark::isSeparator() const
{
return (element.tagName() == QLatin1String("separator"));
}
bool KBookmark::isNull() const
{
return element.isNull();
}
bool KBookmark::hasParent() const
{
QDomElement parent = element.parentNode().toElement();
return !parent.isNull();
}
QString KBookmark::text() const
{
return KStringHandler::csqueeze(fullText());
}
QString KBookmark::fullText() const
{
if (isSeparator()) {
return QCoreApplication::translate("KBookmark", "--- separator ---", "Bookmark separator");
}
QString text = element.namedItem(QStringLiteral("title")).toElement().text();
text.replace(QLatin1Char('\n'), QLatin1Char(' ')); // #140673
return text;
}
void KBookmark::setFullText(const QString &fullText)
{
QDomNode titleNode = element.namedItem(QStringLiteral("title"));
if (titleNode.isNull()) {
titleNode = element.ownerDocument().createElement(QStringLiteral("title"));
element.appendChild(titleNode);
}
if (titleNode.firstChild().isNull()) {
QDomText domtext = titleNode.ownerDocument().createTextNode(QLatin1String(""));
titleNode.appendChild(domtext);
}
QDomText domtext = titleNode.firstChild().toText();
domtext.setData(fullText);
}
QUrl KBookmark::url() const
{
return QUrl(element.attribute(QStringLiteral("href")));
}
void KBookmark::setUrl(const QUrl &url)
{
element.setAttribute(QStringLiteral("href"), url.toString());
}
QString KBookmark::icon() const
{
QDomNode metaDataNode = metaData(Strings::metaDataFreedesktopOwner(), false);
QDomElement iconElement = cd(metaDataNode, QStringLiteral("bookmark:icon"), false).toElement();
QString icon = iconElement.attribute(QStringLiteral("name"));
// migration code
if (icon.isEmpty()) {
icon = element.attribute(QStringLiteral("icon"));
}
if (icon == QLatin1String("www")) { // common icon for kde3 bookmarks
return QStringLiteral("internet-web-browser");
}
// end migration code
if (icon == QLatin1String("bookmark_folder")) {
return QStringLiteral("folder-bookmarks");
}
if (icon.isEmpty()) {
// Default icon depends on URL for bookmarks, and is default directory
// icon for groups.
if (isGroup()) {
icon = QStringLiteral("folder-bookmarks");
} else {
if (isSeparator()) {
icon = QStringLiteral("edit-clear"); // whatever
} else {
// get icon from mimeType
QMimeDatabase db;
QMimeType mime;
QString _mimeType = mimeType();
if (!_mimeType.isEmpty()) {
mime = db.mimeTypeForName(_mimeType);
} else {
mime = db.mimeTypeForUrl(url());
}
if (mime.isValid()) {
icon = mime.iconName();
}
}
}
}
return icon;
}
void KBookmark::setIcon(const QString &icon)
{
QDomNode metaDataNode = metaData(Strings::metaDataFreedesktopOwner(), true);
QDomElement iconElement = cd_or_create(metaDataNode, QStringLiteral("bookmark:icon")).toElement();
iconElement.setAttribute(QStringLiteral("name"), icon);
// migration code
if (!element.attribute(QStringLiteral("icon")).isEmpty()) {
element.removeAttribute(QStringLiteral("icon"));
}
}
QString KBookmark::description() const
{
if (isSeparator()) {
return QString();
}
QString description = element.namedItem(QStringLiteral("desc")).toElement().text();
description.replace(QLatin1Char('\n'), QLatin1Char(' ')); // #140673
return description;
}
void KBookmark::setDescription(const QString &description)
{
QDomNode descNode = element.namedItem(QStringLiteral("desc"));
if (descNode.isNull()) {
descNode = element.ownerDocument().createElement(QStringLiteral("desc"));
element.appendChild(descNode);
}
if (descNode.firstChild().isNull()) {
QDomText domtext = descNode.ownerDocument().createTextNode(QString());
descNode.appendChild(domtext);
}
QDomText domtext = descNode.firstChild().toText();
domtext.setData(description);
}
QString KBookmark::mimeType() const
{
QDomNode metaDataNode = metaData(Strings::metaDataMimeOwner(), false);
QDomElement mimeTypeElement = cd(metaDataNode, QStringLiteral("mime:mime-type"), false).toElement();
return mimeTypeElement.attribute(QStringLiteral("type"));
}
void KBookmark::setMimeType(const QString &mimeType)
{
QDomNode metaDataNode = metaData(Strings::metaDataMimeOwner(), true);
QDomElement iconElement = cd_or_create(metaDataNode, QStringLiteral("mime:mime-type")).toElement();
iconElement.setAttribute(QStringLiteral("type"), mimeType);
}
bool KBookmark::showInToolbar() const
{
if (element.hasAttribute(QStringLiteral("showintoolbar"))) {
bool show = element.attribute(QStringLiteral("showintoolbar")) == QLatin1String("yes");
const_cast<QDomElement *>(&element)->removeAttribute(QStringLiteral("showintoolbar"));
const_cast<KBookmark *>(this)->setShowInToolbar(show);
}
return metaDataItem(QStringLiteral("showintoolbar")) == QLatin1String("yes");
}
void KBookmark::setShowInToolbar(bool show)
{
setMetaDataItem(QStringLiteral("showintoolbar"), show ? QStringLiteral("yes") : QStringLiteral("no"));
}
KBookmarkGroup KBookmark::parentGroup() const
{
return KBookmarkGroup(element.parentNode().toElement());
}
KBookmarkGroup KBookmark::toGroup() const
{
Q_ASSERT(isGroup());
return KBookmarkGroup(element);
}
QString KBookmark::address() const
{
if (element.tagName() == QLatin1String("xbel")) {
return QLatin1String(""); // not QString() !
} else {
// Use keditbookmarks's DEBUG_ADDRESSES flag to debug this code :)
if (element.parentNode().isNull()) {
Q_ASSERT(false);
return QStringLiteral("ERROR"); // Avoid an infinite loop
}
KBookmarkGroup group = parentGroup();
QString parentAddress = group.address();
int pos = group.indexOf(*this);
Q_ASSERT(pos != -1);
return parentAddress + QLatin1Char('/') + QString::number(pos);
}
}
int KBookmark::positionInParent() const
{
return parentGroup().indexOf(*this);
}
QDomElement KBookmark::internalElement() const
{
return element;
}
KBookmark KBookmark::standaloneBookmark(const QString &text, const QUrl &url, const QString &icon)
{
QDomDocument doc(QStringLiteral("xbel"));
QDomElement elem = doc.createElement(QStringLiteral("xbel"));
doc.appendChild(elem);
KBookmarkGroup grp(elem);
grp.addBookmark(text, url, icon);
return grp.first();
}
QString KBookmark::commonParent(const QString &first, const QString &second)
{
QString A = first;
QString B = second;
QString error(QStringLiteral("ERROR"));
if (A == error || B == error) {
return error;
}
A += QLatin1Char('/');
B += QLatin1Char('/');
int lastCommonSlash = 0;
int lastPos = A.length() < B.length() ? A.length() : B.length();
for (int i = 0; i < lastPos; ++i) {
if (A[i] != B[i]) {
return A.left(lastCommonSlash);
}
if (A[i] == QLatin1Char('/')) {
lastCommonSlash = i;
}
}
return A.left(lastCommonSlash);
}
void KBookmark::updateAccessMetadata()
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmark::updateAccessMetadata " << address() << " " << url();
const uint timet = QDateTime::currentDateTimeUtc().toSecsSinceEpoch();
setMetaDataItem(QStringLiteral("time_added"), QString::number(timet), DontOverwriteMetaData);
setMetaDataItem(QStringLiteral("time_visited"), QString::number(timet));
QString countStr = metaDataItem(QStringLiteral("visit_count")); // TODO use spec'ed name
bool ok;
int currentCount = countStr.toInt(&ok);
if (!ok) {
currentCount = 0;
}
currentCount++;
setMetaDataItem(QStringLiteral("visit_count"), QString::number(currentCount));
// TODO - time_modified
}
QString KBookmark::parentAddress(const QString &address)
{
return address.left(address.lastIndexOf(QLatin1Char('/')));
}
uint KBookmark::positionInParent(const QString &address)
{
return QStringView(address).mid(address.lastIndexOf(QLatin1Char('/')) + 1).toInt();
}
QString KBookmark::previousAddress(const QString &address)
{
uint pp = positionInParent(address);
return pp > 0 ? parentAddress(address) + QLatin1Char('/') + QString::number(pp - 1) : QString();
}
QString KBookmark::nextAddress(const QString &address)
{
return parentAddress(address) + QLatin1Char('/') + QString::number(positionInParent(address) + 1);
}
QDomNode KBookmark::metaData(const QString &owner, bool create) const
{
QDomNode infoNode = cd(internalElement(), QStringLiteral("info"), create);
if (infoNode.isNull()) {
return QDomNode();
}
return findMetadata(owner, infoNode, create);
}
QString KBookmark::metaDataItem(const QString &key) const
{
QDomNode metaDataNode = metaData(Strings::metaDataKDEOwner(), false);
for (QDomElement e = metaDataNode.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
if (e.tagName() == key) {
return e.text();
}
}
return QString();
}
void KBookmark::setMetaDataItem(const QString &key, const QString &value, MetaDataOverwriteMode mode)
{
QDomNode metaDataNode = metaData(Strings::metaDataKDEOwner(), true);
QDomNode item = cd_or_create(metaDataNode, key);
QDomText text = get_or_create_text(item);
if (mode == DontOverwriteMetaData && !text.data().isEmpty()) {
return;
}
text.setData(value);
}
bool KBookmark::operator==(const KBookmark &rhs) const
{
return element == rhs.element;
}
////
KBookmarkGroupTraverser::~KBookmarkGroupTraverser()
{
}
void KBookmarkGroupTraverser::traverse(const KBookmarkGroup &root)
{
QStack<KBookmarkGroup> stack;
stack.push(root);
KBookmark bk = root.first();
for (;;) {
if (bk.isNull()) {
if (stack.count() == 1) { // only root is on the stack
return;
}
if (!stack.isEmpty()) {
visitLeave(stack.top());
bk = stack.pop();
}
bk = stack.top().next(bk);
} else if (bk.isGroup()) {
KBookmarkGroup gp = bk.toGroup();
visitEnter(gp);
bk = gp.first();
stack.push(gp);
} else {
visit(bk);
bk = stack.top().next(bk);
}
}
}
void KBookmarkGroupTraverser::visit(const KBookmark &)
{
}
void KBookmarkGroupTraverser::visitEnter(const KBookmarkGroup &)
{
}
void KBookmarkGroupTraverser::visitLeave(const KBookmarkGroup &)
{
}
void KBookmark::populateMimeData(QMimeData *mimeData) const
{
KBookmark::List bookmarkList;
bookmarkList.append(*this);
bookmarkList.populateMimeData(mimeData);
}
KBookmark::List::List()
: QList<KBookmark>()
{
}
void KBookmark::List::populateMimeData(QMimeData *mimeData) const
{
QList<QUrl> urls;
QDomDocument doc(QStringLiteral("xbel"));
QDomElement elem = doc.createElement(QStringLiteral("xbel"));
doc.appendChild(elem);
for (const_iterator it = begin(), end = this->end(); it != end; ++it) {
urls.append((*it).url());
elem.appendChild((*it).internalElement().cloneNode(true /* deep */));
}
// This sets text/uri-list and text/plain into the mimedata
mimeData->setUrls(urls);
mimeData->setData(Strings::xbelMimeType(), doc.toByteArray());
}
bool KBookmark::List::canDecode(const QMimeData *mimeData)
{
return mimeData->hasFormat(Strings::xbelMimeType()) || mimeData->hasUrls();
}
QStringList KBookmark::List::mimeDataTypes()
{
return QStringList() << Strings::xbelMimeType() << KUrlMimeData::mimeDataTypes();
}
KBookmark::List KBookmark::List::fromMimeData(const QMimeData *mimeData, QDomDocument &doc)
{
KBookmark::List bookmarks;
const QByteArray payload = mimeData->data(Strings::xbelMimeType());
if (!payload.isEmpty()) {
doc.setContent(payload);
QDomElement elem = doc.documentElement();
const QDomNodeList children = elem.childNodes();
bookmarks.reserve(children.count());
for (int childno = 0; childno < children.count(); childno++) {
bookmarks.append(KBookmark(children.item(childno).toElement()));
}
return bookmarks;
}
const QList<QUrl> urls = KUrlMimeData::urlsFromMimeData(mimeData);
bookmarks.reserve(urls.size());
for (int i = 0; i < urls.size(); ++i) {
const QUrl url = urls.at(i);
bookmarks.append(KBookmark::standaloneBookmark(url.toDisplayString(), url, QString() /*TODO icon*/));
}
return bookmarks;
}
@@ -0,0 +1,439 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000-2005 David Faure <faure@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef __kbookmark_h
#define __kbookmark_h
#include <kbookmarks_export.h>
#include <QDomElement>
#include <QList>
#include <QMetaType>
#include <QString>
#include <QUrl>
class QMimeData;
class KBookmarkGroup;
/**
* @class KBookmark kbookmark.h KBookmark
*
* A class representing a bookmark.
*/
class KBOOKMARKS_EXPORT KBookmark
{
friend class KBookmarkGroup;
public:
enum MetaDataOverwriteMode {
OverwriteMetaData,
DontOverwriteMetaData,
};
/**
* KBookmark::List is a QList that contains bookmarks with a few
* convenience methods.
* @see KBookmark
* @see QList
*/
class KBOOKMARKS_EXPORT List : public QList<KBookmark>
{
public:
List();
/**
* Adds this list of bookmark into the given QMimeData.
*
* @param mimeData the QMimeData instance used to drag or copy this bookmark
*/
void populateMimeData(QMimeData *mimeData) const;
/**
* Return true if @p mimeData contains bookmarks
*/
static bool canDecode(const QMimeData *mimeData);
/**
* Return the list of mimeTypes that can be decoded by fromMimeData
*/
static QStringList mimeDataTypes();
/**
* Extract a list of bookmarks from the contents of @p mimeData.
* Decoding will fail if @p mimeData does not contain any bookmarks.
* @param mimeData the mime data to extract from; cannot be 0
* @param parentDocument pass an empty QDomDocument here, it will be used as
* container for the bookmarks. You just need to make sure it stays alive longer
* (or just as long) as the returned bookmarks.
* @return the list of bookmarks
* @since 4.3.2
*/
static KBookmark::List fromMimeData(const QMimeData *mimeData, QDomDocument &parentDocument);
};
/**
* Constructs a null bookmark, i.e. a bookmark for which isNull() returns true
* If you want to create a new bookmark use eitehr KBookmarkGroup.addBookmark
* or if you want an interactive dialog use KBookmarkDialog.
*/
KBookmark();
/**
* Creates the KBookmark wrapper for @param elem
* Mostly for internal usage.
*/
explicit KBookmark(const QDomElement &elem);
/**
* Creates a stand alone bookmark. This is fairly expensive since a new QDom Tree is build.
*/
static KBookmark standaloneBookmark(const QString &text, const QUrl &url, const QString &icon);
/**
* Whether the bookmark is a group or a normal bookmark
*/
bool isGroup() const;
/**
* Whether the bookmark is a separator
*/
bool isSeparator() const;
/**
* @return true if this is a null bookmark. This will never
* be the case for a real bookmark (in a menu), but it's used
* for instance as the end condition for KBookmarkGroup::next()
*/
bool isNull() const;
/**
* @return true if bookmark is contained by a QDomDocument,
* if not it is most likely that it has become separated and
* is thus invalid and/or has been deleted from the bookmarks.
*/
bool hasParent() const;
/**
* Text shown for the bookmark
* If bigger than 40, the text is shortened by
* replacing middle characters with "..." (see KStringHandler::csqueeze)
*/
QString text() const;
/**
* Text shown for the bookmark, not truncated.
* You should not use this - this is mainly for keditbookmarks.
*/
QString fullText() const;
/**
* Set the text shown for the bookmark.
*
* @param fullText the new bookmark title
*/
void setFullText(const QString &fullText);
/**
* URL contained by the bookmark
*/
QUrl url() const;
/**
* Set the URL of the bookmark
*
* @param url the new bookmark URL
*/
void setUrl(const QUrl &url);
/**
* @return the pixmap file for this bookmark
* (i.e. the name of the icon)
*/
QString icon() const;
/**
* Set the icon name of the bookmark
*
* @param icon the new icon name for this bookmark
*/
void setIcon(const QString &icon);
/**
* @return Description of the bookmark
* @since 4.4
*/
QString description() const;
/**
* Set the description of the bookmark
*
* @param description
* @since 4.4
*/
void setDescription(const QString &description);
/**
* @return Mime-Type of this item
* @since 4.1
*/
QString mimeType() const;
/**
* Set the Mime-Type of this item
*
* @param Mime-Type
* @since 4.1
*/
void setMimeType(const QString &mimeType);
/**
* @return if the bookmark should be shown in the toolbar
* (used by the filtered toolbar)
*
*/
bool showInToolbar() const;
/**
* Set whether this bookmark is show in a filterd toolbar
*/
void setShowInToolbar(bool show);
/**
* @return the group containing this bookmark
*/
KBookmarkGroup parentGroup() const;
/**
* Convert this to a group - do this only if
* isGroup() returns true.
*/
KBookmarkGroup toGroup() const;
/**
* Return the "address" of this bookmark in the whole tree.
* This is used when telling other processes about a change
* in a given bookmark. The encoding of the address is "/4/2", for
* instance, to designate the 2nd child inside the 4th child of the
* root bookmark.
*/
QString address() const;
/**
* Return the position in the parent, i.e. the last number in the address
*/
int positionInParent() const;
/**
* @internal for KEditBookmarks
*/
QDomElement internalElement() const;
/**
* Updates the bookmarks access metadata
* Call when a user accesses the bookmark
*/
void updateAccessMetadata();
// Utility functions (internal)
/**
* @return address of parent
*/
static QString parentAddress(const QString &address);
/**
* @return position in parent (e.g. /4/5/2 -> 2)
*/
static uint positionInParent(const QString &address);
/**
* @return address of previous sibling (e.g. /4/5/2 -> /4/5/1)
* Returns QString() for a first child
*/
static QString previousAddress(const QString &address);
/**
* @return address of next sibling (e.g. /4/5/2 -> /4/5/3)
* This doesn't check whether it actually exists
*/
static QString nextAddress(const QString &address);
/**
* @return the common parent of both addresses which
* has the greatest depth
*/
static QString commonParent(const QString &A, const QString &B);
/**
* @return the metadata container node for a certain metadata owner
* @since 4.1
*/
QDomNode metaData(const QString &owner, bool create) const;
/**
* Get the value of a specific metadata item (owner = "http://www.kde.org").
* @param key Name of the metadata item
* @return Value of the metadata item. QString() is returned in case
* the specified key does not exist.
*/
QString metaDataItem(const QString &key) const;
/**
* Change the value of a specific metadata item, or create the given item
* if it doesn't exist already (owner = "http://www.kde.org").
* @param key Name of the metadata item to change
* @param value Value to use for the specified metadata item
* @param mode Whether to overwrite the item's value if it exists already or not.
*/
void setMetaDataItem(const QString &key, const QString &value, MetaDataOverwriteMode mode = OverwriteMetaData);
/**
* Adds this bookmark into the given QMimeData.
*
* WARNING: do not call this method multiple times, use KBookmark::List::populateMimeData instead.
*
* @param mimeData the QMimeData instance used to drag or copy this bookmark
*/
void populateMimeData(QMimeData *mimeData) const;
/**
* Comparison operator
*/
bool operator==(const KBookmark &rhs) const;
protected:
QDomElement element;
// Note: you can't add new member variables here.
// The KBookmarks are created on the fly, as wrappers
// around internal QDomElements. Any additional information
// has to be implemented as an attribute of the QDomElement.
};
/**
* A group of bookmarks
*/
class KBOOKMARKS_EXPORT KBookmarkGroup : public KBookmark
{
public:
/**
* Create an invalid group. This is mostly for use in QList,
* and other places where we need a null group.
* Also used as a parent for a bookmark that doesn't have one
* (e.g. Netscape bookmarks)
*/
KBookmarkGroup();
/**
* Create a bookmark group as specified by the given element
*/
KBookmarkGroup(const QDomElement &elem);
/**
* @return true if the bookmark folder is opened in the bookmark editor
*/
bool isOpen() const;
/**
* Return the first child bookmark of this group
*/
KBookmark first() const;
/**
* Return the previous sibling of a child bookmark of this group
* @param current has to be one of our child bookmarks.
*/
KBookmark previous(const KBookmark &current) const;
/**
* Return the next sibling of a child bookmark of this group
* @param current has to be one of our child bookmarks.
*/
KBookmark next(const KBookmark &current) const;
/**
* Return the index of a child bookmark, -1 if not found
*/
int indexOf(const KBookmark &child) const;
/**
* Create a new bookmark folder, as the last child of this group
* @param text for the folder.
* If you want an dialog use KBookmarkDialog
*/
KBookmarkGroup createNewFolder(const QString &text);
/**
* Create a new bookmark separator
* Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
*/
KBookmark createNewSeparator();
/**
* Create a new bookmark, as the last child of this group
* Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
* @param bm the bookmark to add
*/
KBookmark addBookmark(const KBookmark &bm);
/**
* Create a new bookmark, as the last child of this group
* Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
* @param text for the bookmark
* @param url the URL that the bookmark points to.
* It will be stored in its QUrl::FullyEncoded string format.
* @param icon the name of the icon to associate with the bookmark. A suitable default
* will be determined from the URL if not specified.
*/
KBookmark addBookmark(const QString &text, const QUrl &url, const QString &icon);
/**
* Moves @p bookmark after @p after (which should be a child of ours).
* If after is null, @p bookmark is moved as the first child.
* Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
*/
bool moveBookmark(const KBookmark &bookmark, const KBookmark &after);
/**
* Delete a bookmark - it has to be one of our children !
* Don't forget to use KBookmarkManager::self()->emitChanged( parentBookmark );
*/
void deleteBookmark(const KBookmark &bk);
/**
* @return true if this is the toolbar group
*/
bool isToolbarGroup() const;
/**
* @internal
*/
QDomElement findToolbar() const;
/**
* @return the list of urls of bookmarks at top level of the group
*/
QList<QUrl> groupUrlList() const;
protected:
QDomElement nextKnownTag(const QDomElement &start, bool goNext) const;
private:
// Note: you can't add other member variables here, except for caching info.
// The KBookmarks are created on the fly, as wrappers
// around internal QDomElements. Any additional information
// has to be implemented as an attribute of the QDomElement.
};
/**
* A class to traverse bookarm groups
*/
class KBOOKMARKS_EXPORT KBookmarkGroupTraverser
{
protected:
virtual ~KBookmarkGroupTraverser();
void traverse(const KBookmarkGroup &);
virtual void visit(const KBookmark &);
virtual void visitEnter(const KBookmarkGroup &);
virtual void visitLeave(const KBookmarkGroup &);
};
#define KIO_KBOOKMARK_METATYPE_DEFINED 1
Q_DECLARE_METATYPE(KBookmark)
#endif
@@ -0,0 +1,50 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kbookmarkaction.h"
#include "kbookmarkowner.h"
#include <QDesktopServices>
#include <QGuiApplication>
KBookmarkAction::KBookmarkAction(const KBookmark &bk, KBookmarkOwner *owner, QObject *parent)
: QAction(bk.text().replace(QLatin1Char('&'), QLatin1String("&&")), parent)
, KBookmarkActionInterface(bk)
, m_pOwner(owner)
{
setIcon(QIcon::fromTheme(bookmark().icon()));
setIconText(text());
setToolTip(bookmark().url().toDisplayString(QUrl::PreferLocalFile));
setStatusTip(toolTip());
setWhatsThis(toolTip());
const QString description = bk.description();
if (!description.isEmpty()) {
setToolTip(description);
}
connect(this, &QAction::triggered, this, &KBookmarkAction::slotTriggered);
}
KBookmarkAction::~KBookmarkAction()
{
}
void KBookmarkAction::slotTriggered()
{
slotSelected(QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
}
void KBookmarkAction::slotSelected(Qt::MouseButtons mb, Qt::KeyboardModifiers km)
{
if (!m_pOwner) {
QDesktopServices::openUrl(bookmark().url());
} else {
m_pOwner->openBookmark(bookmark(), mb, km);
}
}
#include "moc_kbookmarkaction.cpp"
@@ -0,0 +1,43 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KBOOKMARKACTION_H
#define KBOOKMARKACTION_H
#include "kbookmarkactioninterface.h"
#include <QAction>
class KBookmark;
class KBookmarkOwner;
/**
* @class KBookmarkAction kbookmarkaction.h KBookmarkAction
*
* This class is a QAction for bookmarks.
* It provides a nice constructor.
* And on triggered uses the owner to open the bookmark.
*/
class KBOOKMARKS_EXPORT KBookmarkAction : public QAction, public KBookmarkActionInterface
{
Q_OBJECT
public:
KBookmarkAction(const KBookmark &bk, KBookmarkOwner *owner, QObject *parent);
~KBookmarkAction() override;
public Q_SLOTS:
void slotSelected(Qt::MouseButtons mb, Qt::KeyboardModifiers km);
private Q_SLOTS:
KBOOKMARKS_NO_EXPORT void slotTriggered();
private:
KBookmarkOwner *const m_pOwner;
};
#endif
@@ -0,0 +1,23 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kbookmarkactioninterface.h"
KBookmarkActionInterface::KBookmarkActionInterface(const KBookmark &bk)
: bm(bk)
{
}
KBookmarkActionInterface::~KBookmarkActionInterface()
{
}
const KBookmark KBookmarkActionInterface::bookmark() const
{
return bm;
}
@@ -0,0 +1,30 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KBOOKMARKACTIONINTERFACE_H
#define KBOOKMARKACTIONINTERFACE_H
#include "kbookmark.h"
/**
* @class KBookmarkActionInterface kbookmarkactioninterface.h KBookmarkActionInterface
*
* The interface to implement by actions and menus which represent a bookimark
*/
class KBOOKMARKS_EXPORT KBookmarkActionInterface
{
public:
explicit KBookmarkActionInterface(const KBookmark &bk);
virtual ~KBookmarkActionInterface();
const KBookmark bookmark() const;
private:
const KBookmark bm;
};
#endif
@@ -0,0 +1,391 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
SPDX-FileCopyrightText: 2003 Alexander Kellett <lypanov@kde.org>
SPDX-FileCopyrightText: 2008 Norbert Frese <nf2@scheinwelt.at>
SPDX-License-Identifier: LGPL-2.0-only
*/
#include "kbookmarkmanager.h"
#include "kbookmarks_debug.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QRegularExpression>
#include <QSaveFile>
#include <QStandardPaths>
#include <QTextStream>
#include <KBackup>
#include <KConfig>
#include <KConfigGroup>
#include <KDirWatch>
namespace
{
namespace Strings
{
QString piData()
{
return QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"");
}
}
}
class KBookmarkMap : private KBookmarkGroupTraverser
{
public:
KBookmarkMap()
: m_mapNeedsUpdate(true)
{
}
void setNeedsUpdate()
{
m_mapNeedsUpdate = true;
}
void update(KBookmarkManager *);
QList<KBookmark> find(const QString &url) const
{
return m_bk_map.value(url);
}
private:
void visit(const KBookmark &) override;
void visitEnter(const KBookmarkGroup &) override
{
;
}
void visitLeave(const KBookmarkGroup &) override
{
;
}
private:
typedef QList<KBookmark> KBookmarkList;
QMap<QString, KBookmarkList> m_bk_map;
bool m_mapNeedsUpdate;
};
void KBookmarkMap::update(KBookmarkManager *manager)
{
if (m_mapNeedsUpdate) {
m_mapNeedsUpdate = false;
m_bk_map.clear();
KBookmarkGroup root = manager->root();
traverse(root);
}
}
void KBookmarkMap::visit(const KBookmark &bk)
{
if (!bk.isSeparator()) {
// add bookmark to url map
m_bk_map[bk.internalElement().attribute(QStringLiteral("href"))].append(bk);
}
}
// #########################
// KBookmarkManagerPrivate
class KBookmarkManagerPrivate
{
public:
KBookmarkManagerPrivate(bool bDocIsloaded)
: m_doc(QStringLiteral("xbel"))
, m_docIsLoaded(bDocIsloaded)
, m_dirWatch(nullptr)
{
}
mutable QDomDocument m_doc;
mutable QDomDocument m_toolbarDoc;
QString m_bookmarksFile;
mutable bool m_docIsLoaded;
KDirWatch *m_dirWatch; // for monitoring changes on bookmark files
KBookmarkMap m_map;
};
// ################
// KBookmarkManager
static QDomElement createXbelTopLevelElement(QDomDocument &doc)
{
QDomElement topLevel = doc.createElement(QStringLiteral("xbel"));
topLevel.setAttribute(QStringLiteral("xmlns:mime"), QStringLiteral("http://www.freedesktop.org/standards/shared-mime-info"));
topLevel.setAttribute(QStringLiteral("xmlns:bookmark"), QStringLiteral("http://www.freedesktop.org/standards/desktop-bookmarks"));
topLevel.setAttribute(QStringLiteral("xmlns:kdepriv"), QStringLiteral("http://www.kde.org/kdepriv"));
doc.appendChild(topLevel);
doc.insertBefore(doc.createProcessingInstruction(QStringLiteral("xml"), Strings::piData()), topLevel);
return topLevel;
}
KBookmarkManager::KBookmarkManager(const QString &bookmarksFile, QObject *parent)
: QObject(parent)
, d(new KBookmarkManagerPrivate(false))
{
Q_ASSERT(!bookmarksFile.isEmpty());
d->m_bookmarksFile = bookmarksFile;
if (!QFile::exists(d->m_bookmarksFile)) {
createXbelTopLevelElement(d->m_doc);
} else {
parse();
}
d->m_docIsLoaded = true;
// start KDirWatch
KDirWatch::self()->addFile(d->m_bookmarksFile);
QObject::connect(KDirWatch::self(), &KDirWatch::dirty, this, &KBookmarkManager::slotFileChanged);
QObject::connect(KDirWatch::self(), &KDirWatch::created, this, &KBookmarkManager::slotFileChanged);
QObject::connect(KDirWatch::self(), &KDirWatch::deleted, this, &KBookmarkManager::slotFileChanged);
// qCDebug(KBOOKMARKS_LOG) << "starting KDirWatch for" << d->m_bookmarksFile;
}
void KBookmarkManager::slotFileChanged(const QString &path)
{
if (path == d->m_bookmarksFile) {
// qCDebug(KBOOKMARKS_LOG) << "file changed (KDirWatch) " << path ;
// Reparse
parse();
// Tell our GUI
// (emit where group is "" to directly mark the root menu as dirty)
Q_EMIT changed(QLatin1String(""));
}
}
KBookmarkManager::~KBookmarkManager()
{
}
QDomDocument KBookmarkManager::internalDocument() const
{
if (!d->m_docIsLoaded) {
parse();
d->m_toolbarDoc.clear();
}
return d->m_doc;
}
void KBookmarkManager::parse() const
{
d->m_docIsLoaded = true;
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::parse " << d->m_bookmarksFile;
QFile file(d->m_bookmarksFile);
if (!file.open(QIODevice::ReadOnly)) {
qCWarning(KBOOKMARKS_LOG) << "Can't open" << d->m_bookmarksFile;
d->m_doc = QDomDocument(QStringLiteral("xbel"));
createXbelTopLevelElement(d->m_doc);
return;
}
d->m_doc = QDomDocument(QStringLiteral("xbel"));
d->m_doc.setContent(&file);
if (d->m_doc.documentElement().isNull()) {
qCWarning(KBOOKMARKS_LOG) << "KBookmarkManager::parse : main tag is missing, creating default " << d->m_bookmarksFile;
QDomElement element = d->m_doc.createElement(QStringLiteral("xbel"));
d->m_doc.appendChild(element);
}
QDomElement docElem = d->m_doc.documentElement();
QString mainTag = docElem.tagName();
if (mainTag != QLatin1String("xbel")) {
qCWarning(KBOOKMARKS_LOG) << "KBookmarkManager::parse : unknown main tag " << mainTag;
}
QDomNode n = d->m_doc.documentElement().previousSibling();
if (n.isProcessingInstruction()) {
QDomProcessingInstruction pi = n.toProcessingInstruction();
pi.parentNode().removeChild(pi);
}
QDomProcessingInstruction pi;
pi = d->m_doc.createProcessingInstruction(QStringLiteral("xml"), Strings::piData());
d->m_doc.insertBefore(pi, docElem);
file.close();
d->m_map.setNeedsUpdate();
}
bool KBookmarkManager::save(bool toolbarCache) const
{
return saveAs(d->m_bookmarksFile, toolbarCache);
}
bool KBookmarkManager::saveAs(const QString &filename, bool toolbarCache) const
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::save " << filename;
// Save the bookmark toolbar folder for quick loading
// but only when it will actually make things quicker
const QString cacheFilename = filename + QLatin1String(".tbcache");
if (toolbarCache && !root().isToolbarGroup()) {
QSaveFile cacheFile(cacheFilename);
if (cacheFile.open(QIODevice::WriteOnly)) {
QString str;
QTextStream stream(&str, QIODevice::WriteOnly);
stream << root().findToolbar();
const QByteArray cstr = str.toUtf8();
cacheFile.write(cstr.data(), cstr.length());
cacheFile.commit();
}
} else { // remove any (now) stale cache
QFile::remove(cacheFilename);
}
// Create parent dirs
QFileInfo info(filename);
QDir().mkpath(info.absolutePath());
if (filename == d->m_bookmarksFile) {
KDirWatch::self()->removeFile(d->m_bookmarksFile);
}
QSaveFile file(filename);
bool success = false;
if (file.open(QIODevice::WriteOnly)) {
KBackup::simpleBackupFile(file.fileName(), QString(), QStringLiteral(".bak"));
QTextStream stream(&file);
// In Qt6 it's UTF-8 by default
stream << internalDocument().toString();
stream.flush();
success = file.commit();
}
if (filename == d->m_bookmarksFile) {
KDirWatch::self()->addFile(d->m_bookmarksFile);
}
if (!success) {
QString err = tr("Unable to save bookmarks in %1. Reported error was: %2. "
"This error message will only be shown once. The cause "
"of the error needs to be fixed as quickly as possible, "
"which is most likely a full hard drive.")
.arg(filename, file.errorString());
qCCritical(KBOOKMARKS_LOG)
<< QStringLiteral("Unable to save bookmarks in %1. File reported the following error-code: %2.").arg(filename).arg(file.error());
Q_EMIT const_cast<KBookmarkManager *>(this)->error(err);
}
return success;
}
QString KBookmarkManager::path() const
{
return d->m_bookmarksFile;
}
KBookmarkGroup KBookmarkManager::root() const
{
return KBookmarkGroup(internalDocument().documentElement());
}
KBookmarkGroup KBookmarkManager::toolbar()
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar begin";
// Only try to read from a toolbar cache if the full document isn't loaded
if (!d->m_docIsLoaded) {
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar trying cache";
const QString cacheFilename = d->m_bookmarksFile + QLatin1String(".tbcache");
QFileInfo bmInfo(d->m_bookmarksFile);
QFileInfo cacheInfo(cacheFilename);
if (d->m_toolbarDoc.isNull() && QFile::exists(cacheFilename) && bmInfo.lastModified() < cacheInfo.lastModified()) {
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar reading file";
QFile file(cacheFilename);
if (file.open(QIODevice::ReadOnly)) {
d->m_toolbarDoc = QDomDocument(QStringLiteral("cache"));
d->m_toolbarDoc.setContent(&file);
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar opened";
}
}
if (!d->m_toolbarDoc.isNull()) {
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar returning element";
QDomElement elem = d->m_toolbarDoc.firstChild().toElement();
return KBookmarkGroup(elem);
}
}
// Fallback to the normal way if there is no cache or if the bookmark file
// is already loaded
QDomElement elem = root().findToolbar();
if (elem.isNull()) {
// Root is the bookmark toolbar if none has been set.
// Make it explicit to speed up invocations of findToolbar()
root().internalElement().setAttribute(QStringLiteral("toolbar"), QStringLiteral("yes"));
return root();
} else {
return KBookmarkGroup(elem);
}
}
KBookmark KBookmarkManager::findByAddress(const QString &address)
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::findByAddress " << address;
KBookmark result = root();
// The address is something like /5/10/2+
static const QRegularExpression separator(QStringLiteral("[/+]"));
const QStringList addresses = address.split(separator, Qt::SkipEmptyParts);
// qCWarning(KBOOKMARKS_LOG) << addresses.join(",");
for (QStringList::const_iterator it = addresses.begin(); it != addresses.end();) {
bool append = ((*it) == QLatin1String("+"));
uint number = (*it).toUInt();
Q_ASSERT(result.isGroup());
KBookmarkGroup group = result.toGroup();
KBookmark bk = group.first();
KBookmark lbk = bk; // last non-null bookmark
for (uint i = 0; ((i < number) || append) && !bk.isNull(); ++i) {
lbk = bk;
bk = group.next(bk);
// qCWarning(KBOOKMARKS_LOG) << i;
}
it++;
// qCWarning(KBOOKMARKS_LOG) << "found section";
result = bk;
}
if (result.isNull()) {
qCWarning(KBOOKMARKS_LOG) << "KBookmarkManager::findByAddress: couldn't find item " << address;
}
// qCWarning(KBOOKMARKS_LOG) << "found " << result.address();
return result;
}
void KBookmarkManager::emitChanged()
{
emitChanged(root());
}
void KBookmarkManager::emitChanged(const KBookmarkGroup &group)
{
(void)save(); // KDE5 TODO: emitChanged should return a bool? Maybe rename it to saveAndEmitChanged?
// Tell the other processes too
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::emitChanged : broadcasting change " << group.address();
Q_EMIT changed(group.address());
}
///////
bool KBookmarkManager::updateAccessMetadata(const QString &url)
{
d->m_map.update(this);
QList<KBookmark> list = d->m_map.find(url);
if (list.isEmpty()) {
return false;
}
for (QList<KBookmark>::iterator it = list.begin(); it != list.end(); ++it) {
(*it).updateAccessMetadata();
}
return true;
}
#include "moc_kbookmarkmanager.cpp"
@@ -0,0 +1,175 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000, 2006 David Faure <faure@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef __kbookmarkmanager_h
#define __kbookmarkmanager_h
#include <QDomDocument>
#include <QObject>
#include <QString>
#include <memory>
class KBookmarkManagerPrivate;
#include "kbookmark.h"
class KBookmarkGroup;
/**
* @class KBookmarkManager kbookmarkmanager.h KBookmarkManager
*
* This class implements the reading/writing of bookmarks in XML.
* The bookmarks file is read and written using the XBEL standard
* (http://pyxml.sourceforge.net/topics/xbel/)
*
* A sample file looks like this :
* \code
* <xbel>
* <bookmark href="http://techbase.kde.org"><title>Developer Web Site</title></bookmark>
* <folder folded="no">
* <title>Title of this folder</title>
* <bookmark icon="kde" href="http://www.kde.org"><title>KDE Web Site</title></bookmark>
* <folder toolbar="yes">
* <title>My own bookmarks</title>
* <bookmark href="http://www.koffice.org"><title>KOffice Web Site</title></bookmark>
* <separator/>
* <bookmark href="http://www.kdevelop.org"><title>KDevelop Web Site</title></bookmark>
* </folder>
* </folder>
* </xbel>
* \endcode
*/
class KBOOKMARKS_EXPORT KBookmarkManager : public QObject
{
Q_OBJECT
public:
/**
* Create a KBookmarkManager responsible for the given @p bookmarksFile.
*
* The manager watches the file for change detection.
*
* @param bookmarksFile full path to the bookmarks file,
* Use ~/.kde/share/apps/konqueror/bookmarks.xml for the konqueror bookmarks
*
* @since 6.0
*
*/
explicit KBookmarkManager(const QString &bookmarksFile, QObject *parent = nullptr);
/**
* Destructor
*/
~KBookmarkManager() override;
/**
* Save the bookmarks to the given XML file on disk.
* @param filename full path to the desired bookmarks file location
* @param toolbarCache iff true save a cache of the toolbar folder, too
* @return true if saving was successful
*/
// KF6 TODO: Use an enum and not a bool
bool saveAs(const QString &filename, bool toolbarCache = true) const;
/**
* Update access time stamps for a given url.
* @param url the viewed url
* @return true if any metadata was modified (bookmarks file is not saved automatically)
*/
bool updateAccessMetadata(const QString &url);
/**
* This will return the path that this manager is using to read
* the bookmarks.
* @internal
* @return the path containing the bookmarks
*/
QString path() const;
/**
* This will return the root bookmark. It is used to iterate
* through the bookmarks manually. It is mostly used internally.
*
* @return the root (top-level) bookmark
*/
KBookmarkGroup root() const;
/**
* This returns the root of the toolbar menu.
* In the XML, this is the group with the attribute toolbar=yes
*
* @return the toolbar group
*/
KBookmarkGroup toolbar();
/**
* @return the bookmark designated by @p address
* @param address the address belonging to the bookmark you're looking for
* @param tolerate when true tries to find the most tolerable bookmark position
* @see KBookmark::address
*/
KBookmark findByAddress(const QString &address);
/**
* Saves the bookmark file and notifies everyone.
*
**/
void emitChanged();
/**
* Saves the bookmark file and notifies everyone.
* @param group the parent of all changed bookmarks
*/
void emitChanged(const KBookmarkGroup &group);
/**
* Save the bookmarks to an XML file on disk.
* You should use emitChanged() instead of this function, it saves
* and notifies everyone that the file has changed.
* Only use this if you don't want the emitChanged signal.
* @param toolbarCache iff true save a cache of the toolbar folder, too
* @return true if saving was successful
*/
// KF6 TODO: Use an enum and not a bool
bool save(bool toolbarCache = true) const;
/**
* @internal
*/
QDomDocument internalDocument() const;
Q_SIGNALS:
/**
* Signals that the group (or any of its children) with the address
* @p groupAddress (e.g. "/4/5")
* has been modified.
* connect to this
*/
void changed(const QString &groupAddress);
/**
* Emitted when an error occurs.
* Contains the translated error message.
* @since 4.6
*/
void error(const QString &errorMessage);
private Q_SLOTS:
KBOOKMARKS_NO_EXPORT void slotFileChanged(const QString &path); // external bookmarks
private:
// consts added to avoid a copy-and-paste of internalDocument
KBOOKMARKS_NO_EXPORT void parse() const;
private:
std::unique_ptr<KBookmarkManagerPrivate> const d;
friend class KBookmarkGroup;
};
#endif
@@ -0,0 +1,91 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
SPDX-FileCopyrightText: 2003 Alexander Kellett <lypanov@kde.org>
SPDX-FileCopyrightText: 2008 Norbert Frese <nf2@scheinwelt.at>
SPDX-License-Identifier: LGPL-2.0-only
*/
#include "kbookmarkowner.h"
class Q_DECL_HIDDEN KBookmarkOwner::FutureBookmarkPrivate : public QSharedData
{
public:
QString title;
QUrl url;
QString icon;
};
KBookmarkOwner::FutureBookmark::FutureBookmark(const QString &title, const QUrl &url, const QString &icon)
: d(new FutureBookmarkPrivate)
{
d->title = title;
d->url = url;
d->icon = icon;
}
KBookmarkOwner::FutureBookmark::FutureBookmark(const FutureBookmark &other)
: d(other.d)
{
}
KBookmarkOwner::FutureBookmark &KBookmarkOwner::FutureBookmark::operator=(const FutureBookmark &other)
{
d = other.d;
return *this;
}
KBookmarkOwner::FutureBookmark::~FutureBookmark()
{
}
QString KBookmarkOwner::FutureBookmark::title() const
{
return d->title;
}
QUrl KBookmarkOwner::FutureBookmark::url() const
{
return d->url;
}
QString KBookmarkOwner::FutureBookmark::icon() const
{
return d->icon;
}
KBookmarkOwner::KBookmarkOwner()
: d(nullptr)
{
}
KBookmarkOwner::~KBookmarkOwner() = default;
bool KBookmarkOwner::enableOption(BookmarkOption action) const
{
if (action == ShowAddBookmark) {
return true;
}
if (action == ShowEditBookmark) {
return true;
}
return false;
}
void KBookmarkOwner::openFolderinTabs(const KBookmarkGroup &)
{
}
void KBookmarkOwner::openInNewTab(const KBookmark &bm)
{
// fallback
openBookmark(bm, Qt::LeftButton, Qt::NoModifier);
}
void KBookmarkOwner::openInNewWindow(const KBookmark &bm)
{
// fallback
openBookmark(bm, Qt::LeftButton, Qt::NoModifier);
}
@@ -0,0 +1,175 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000, 2006 David Faure <faure@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef KBOOKMARK_OWNER_H
#define KBOOKMARK_OWNER_H
#include "kbookmark.h"
#include <QSharedDataPointer>
#include <QString>
class QWidget;
class KBookmarkGroup;
/**
* @class KBookmarkOwner kbookmarkowner.h KBookmarkOwner
*
* The KBookmarkMenu and KBookmarkBar classes gives the user
* the ability to either edit bookmarks or add their own. In the
* first case, the app may want to open the bookmark in a special way.
* In the second case, the app @em must supply the name and the
* URL for the bookmark.
*
* This class gives the app this callback-like ability.
*
* If your app does not give the user the ability to add bookmarks and
* you don't mind using the default bookmark editor to edit your
* bookmarks, then you don't need to overload this class at all.
* Rather, just use something like:
*
* @code
* bookmarks = new KBookmarkMenu(manager, nullptr, menu);
* @endcode
*
* If you wish to use your own editor or allow the user to add
* bookmarks, you must overload this class.
*/
class KBOOKMARKS_EXPORT KBookmarkOwner
{
public:
KBookmarkOwner();
virtual ~KBookmarkOwner();
/**
* This function is called whenever the user wants to add the
* current page to the bookmarks list. The title will become the
* "name" of the bookmark. You must overload this function if you
* wish to give your users the ability to add bookmarks.
* The default returns an empty string.
*
* @return the title of the current page.
*/
virtual QString currentTitle() const
{
return QString();
}
/**
* This function is called whenever the user wants to add the
* current page to the bookmarks list. The URL will become the URL
* of the bookmark. You must overload this function if you wish to
* give your users the ability to add bookmarks.
* The default returns an empty string.
*
* @return the URL of the current page.
* Since 5.0 this method returns a QUrl. While porting it, remember to implement currentIcon too.
*/
virtual QUrl currentUrl() const
{
return QUrl();
}
/**
* This function is called whenever the user wants to add the
* current page to the bookmarks list. The icon will become the icon
* of the bookmark. You must overload this function if you wish to
* give your users the ability to add bookmarks.
* The default returns an empty string.
*
* A very common implementation for this method is
* return KIO::iconNameForUrl(currentUrl());
*
* @return the icon name of the current page.
* @since 5.0
*/
virtual QString currentIcon() const
{
return QString();
}
/**
* This function returns whether the owner supports tabs.
* The default returns @c false.
*/
virtual bool supportsTabs() const
{
return false;
}
class FutureBookmarkPrivate;
/**
* Represents the data for a bookmark that will be added.
* @since 5.0
*/
class KBOOKMARKS_EXPORT FutureBookmark
{
public:
FutureBookmark(const QString &title, const QUrl &url, const QString &icon);
~FutureBookmark();
FutureBookmark(const FutureBookmark &other);
FutureBookmark &operator=(const FutureBookmark &other);
QString title() const;
QUrl url() const;
QString icon() const;
private:
QSharedDataPointer<FutureBookmarkPrivate> d;
};
/**
* Returns a list of bookmark data for the open tabs.
* The default returns an empty list.
*/
virtual QList<FutureBookmark> currentBookmarkList() const
{
return QList<FutureBookmark>();
}
enum BookmarkOption { ShowAddBookmark, ShowEditBookmark };
/** Returns true if \p action should be shown in the menu
* The default is to show both a add and editBookmark Entry
* //TODO ContextMenuAction? to disable the contextMenu?
* Delete and Properties to disable those in the
* context menu?
*/
virtual bool enableOption(BookmarkOption option) const;
/**
* Called if a bookmark is selected. You need to override this.
*/
virtual void openBookmark(const KBookmark &bm, Qt::MouseButtons mb, Qt::KeyboardModifiers km) = 0;
/**
* Called if the user wants to open every bookmark in this folder in a new tab.
* The default implementation does nothing.
* This is only called if supportsTabs() returns true
*/
virtual void openFolderinTabs(const KBookmarkGroup &bm);
/**
* Called when a bookmark should be opened in a new tab.
* The default implementation calls openBookmark.
* @since 5.0
*/
virtual void openInNewTab(const KBookmark &bm);
/**
* Called when a bookmark should be opened in a new window.
* The default implementation calls openBookmark.
* @since 5.0
*/
virtual void openInNewWindow(const KBookmark &bm);
private:
class KBookmarkOwnerPrivate;
KBookmarkOwnerPrivate *d;
};
#endif
@@ -0,0 +1,37 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
SPDX-FileCopyrightText: 2003 Alexander Kellett <lypanov@kde.org>
SPDX-FileCopyrightText: 2008 Norbert Frese <nf2@scheinwelt.at>
SPDX-License-Identifier: LGPL-2.0-only
*/
#include "kbookmarksettings_p.h"
#include <KConfig>
#include <KConfigGroup>
KBookmarkSettings *KBookmarkSettings::s_self = nullptr;
void KBookmarkSettings::readSettings()
{
KConfig config(QStringLiteral("kbookmarkrc"), KConfig::NoGlobals);
KConfigGroup cg(&config, QStringLiteral("Bookmarks"));
// add bookmark dialog usage - no reparse
s_self->m_advancedaddbookmark = cg.readEntry("AdvancedAddBookmarkDialog", false);
// this one alters the menu, therefore it needs a reparse
s_self->m_contextmenu = cg.readEntry("ContextMenuActions", true);
}
KBookmarkSettings *KBookmarkSettings::self()
{
if (!s_self) {
s_self = new KBookmarkSettings;
readSettings();
}
return s_self;
}
@@ -0,0 +1,30 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2003 Alexander Kellett <lypanov@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef __kbookmarksettings_p_h__
#define __kbookmarksettings_p_h__
#include <kbookmarks_export.h>
class QString;
class KBookmark;
class KBookmarkGroup;
#define KEDITBOOKMARKS_BINARY "keditbookmarks"
class KBOOKMARKS_EXPORT KBookmarkSettings
{
public:
bool m_advancedaddbookmark;
bool m_contextmenu;
static KBookmarkSettings *s_self;
static void readSettings();
static KBookmarkSettings *self();
};
#endif
@@ -0,0 +1,73 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000, 2006 David Faure <faure@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
#include "keditbookmarks_p.h"
#include <QGuiApplication>
#include <QObject>
#include <QProcess>
#include <QStandardPaths>
#include "kbookmarksettings_p.h"
void KEditBookmarks::setBrowserMode(bool browserMode)
{
m_browserMode = browserMode;
}
KEditBookmarks::OpenResult KEditBookmarks::openForFile(const QString &file)
{
QStringList args;
args << QStringLiteral("--customcaption") << QGuiApplication::applicationDisplayName();
if (!m_browserMode) {
args << QStringLiteral("--nobrowser");
}
args << file;
return startKEditBookmarks(args);
}
KEditBookmarks::OpenResult KEditBookmarks::openForFileAtAddress(const QString &file, const QString &address)
{
QStringList args;
args << QStringLiteral("--customcaption") << QGuiApplication::applicationDisplayName();
if (!m_browserMode) {
args << QStringLiteral("--nobrowser");
}
args << QStringLiteral("--address") << address;
args << file;
return startKEditBookmarks(args);
}
KEditBookmarks::OpenResult KEditBookmarks::startKEditBookmarks(const QStringList &args)
{
const QString exec = QStandardPaths::findExecutable(QStringLiteral(KEDITBOOKMARKS_BINARY));
if (!exec.isEmpty()) {
bool success = QProcess::startDetached(exec, args);
if (!success) {
OpenResult result;
result.m_sucess = false;
result.m_errorMessage = QObject::tr("keditbookmarks could not be started");
return result;
}
} else {
OpenResult result;
result.m_sucess = false;
result.m_errorMessage = QObject::tr("The keditbookmarks executable was not found");
return result;
}
OpenResult result;
result.m_sucess = true;
return result;
}
@@ -0,0 +1,45 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2000, 2006 David Faure <faure@kde.org>
SPDX-License-Identifier: LGPL-2.0-only
*/
#include <QString>
#include "kbookmarks_export.h"
class KBOOKMARKS_EXPORT KEditBookmarks
{
public:
class OpenResult
{
public:
bool sucess()
{
return m_sucess;
}
QString errorMessage() const
{
return m_errorMessage;
}
private:
bool m_sucess;
QString m_errorMessage;
friend KEditBookmarks;
};
void setBrowserMode(bool browserMode);
bool browserMode() const;
OpenResult openForFile(const QString &file);
OpenResult openForFileAtAddress(const QString &file, const QString &address);
private:
OpenResult startKEditBookmarks(const QStringList &args);
bool m_browserMode = false;
};
@@ -0,0 +1,101 @@
add_library(KF6BookmarksWidgets)
add_library(KF6::BookmarksWidgets ALIAS KF6BookmarksWidgets)
set_target_properties(KF6BookmarksWidgets PROPERTIES
VERSION ${KBOOKMARKS_VERSION}
SOVERSION ${KBOOKMARKS_SOVERSION}
EXPORT_NAME BookmarksWidgets
)
ecm_create_qm_loader(KF6BookmarksWidgets kbookmarkswidgets6_qt)
target_sources(KF6BookmarksWidgets PRIVATE
kbookmarkactionmenu.cpp
kbookmarkactionmenu.h
kbookmarkcontextmenu.cpp
kbookmarkcontextmenu.h
kbookmarkdialog.cpp
kbookmarkdialog.h
kbookmarkdialog_p.h
kbookmarkmenu.cpp
kbookmarkmenu.h
kbookmarkmenu_p.h
)
ecm_qt_declare_logging_category(KF6BookmarksWidgets
HEADER kbookmarkswidgets_debug.h
IDENTIFIER KBOOKMARKSWIDGETS_LOG
CATEGORY_NAME kf.bookmarks.widgets
DESCRIPTION "KBookmarks Widgets"
EXPORT KBOOKMARKSWIDGETS
)
ecm_generate_export_header(KF6BookmarksWidgets
BASE_NAME KBookmarksWidgets
GROUP_BASE_NAME KF
VERSION ${KF_VERSION}
USE_VERSION_HEADER kbookmarks_version.h
DEPRECATED_BASE_VERSION 0
DEPRECATION_VERSIONS
EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT}
)
target_include_directories(KF6BookmarksWidgets INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KBookmarksWidgets>")
target_link_libraries(KF6BookmarksWidgets PUBLIC Qt6::Widgets KF6::WidgetsAddons)
target_link_libraries(KF6BookmarksWidgets PRIVATE
KF6::Bookmarks
KF6::ConfigCore # for KAuthorized
KF6::ConfigGui # for KStandardAction
)
ecm_generate_headers(KBookmarksWidgets_HEADERS
HEADER_NAMES
KBookmarkActionMenu
KBookmarkContextMenu
KBookmarkMenu
KBookmarkDialog
REQUIRED_HEADERS KBookmarksWidgets_HEADERS
)
install(TARGETS KF6BookmarksWidgets EXPORT KF6BookmarksTargets ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/kbookmarkswidgets_export.h
${KBookmarksWidgets_HEADERS}
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KBookmarksWidgets COMPONENT Devel
)
ecm_qt_install_logging_categories(
EXPORT KBOOKMARKSWIDGETS
FILE kbookmarkswidgets.categories
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
)
if(BUILD_QCH)
ecm_add_qch(
KF6BookmarksWidgets_QCH
NAME KBookmarksWidgets
BASE_NAME KF6BookmarksWidgets
VERSION ${KF_VERSION}
ORG_DOMAIN org.kde
SOURCES # using only public headers, to cover only public API
${KBookmarksWidgets_HEADERS}
MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md"
LINK_QCHS
Qt6Widgets_QCH
Qt6Xml_QCH
KF6WidgetsAddons_QCH
INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}
BLANK_MACROS
KBOOKMARKSWIDGETS_EXPORT
KBOOKMARKSWIDGETS_DEPRECATED
KBOOKMARKSWIDGETS_DEPRECATED_EXPORT
"KBOOKMARKS_DEPRECATED_VERSION(x, y, t)"
TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR}
COMPONENT Devel
)
endif()
@@ -0,0 +1,29 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kbookmarkactionmenu.h"
KBookmarkActionMenu::KBookmarkActionMenu(const KBookmark &bm, QObject *parent)
: KActionMenu(QIcon::fromTheme(bm.icon()), bm.text().replace(QLatin1Char('&'), QLatin1String("&&")), parent)
, KBookmarkActionInterface(bm)
{
setToolTip(bm.description());
setIconText(text());
}
KBookmarkActionMenu::KBookmarkActionMenu(const KBookmark &bm, const QString &text, QObject *parent)
: KActionMenu(text, parent)
, KBookmarkActionInterface(bm)
{
}
KBookmarkActionMenu::~KBookmarkActionMenu()
{
}
#include "moc_kbookmarkactionmenu.cpp"
@@ -0,0 +1,30 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KBOOKMARKACTIONMENU_H
#define KBOOKMARKACTIONMENU_H
#include "kbookmarkactioninterface.h"
#include <KActionMenu>
#include <kbookmarkswidgets_export.h>
/**
* @class KBookmarkActionMenu kbookmarkactionmenu.h KBookmarkActionMenu
*
* A wrapper around KActionMenu to provide a nice constructor for bookmark groups.
*/
class KBOOKMARKSWIDGETS_EXPORT KBookmarkActionMenu : public KActionMenu, public KBookmarkActionInterface
{
Q_OBJECT
public:
KBookmarkActionMenu(const KBookmark &bm, QObject *parent);
KBookmarkActionMenu(const KBookmark &bm, const QString &text, QObject *parent);
~KBookmarkActionMenu() override;
};
#endif
@@ -0,0 +1,198 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kbookmarkcontextmenu.h"
#include "kbookmarkdialog.h"
#include "kbookmarkmanager.h"
#include "kbookmarkowner.h"
#include "keditbookmarks_p.h"
#include <QApplication>
#include <QClipboard>
#include <QMessageBox>
#include <QMimeData>
KBookmarkContextMenu::KBookmarkContextMenu(const KBookmark &bk, KBookmarkManager *manager, KBookmarkOwner *owner, QWidget *parent)
: QMenu(parent)
, bm(bk)
, m_pManager(manager)
, m_pOwner(owner)
{
connect(this, &QMenu::aboutToShow, this, &KBookmarkContextMenu::slotAboutToShow);
}
void KBookmarkContextMenu::slotAboutToShow()
{
addActions();
}
void KBookmarkContextMenu::addActions()
{
if (bm.isGroup()) {
addOpenFolderInTabs();
addBookmark();
addFolderActions();
} else {
addBookmark();
addBookmarkActions();
}
}
KBookmarkContextMenu::~KBookmarkContextMenu()
{
}
void KBookmarkContextMenu::addBookmark()
{
if (m_pOwner && m_pOwner->enableOption(KBookmarkOwner::ShowAddBookmark)) {
addAction(QIcon::fromTheme(QStringLiteral("bookmark-new")), tr("Add Bookmark Here", "@action:inmenu"), this, &KBookmarkContextMenu::slotInsert);
}
}
void KBookmarkContextMenu::addFolderActions()
{
addAction(tr("Open Folder in Bookmark Editor", "@action:inmenu"), this, &KBookmarkContextMenu::slotEditAt);
addProperties();
addSeparator();
addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("Delete Folder", "@action:inmenu"), this, &KBookmarkContextMenu::slotRemove);
}
void KBookmarkContextMenu::addProperties()
{
addAction(tr("Properties", "@action:inmenu"), this, &KBookmarkContextMenu::slotProperties);
}
void KBookmarkContextMenu::addBookmarkActions()
{
addAction(tr("Copy Link Address", "@action:inmenu"), this, &KBookmarkContextMenu::slotCopyLocation);
addProperties();
addSeparator();
addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), tr("Delete Bookmark", "@action:inmenu"), this, &KBookmarkContextMenu::slotRemove);
}
void KBookmarkContextMenu::addOpenFolderInTabs()
{
if (m_pOwner->supportsTabs()) {
addAction(QIcon::fromTheme(QStringLiteral("tab-new")), tr("Open Folder in Tabs", "@action:inmenu"), this, &KBookmarkContextMenu::slotOpenFolderInTabs);
}
}
void KBookmarkContextMenu::slotEditAt()
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotEditAt" << m_highlightedAddress;
KEditBookmarks editBookmarks;
editBookmarks.setBrowserMode(m_browserMode);
auto result = editBookmarks.openForFileAtAddress(m_pManager->path(), bm.address());
if (!result.sucess()) {
QMessageBox::critical(QApplication::activeWindow(), QApplication::applicationDisplayName(), result.errorMessage());
}
}
void KBookmarkContextMenu::slotProperties()
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotProperties" << m_highlightedAddress;
KBookmarkDialog *dlg = new KBookmarkDialog(m_pManager, QApplication::activeWindow());
dlg->editBookmark(bm);
delete dlg;
}
void KBookmarkContextMenu::slotInsert()
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotInsert" << m_highlightedAddress;
QUrl url = m_pOwner->currentUrl();
if (url.isEmpty()) {
QMessageBox::critical(QApplication::activeWindow(), QApplication::applicationName(), tr("Cannot add bookmark with empty URL.", "@info"));
return;
}
QString title = m_pOwner->currentTitle();
if (title.isEmpty()) {
title = url.toDisplayString();
}
if (bm.isGroup()) {
KBookmarkGroup parentBookmark = bm.toGroup();
Q_ASSERT(!parentBookmark.isNull());
parentBookmark.addBookmark(title, url, m_pOwner->currentIcon());
m_pManager->emitChanged(parentBookmark);
} else {
KBookmarkGroup parentBookmark = bm.parentGroup();
Q_ASSERT(!parentBookmark.isNull());
KBookmark newBookmark = parentBookmark.addBookmark(title, m_pOwner->currentUrl(), m_pOwner->currentIcon());
parentBookmark.moveBookmark(newBookmark, parentBookmark.previous(bm));
m_pManager->emitChanged(parentBookmark);
}
}
void KBookmarkContextMenu::slotRemove()
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotRemove" << m_highlightedAddress;
bool folder = bm.isGroup();
if (QMessageBox::warning(QApplication::activeWindow(),
folder ? tr("Bookmark Folder Deletion", "@title:window") : tr("Bookmark Deletion", "@title:window"),
folder ? tr("Are you sure you wish to remove the bookmark folder\n\"%1\"?").arg(bm.text())
: tr("Are you sure you wish to remove the bookmark\n\"%1\"?").arg(bm.text()),
QMessageBox::Yes | QMessageBox::Cancel)
!= QMessageBox::Yes) {
return;
}
KBookmarkGroup parentBookmark = bm.parentGroup();
parentBookmark.deleteBookmark(bm);
m_pManager->emitChanged(parentBookmark);
}
void KBookmarkContextMenu::slotCopyLocation()
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotCopyLocation" << m_highlightedAddress;
if (!bm.isGroup()) {
QMimeData *mimeData = new QMimeData;
bm.populateMimeData(mimeData);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection);
mimeData = new QMimeData;
bm.populateMimeData(mimeData);
QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
}
}
void KBookmarkContextMenu::slotOpenFolderInTabs()
{
owner()->openFolderinTabs(bookmark().toGroup());
}
KBookmarkManager *KBookmarkContextMenu::manager() const
{
return m_pManager;
}
KBookmarkOwner *KBookmarkContextMenu::owner() const
{
return m_pOwner;
}
KBookmark KBookmarkContextMenu::bookmark() const
{
return bm;
}
void KBookmarkContextMenu::setBrowserMode(bool browserMode)
{
m_browserMode = browserMode;
}
bool KBookmarkContextMenu::browserMode() const
{
return m_browserMode;
}
#include "moc_kbookmarkcontextmenu.cpp"
@@ -0,0 +1,80 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef KBOOKMARKCONTEXTMENU_H
#define KBOOKMARKCONTEXTMENU_H
#include <QMenu>
#include "kbookmark.h"
#include <kbookmarkswidgets_export.h>
class KBookmarkManager;
class KBookmarkOwner;
/**
* @class KBookmarkContextMenu kbookmarkcontextmenu.h KBookmarkContextMenu
*
* A context menu for a bookmark.
*/
class KBOOKMARKSWIDGETS_EXPORT KBookmarkContextMenu : public QMenu
{
Q_OBJECT
public:
KBookmarkContextMenu(const KBookmark &bm, KBookmarkManager *manager, KBookmarkOwner *owner, QWidget *parent = nullptr);
~KBookmarkContextMenu() override;
virtual void addActions();
/**
* Set this to true to make any "Edit Bookmarks" dialog
* show UI elements that are specific to browsers.
*
* @since 6.0
*/
void setBrowserMode(bool browserMode);
/**
* Whether any "Edit Bookmarks" dialog shows UI elements
* that are specific to browsers.
*
* @since 6.0
*/
bool browserMode() const;
public Q_SLOTS:
void slotEditAt();
void slotProperties();
void slotInsert();
void slotRemove();
void slotCopyLocation();
void slotOpenFolderInTabs();
protected:
void addBookmark();
void addFolderActions();
void addProperties();
void addBookmarkActions();
void addOpenFolderInTabs();
KBookmarkManager *manager() const;
KBookmarkOwner *owner() const;
KBookmark bookmark() const;
private Q_SLOTS:
KBOOKMARKS_NO_EXPORT void slotAboutToShow();
private:
// TODO KF6 dptr it
const KBookmark bm;
KBookmarkManager *const m_pManager;
KBookmarkOwner *const m_pOwner;
bool m_browserMode = false;
};
#endif
@@ -0,0 +1,391 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2007 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-only
*/
#include "kbookmarkdialog.h"
#include "kbookmarkdialog_p.h"
#include "kbookmarkmanager.h"
#include "kbookmarkmenu_p.h"
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QHeaderView>
#include <QIcon>
#include <QInputDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QTreeWidget>
#include <KGuiItem>
KBookmarkDialogPrivate::KBookmarkDialogPrivate(KBookmarkDialog *qq)
: q(qq)
, folderTree(nullptr)
, layout(false)
{
}
KBookmarkDialogPrivate::~KBookmarkDialogPrivate()
{
}
void KBookmarkDialogPrivate::initLayout()
{
QBoxLayout *vbox = new QVBoxLayout(q);
QFormLayout *form = new QFormLayout();
vbox->addLayout(form);
form->addRow(titleLabel, title);
form->addRow(urlLabel, url);
form->addRow(commentLabel, comment);
vbox->addWidget(folderTree);
vbox->addWidget(buttonBox);
}
void KBookmarkDialogPrivate::initLayoutPrivate()
{
title = new QLineEdit(q);
title->setMinimumWidth(300);
titleLabel = new QLabel(KBookmarkDialog::tr("Name:", "@label:textbox"), q);
titleLabel->setBuddy(title);
url = new QLineEdit(q);
url->setMinimumWidth(300);
urlLabel = new QLabel(KBookmarkDialog::tr("Location:", "@label:textbox"), q);
urlLabel->setBuddy(url);
comment = new QLineEdit(q);
comment->setMinimumWidth(300);
commentLabel = new QLabel(KBookmarkDialog::tr("Comment:", "@label:textbox"), q);
commentLabel->setBuddy(comment);
folderTree = new QTreeWidget(q);
folderTree->setColumnCount(1);
folderTree->header()->hide();
folderTree->setSortingEnabled(false);
folderTree->setSelectionMode(QTreeWidget::SingleSelection);
folderTree->setSelectionBehavior(QTreeWidget::SelectRows);
folderTree->setMinimumSize(60, 100);
QTreeWidgetItem *root = new KBookmarkTreeItem(folderTree);
fillGroup(root, mgr->root());
buttonBox = new QDialogButtonBox(q);
buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
q->connect(buttonBox, &QDialogButtonBox::accepted, q, &KBookmarkDialog::accept);
q->connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);
initLayout();
layout = true;
}
void KBookmarkDialogPrivate::fillGroup(QTreeWidgetItem *parentItem, const KBookmarkGroup &group, const KBookmarkGroup &selectGroup)
{
for (KBookmark bk = group.first(); !bk.isNull(); bk = group.next(bk)) {
if (bk.isGroup()) {
const KBookmarkGroup bkGroup = bk.toGroup();
QTreeWidgetItem *item = new KBookmarkTreeItem(parentItem, folderTree, bkGroup);
if (selectGroup == bkGroup) {
folderTree->setCurrentItem(item);
}
fillGroup(item, bkGroup, selectGroup);
}
}
}
void KBookmarkDialogPrivate::setParentBookmark(const KBookmark &bm)
{
QString address = bm.address();
KBookmarkTreeItem *item = static_cast<KBookmarkTreeItem *>(folderTree->topLevelItem(0));
while (true) {
if (item->address() == bm.address()) {
folderTree->setCurrentItem(item);
return;
}
for (int i = 0; i < item->childCount(); ++i) {
KBookmarkTreeItem *child = static_cast<KBookmarkTreeItem *>(item->child(i));
if (KBookmark::commonParent(child->address(), address) == child->address()) {
item = child;
break;
}
}
}
}
KBookmarkGroup KBookmarkDialogPrivate::parentBookmark()
{
KBookmarkTreeItem *item = dynamic_cast<KBookmarkTreeItem *>(folderTree->currentItem());
if (!item) {
return mgr->root();
}
const QString &address = item->address();
return mgr->findByAddress(address).toGroup();
}
void KBookmarkDialog::accept()
{
if (d->mode == KBookmarkDialogPrivate::NewFolder) {
KBookmarkGroup parent = d->parentBookmark();
if (d->title->text().isEmpty()) {
d->title->setText(QStringLiteral("New Folder"));
}
d->bm = parent.createNewFolder(d->title->text());
d->bm.setDescription(d->comment->text());
d->mgr->emitChanged(parent);
} else if (d->mode == KBookmarkDialogPrivate::NewBookmark) {
KBookmarkGroup parent = d->parentBookmark();
if (d->title->text().isEmpty()) {
d->title->setText(QStringLiteral("New Bookmark"));
}
d->bm = parent.addBookmark(d->title->text(), QUrl(d->url->text()), d->icon);
d->bm.setDescription(d->comment->text());
d->mgr->emitChanged(parent);
} else if (d->mode == KBookmarkDialogPrivate::NewMultipleBookmarks) {
KBookmarkGroup parent = d->parentBookmark();
if (d->title->text().isEmpty()) {
d->title->setText(QStringLiteral("New Folder"));
}
d->bm = parent.createNewFolder(d->title->text());
d->bm.setDescription(d->comment->text());
for (const KBookmarkOwner::FutureBookmark &fb : std::as_const(d->list)) {
d->bm.toGroup().addBookmark(fb.title(), fb.url(), fb.icon());
}
d->mgr->emitChanged(parent);
} else if (d->mode == KBookmarkDialogPrivate::EditBookmark) {
d->bm.setFullText(d->title->text());
d->bm.setUrl(QUrl(d->url->text()));
d->bm.setDescription(d->comment->text());
d->mgr->emitChanged(d->bm.parentGroup());
} else if (d->mode == d->SelectFolder) {
d->bm = d->parentBookmark();
}
QDialog::accept();
}
KBookmark KBookmarkDialog::editBookmark(const KBookmark &bm)
{
if (!d->layout) {
d->initLayoutPrivate();
}
KGuiItem::assign(d->buttonBox->button(QDialogButtonBox::Ok), KGuiItem(tr("Update", "@action:button")));
setWindowTitle(tr("Bookmark Properties", "@title:window"));
d->url->setVisible(!bm.isGroup());
d->urlLabel->setVisible(!bm.isGroup());
d->bm = bm;
d->title->setText(bm.fullText());
d->url->setText(bm.url().toString());
d->comment->setVisible(true);
d->commentLabel->setVisible(true);
d->comment->setText(bm.description());
d->folderTree->setVisible(false);
d->mode = KBookmarkDialogPrivate::EditBookmark;
if (exec() == QDialog::Accepted) {
return d->bm;
} else {
return KBookmark();
}
}
KBookmark KBookmarkDialog::addBookmark(const QString &title, const QUrl &url, const QString &icon, KBookmark parent)
{
if (!d->layout) {
d->initLayoutPrivate();
}
if (parent.isNull()) {
parent = d->mgr->root();
}
QPushButton *newButton = new QPushButton;
KGuiItem::assign(newButton, KGuiItem(tr("&New Folder…", "@action:button"), QStringLiteral("folder-new")));
d->buttonBox->addButton(newButton, QDialogButtonBox::ActionRole);
connect(newButton, &QAbstractButton::clicked, this, &KBookmarkDialog::newFolderButton);
KGuiItem::assign(d->buttonBox->button(QDialogButtonBox::Ok), KGuiItem(tr("Add", "@action:button"), QStringLiteral("bookmark-new")));
setWindowTitle(tr("Add Bookmark", "@title:window"));
d->url->setVisible(true);
d->urlLabel->setVisible(true);
d->title->setText(title);
d->url->setText(url.toString());
d->comment->setText(QString());
d->comment->setVisible(true);
d->commentLabel->setVisible(true);
d->setParentBookmark(parent);
d->folderTree->setVisible(true);
d->icon = icon;
d->mode = KBookmarkDialogPrivate::NewBookmark;
if (exec() == QDialog::Accepted) {
return d->bm;
} else {
return KBookmark();
}
}
KBookmarkGroup KBookmarkDialog::addBookmarks(const QList<KBookmarkOwner::FutureBookmark> &list, const QString &name, KBookmarkGroup parent)
{
if (!d->layout) {
d->initLayoutPrivate();
}
if (parent.isNull()) {
parent = d->mgr->root();
}
d->list = list;
QPushButton *newButton = new QPushButton;
KGuiItem::assign(newButton, KGuiItem(tr("&New Folder…", "@action:button"), QStringLiteral("folder-new")));
d->buttonBox->addButton(newButton, QDialogButtonBox::ActionRole);
connect(newButton, &QAbstractButton::clicked, this, &KBookmarkDialog::newFolderButton);
KGuiItem::assign(d->buttonBox->button(QDialogButtonBox::Ok), KGuiItem(tr("Add", "@action:button"), QStringLiteral("bookmark-new")));
setWindowTitle(tr("Add Bookmarks", "@title:window"));
d->url->setVisible(false);
d->urlLabel->setVisible(false);
d->title->setText(name);
d->comment->setVisible(true);
d->commentLabel->setVisible(true);
d->comment->setText(QString());
d->setParentBookmark(parent);
d->folderTree->setVisible(true);
d->mode = KBookmarkDialogPrivate::NewMultipleBookmarks;
if (exec() == QDialog::Accepted) {
return d->bm.toGroup();
} else {
return KBookmarkGroup();
}
}
KBookmarkGroup KBookmarkDialog::selectFolder(KBookmark parent)
{
if (!d->layout) {
d->initLayoutPrivate();
}
if (parent.isNull()) {
parent = d->mgr->root();
}
QPushButton *newButton = new QPushButton;
KGuiItem::assign(newButton, KGuiItem(tr("&New Folder…", "@action:button"), QStringLiteral("folder-new")));
d->buttonBox->addButton(newButton, QDialogButtonBox::ActionRole);
connect(newButton, &QAbstractButton::clicked, this, &KBookmarkDialog::newFolderButton);
setWindowTitle(tr("Select Folder", "@title:window"));
d->url->setVisible(false);
d->urlLabel->setVisible(false);
d->title->setVisible(false);
d->titleLabel->setVisible(false);
d->comment->setVisible(false);
d->commentLabel->setVisible(false);
d->setParentBookmark(parent);
d->folderTree->setVisible(true);
d->mode = d->SelectFolder;
if (exec() == QDialog::Accepted) {
return d->bm.toGroup();
} else {
return KBookmarkGroup();
}
}
KBookmarkGroup KBookmarkDialog::createNewFolder(const QString &name, KBookmark parent)
{
if (!d->layout) {
d->initLayoutPrivate();
}
if (parent.isNull()) {
parent = d->mgr->root();
}
setWindowTitle(tr("New Folder", "@title:window"));
d->url->setVisible(false);
d->urlLabel->setVisible(false);
d->comment->setVisible(true);
d->commentLabel->setVisible(true);
d->comment->setText(QString());
d->title->setText(name);
d->setParentBookmark(parent);
d->folderTree->setVisible(true);
d->mode = KBookmarkDialogPrivate::NewFolder;
if (exec() == QDialog::Accepted) {
return d->bm.toGroup();
} else {
return KBookmarkGroup();
}
}
KBookmarkDialog::KBookmarkDialog(KBookmarkManager *mgr, QWidget *parent)
: QDialog(parent)
, d(new KBookmarkDialogPrivate(this))
{
d->mgr = mgr;
}
KBookmarkDialog::~KBookmarkDialog() = default;
void KBookmarkDialog::newFolderButton()
{
QString caption = d->parentBookmark().fullText().isEmpty() ? tr("Create New Bookmark Folder", "@title:window")
: tr("Create New Bookmark Folder in %1", "@title:window").arg(d->parentBookmark().text());
bool ok;
QString text = QInputDialog::getText(this, caption, tr("New folder:", "@label:textbox"), QLineEdit::Normal, QString(), &ok);
if (!ok) {
return;
}
KBookmarkGroup group = d->parentBookmark().createNewFolder(text);
if (!group.isNull()) {
KBookmarkGroup parentGroup = group.parentGroup();
d->mgr->emitChanged(parentGroup);
d->folderTree->clear();
QTreeWidgetItem *root = new KBookmarkTreeItem(d->folderTree);
d->fillGroup(root, d->mgr->root(), group);
}
}
/********************************************************************/
KBookmarkTreeItem::KBookmarkTreeItem(QTreeWidget *tree)
: QTreeWidgetItem(tree)
, m_address(QLatin1String(""))
{
setText(0, KBookmarkDialog::tr("Bookmarks", "name of the container of all browser bookmarks"));
setIcon(0, QIcon::fromTheme(QStringLiteral("bookmarks")));
tree->expandItem(this);
tree->setCurrentItem(this);
setSelected(true);
}
KBookmarkTreeItem::KBookmarkTreeItem(QTreeWidgetItem *parent, QTreeWidget *tree, const KBookmarkGroup &bk)
: QTreeWidgetItem(parent)
{
setIcon(0, QIcon::fromTheme(bk.icon()));
setText(0, bk.fullText());
tree->expandItem(this);
m_address = bk.address();
}
KBookmarkTreeItem::~KBookmarkTreeItem()
{
}
QString KBookmarkTreeItem::address()
{
return m_address;
}
#include "moc_kbookmarkdialog.cpp"
@@ -0,0 +1,76 @@
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2007 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef __kbookmarkdialog_h
#define __kbookmarkdialog_h
#include "kbookmark.h"
#include "kbookmarkowner.h"
#include <kbookmarkswidgets_export.h>
#include <QDialog>
#include <memory>
class KBookmarkManager;
class KBookmarkDialogPrivate;
/**
* @class KBookmarkDialog kbookmarkdialog.h KBookmarkDialog
*
* This class provides a Dialog for editing properties, adding Bookmarks and creating new folders.
* It can be used to show dialogs for common tasks with bookmarks.
*
* It is used by KBookmarkMenu to show a dialog for "Properties", "Add Bookmark" and "Create New Folder".
* If you want to customize those dialogs, derive from KBookmarkOwner and reimplement bookmarkDialog(),
* return a KBookmarkDialog subclass and reimplement initLayout(), aboutToShow() and save().
*/
class KBOOKMARKSWIDGETS_EXPORT KBookmarkDialog : public QDialog
{
Q_OBJECT
public:
/**
* Creates a KBookmarkDialog instance
*/
KBookmarkDialog(KBookmarkManager *manager, QWidget *parent = nullptr);
/**
* Shows a properties dialog
* Note: this updates the bookmark and calls KBookmarkManager::emitChanged
*/
KBookmark editBookmark(const KBookmark &bm);
/**
* Shows a "Add Bookmark" dialog
* Note: this updates the bookmark and calls KBookmarkManager::emitChanged
*/
KBookmark addBookmark(const QString &title, const QUrl &url, const QString &icon, KBookmark parent = KBookmark());
/**
* Creates a folder from a list of bookmarks
* Note: this updates the bookmark and calls KBookmarkManager::emitChanged
*/
KBookmarkGroup addBookmarks(const QList<KBookmarkOwner::FutureBookmark> &list, const QString &name = QString(), KBookmarkGroup parent = KBookmarkGroup());
/**
* Shows a dialog to create a new folder.
*/
KBookmarkGroup createNewFolder(const QString &name, KBookmark parent = KBookmark());
/**
* Shows a dialog to select a folder.
*/
KBookmarkGroup selectFolder(KBookmark start = KBookmark());
~KBookmarkDialog() override;
protected:
void accept() override;
protected Q_SLOTS:
void newFolderButton();
private:
std::unique_ptr<KBookmarkDialogPrivate> const d;
friend class KBookmarkDialogPrivate;
};
#endif
@@ -0,0 +1,55 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE libraries
SPDX-FileCopyrightText: 2013 Jignesh Kakadiya <jigneshhk1992@gmail.com>
SPDX-License-Identifier: LGPL-2.0-only
*/
#ifndef __kbookmarkdialog_p_h__
#define __kbookmarkdialog_p_h__
#include "kbookmark.h"
#include "kbookmarkowner.h"
#include <QDialog>
class KBookmarkDialog;
class KBookmarkManager;
class QDialogButtonBox;
class QLabel;
class QTreeWidget;
class QLineEdit;
class QTreeWidgetItem;
class KBookmarkDialogPrivate
{
public:
explicit KBookmarkDialogPrivate(KBookmarkDialog *qq);
~KBookmarkDialogPrivate();
typedef enum { NewFolder, NewBookmark, EditBookmark, NewMultipleBookmarks, SelectFolder } BookmarkDialogMode;
void initLayout();
void initLayoutPrivate();
// selects the specified bookmark in the folder tree
void setParentBookmark(const KBookmark &bm);
KBookmarkGroup parentBookmark();
void fillGroup(QTreeWidgetItem *parentItem, const KBookmarkGroup &group, const KBookmarkGroup &selectGroup = KBookmarkGroup());
KBookmarkDialog *const q;
BookmarkDialogMode mode;
QDialogButtonBox *buttonBox = nullptr;
QLineEdit *url = nullptr;
QLineEdit *title = nullptr;
QLineEdit *comment = nullptr;
QLabel *titleLabel = nullptr;
QLabel *urlLabel = nullptr;
QLabel *commentLabel;
QString icon;
QTreeWidget *folderTree = nullptr;
KBookmarkManager *mgr = nullptr;
KBookmark bm;
QList<KBookmarkOwner::FutureBookmark> list;
bool layout;
};
#endif
@@ -0,0 +1,462 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kbookmarkmenu.h"
#include "kbookmarkmenu_p.h"
#include "../kbookmarksettings_p.h"
#include "kbookmarkaction.h"
#include "kbookmarkactionmenu.h"
#include "kbookmarkcontextmenu.h"
#include "kbookmarkdialog.h"
#include "kbookmarkmanager.h"
#include "kbookmarkowner.h"
#include "kbookmarkswidgets_debug.h"
#include "keditbookmarks_p.h"
#include <KAuthorized>
#include <KStandardActions>
#include <QApplication>
#include <QMenu>
#include <QMessageBox>
#include <QStandardPaths>
/********************************************************************/
/********************************************************************/
/********************************************************************/
class KBookmarkMenuPrivate
{
public:
QAction *newBookmarkFolderAction = nullptr;
QAction *addBookmarkAction = nullptr;
QAction *bookmarksToFolderAction = nullptr;
QAction *editBookmarksAction = nullptr;
bool browserMode = false;
bool isRoot;
bool dirty;
KBookmarkManager *manager;
KBookmarkOwner *owner;
QMenu *parentMenu;
QString parentAddress;
};
KBookmarkMenu::KBookmarkMenu(KBookmarkManager *manager, KBookmarkOwner *_owner, QMenu *_parentMenu)
: QObject()
, d(new KBookmarkMenuPrivate())
{
d->isRoot = true;
d->manager = manager;
d->owner = _owner;
d->parentMenu = _parentMenu;
d->parentAddress = QString(); // TODO KBookmarkAdress::root
// TODO KDE5 find a QMenu equvalnet for this one
// m_parentMenu->setKeyboardShortcutsEnabled( true );
init();
}
void KBookmarkMenu::init()
{
connect(d->parentMenu, &QMenu::aboutToShow, this, &KBookmarkMenu::slotAboutToShow);
if (KBookmarkSettings::self()->m_contextmenu) {
d->parentMenu->setContextMenuPolicy(Qt::CustomContextMenu);
connect(d->parentMenu, &QWidget::customContextMenuRequested, this, &KBookmarkMenu::slotCustomContextMenu);
}
connect(d->manager, &KBookmarkManager::changed, this, &KBookmarkMenu::slotBookmarksChanged);
d->dirty = true;
addActions();
}
void KBookmarkMenu::addActions()
{
if (d->isRoot) {
addAddBookmark();
addAddBookmarksList();
addNewFolder();
addEditBookmarks();
} else {
if (!d->parentMenu->actions().isEmpty()) {
d->parentMenu->addSeparator();
}
addOpenInTabs();
addAddBookmark();
addAddBookmarksList();
addNewFolder();
}
}
KBookmarkMenu::KBookmarkMenu(KBookmarkManager *mgr, KBookmarkOwner *_owner, QMenu *_parentMenu, const QString &parentAddress)
: QObject()
, d(new KBookmarkMenuPrivate())
{
d->isRoot = false;
d->manager = mgr;
d->owner = _owner;
d->parentMenu = _parentMenu;
d->parentAddress = parentAddress;
connect(_parentMenu, &QMenu::aboutToShow, this, &KBookmarkMenu::slotAboutToShow);
if (KBookmarkSettings::self()->m_contextmenu) {
d->parentMenu->setContextMenuPolicy(Qt::CustomContextMenu);
connect(d->parentMenu, &QWidget::customContextMenuRequested, this, &KBookmarkMenu::slotCustomContextMenu);
}
d->dirty = true;
}
KBookmarkMenu::~KBookmarkMenu()
{
qDeleteAll(m_lstSubMenus);
qDeleteAll(m_actions);
}
void KBookmarkMenu::ensureUpToDate()
{
slotAboutToShow();
}
void KBookmarkMenu::slotAboutToShow()
{
// Did the bookmarks change since the last time we showed them ?
if (d->dirty) {
d->dirty = false;
clear();
refill();
d->parentMenu->adjustSize();
}
}
void KBookmarkMenu::slotCustomContextMenu(const QPoint &pos)
{
QAction *action = d->parentMenu->actionAt(pos);
QMenu *menu = contextMenu(action);
if (!menu) {
return;
}
menu->setAttribute(Qt::WA_DeleteOnClose);
menu->popup(d->parentMenu->mapToGlobal(pos));
}
QMenu *KBookmarkMenu::contextMenu(QAction *action)
{
KBookmarkActionInterface *act = dynamic_cast<KBookmarkActionInterface *>(action);
if (!act) {
return nullptr;
}
return new KBookmarkContextMenu(act->bookmark(), d->manager, d->owner);
}
bool KBookmarkMenu::isRoot() const
{
return d->isRoot;
}
bool KBookmarkMenu::isDirty() const
{
return d->dirty;
}
QString KBookmarkMenu::parentAddress() const
{
return d->parentAddress;
}
KBookmarkManager *KBookmarkMenu::manager() const
{
return d->manager;
}
KBookmarkOwner *KBookmarkMenu::owner() const
{
return d->owner;
}
QMenu *KBookmarkMenu::parentMenu() const
{
return d->parentMenu;
}
/********************************************************************/
/********************************************************************/
/********************************************************************/
/********************************************************************/
/********************************************************************/
/********************************************************************/
void KBookmarkMenu::slotBookmarksChanged(const QString &groupAddress)
{
qCDebug(KBOOKMARKSWIDGETS_LOG) << "KBookmarkMenu::slotBookmarksChanged groupAddress: " << groupAddress;
if (groupAddress == d->parentAddress) {
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotBookmarksChanged -> setting m_bDirty on " << groupAddress;
d->dirty = true;
} else {
// Iterate recursively into child menus
for (QList<KBookmarkMenu *>::iterator it = m_lstSubMenus.begin(), end = m_lstSubMenus.end(); it != end; ++it) {
(*it)->slotBookmarksChanged(groupAddress);
}
}
}
void KBookmarkMenu::clear()
{
qDeleteAll(m_lstSubMenus);
m_lstSubMenus.clear();
for (QList<QAction *>::iterator it = m_actions.begin(), end = m_actions.end(); it != end; ++it) {
d->parentMenu->removeAction(*it);
delete *it;
}
d->parentMenu->clear();
m_actions.clear();
}
void KBookmarkMenu::refill()
{
// qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::refill()";
if (d->isRoot) {
addActions();
}
fillBookmarks();
if (!d->isRoot) {
addActions();
}
}
void KBookmarkMenu::addOpenInTabs()
{
if (!d->owner || !d->owner->supportsTabs() || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
return;
}
const QString title = tr("Open Folder in Tabs", "@action:inmenu");
QAction *paOpenFolderInTabs = new QAction(title, this);
paOpenFolderInTabs->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
paOpenFolderInTabs->setToolTip(tr("Open all bookmarks in this folder as a new tab", "@info:tooltip"));
paOpenFolderInTabs->setStatusTip(paOpenFolderInTabs->toolTip());
connect(paOpenFolderInTabs, &QAction::triggered, this, &KBookmarkMenu::slotOpenFolderInTabs);
d->parentMenu->addAction(paOpenFolderInTabs);
m_actions.append(paOpenFolderInTabs);
}
void KBookmarkMenu::addAddBookmarksList()
{
if (!d->owner || !d->owner->enableOption(KBookmarkOwner::ShowAddBookmark) || !d->owner->supportsTabs()
|| !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
return;
}
if (!d->bookmarksToFolderAction) {
const QString title = tr("Bookmark Tabs as Folder…", "@action:inmenu");
d->bookmarksToFolderAction = new QAction(title, this);
if (d->isRoot) {
d->bookmarksToFolderAction->setObjectName(QStringLiteral("add_bookmarks_list"));
}
d->bookmarksToFolderAction->setIcon(QIcon::fromTheme(QStringLiteral("bookmark-new-list")));
d->bookmarksToFolderAction->setToolTip(tr("Add a folder of bookmarks for all open tabs", "@info:tooltip"));
d->bookmarksToFolderAction->setStatusTip(d->bookmarksToFolderAction->toolTip());
connect(d->bookmarksToFolderAction, &QAction::triggered, this, &KBookmarkMenu::slotAddBookmarksList);
}
d->parentMenu->addAction(d->bookmarksToFolderAction);
}
void KBookmarkMenu::addAddBookmark()
{
if (!d->owner || !d->owner->enableOption(KBookmarkOwner::ShowAddBookmark) || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
return;
}
if (!d->addBookmarkAction) {
d->addBookmarkAction = KStandardActions::addBookmark(this, &KBookmarkMenu::slotAddBookmark, this);
if (d->isRoot) {
d->addBookmarkAction->setObjectName(QStringLiteral("add_bookmark"));
}
if (!d->isRoot) {
d->addBookmarkAction->setShortcut(QKeySequence());
}
}
d->parentMenu->addAction(d->addBookmarkAction);
}
void KBookmarkMenu::addEditBookmarks()
{
if ((d->owner && !d->owner->enableOption(KBookmarkOwner::ShowEditBookmark))
|| QStandardPaths::findExecutable(QStringLiteral(KEDITBOOKMARKS_BINARY)).isEmpty() || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
return;
}
d->editBookmarksAction = KStandardActions::editBookmarks(this, &KBookmarkMenu::slotEditBookmarks, this);
d->editBookmarksAction->setObjectName(QStringLiteral("edit_bookmarks"));
d->parentMenu->addAction(d->editBookmarksAction);
d->editBookmarksAction->setToolTip(tr("Edit your bookmark collection in a separate window", "@info:tooltip"));
d->editBookmarksAction->setStatusTip(d->editBookmarksAction->toolTip());
}
void KBookmarkMenu::slotEditBookmarks()
{
KEditBookmarks editBookmarks;
editBookmarks.setBrowserMode(d->browserMode);
auto result = editBookmarks.openForFile(d->manager->path());
if (!result.sucess()) {
QMessageBox::critical(QApplication::activeWindow(), QApplication::applicationDisplayName(), result.errorMessage());
}
}
void KBookmarkMenu::addNewFolder()
{
if (!d->owner || !d->owner->enableOption(KBookmarkOwner::ShowAddBookmark) || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
return;
}
if (!d->newBookmarkFolderAction) {
d->newBookmarkFolderAction = new QAction(tr("New Bookmark Folder…", "@action:inmenu"), this);
d->newBookmarkFolderAction->setIcon(QIcon::fromTheme(QStringLiteral("folder-new")));
d->newBookmarkFolderAction->setToolTip(tr("Create a new bookmark folder in this menu", "@info:tooltip"));
d->newBookmarkFolderAction->setStatusTip(d->newBookmarkFolderAction->toolTip());
if (d->isRoot) {
d->newBookmarkFolderAction->setObjectName(QStringLiteral("new_bookmark_folder"));
}
connect(d->newBookmarkFolderAction, &QAction::triggered, this, &KBookmarkMenu::slotNewFolder);
}
d->parentMenu->addAction(d->newBookmarkFolderAction);
}
void KBookmarkMenu::fillBookmarks()
{
KBookmarkGroup parentBookmark = d->manager->findByAddress(d->parentAddress).toGroup();
Q_ASSERT(!parentBookmark.isNull());
if (d->isRoot && !parentBookmark.first().isNull()) { // at least one bookmark
d->parentMenu->addSeparator();
}
for (KBookmark bm = parentBookmark.first(); !bm.isNull(); bm = parentBookmark.next(bm)) {
d->parentMenu->addAction(actionForBookmark(bm));
}
}
QAction *KBookmarkMenu::actionForBookmark(const KBookmark &bm)
{
if (bm.isGroup()) {
// qCDebug(KBOOKMARKS_LOG) << "Creating bookmark submenu named " << bm.text();
KActionMenu *actionMenu = new KBookmarkActionMenu(bm, this);
m_actions.append(actionMenu);
KBookmarkMenu *subMenu = new KBookmarkMenu(d->manager, d->owner, actionMenu->menu(), bm.address());
m_lstSubMenus.append(subMenu);
return actionMenu;
} else if (bm.isSeparator()) {
QAction *sa = new QAction(this);
sa->setSeparator(true);
m_actions.append(sa);
return sa;
} else {
// qCDebug(KBOOKMARKS_LOG) << "Creating bookmark menu item for " << bm.text();
QAction *action = new KBookmarkAction(bm, d->owner, this);
m_actions.append(action);
return action;
}
}
void KBookmarkMenu::slotAddBookmarksList()
{
if (!d->owner || !d->owner->supportsTabs()) {
return;
}
KBookmarkGroup parentBookmark = d->manager->findByAddress(d->parentAddress).toGroup();
KBookmarkDialog *dlg = new KBookmarkDialog(d->manager, QApplication::activeWindow());
dlg->addBookmarks(d->owner->currentBookmarkList(), QLatin1String(""), parentBookmark);
delete dlg;
}
void KBookmarkMenu::slotAddBookmark()
{
if (!d->owner) {
return;
}
if (d->owner->currentTitle().isEmpty() && d->owner->currentUrl().isEmpty()) {
return;
}
KBookmarkGroup parentBookmark = d->manager->findByAddress(d->parentAddress).toGroup();
if (KBookmarkSettings::self()->m_advancedaddbookmark) {
KBookmarkDialog *dlg = new KBookmarkDialog(d->manager, QApplication::activeWindow());
dlg->addBookmark(d->owner->currentTitle(), d->owner->currentUrl(), d->owner->currentIcon(), parentBookmark);
delete dlg;
} else {
parentBookmark.addBookmark(d->owner->currentTitle(), d->owner->currentUrl(), d->owner->currentIcon());
d->manager->emitChanged(parentBookmark);
}
}
void KBookmarkMenu::slotOpenFolderInTabs()
{
d->owner->openFolderinTabs(d->manager->findByAddress(d->parentAddress).toGroup());
}
void KBookmarkMenu::slotNewFolder()
{
if (!d->owner) {
return; // this view doesn't handle bookmarks...
}
KBookmarkGroup parentBookmark = d->manager->findByAddress(d->parentAddress).toGroup();
Q_ASSERT(!parentBookmark.isNull());
KBookmarkDialog *dlg = new KBookmarkDialog(d->manager, QApplication::activeWindow());
dlg->createNewFolder(QLatin1String(""), parentBookmark);
delete dlg;
}
QAction *KBookmarkMenu::addBookmarkAction() const
{
return d->addBookmarkAction;
}
QAction *KBookmarkMenu::bookmarkTabsAsFolderAction() const
{
return d->bookmarksToFolderAction;
}
QAction *KBookmarkMenu::newBookmarkFolderAction() const
{
return d->newBookmarkFolderAction;
}
QAction *KBookmarkMenu::editBookmarksAction() const
{
return d->editBookmarksAction;
}
void KBookmarkMenu::setBrowserMode(bool browserMode)
{
d->browserMode = browserMode;
}
bool KBookmarkMenu::browserMode() const
{
return d->browserMode;
}
#include "moc_kbookmarkmenu.cpp"
@@ -0,0 +1,213 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef __kbookmarkmenu_h__
#define __kbookmarkmenu_h__
#include <kbookmarkswidgets_export.h>
#include <QObject>
#include <memory>
class QAction;
class QMenu;
class KBookmark;
class KBookmarkManager;
class KBookmarkOwner;
class KBookmarkMenu;
class KBookmarkMenuPrivate;
/**
* @class KBookmarkMenu kbookmarkmenu.h KBookmarkMenu
*
* This class provides a bookmark menu. It is typically used in
* cooperation with KActionMenu but doesn't have to be.
*
* If you use this class by itself, then it will use KDE defaults for
* everything -- the bookmark path, bookmark editor, bookmark launcher..
* everything. These defaults reside in the classes
* KBookmarkOwner (editing bookmarks) and KBookmarkManager
* (almost everything else). If you wish to change the defaults in
* any way, you must reimplement either this class or KBookmarkOwner.
*
* Using this class is very simple:
*
* 1) Create a popup menu (either KActionMenu or QMenu will do)
* 2) Instantiate a new KBookmarkMenu object using the above popup
* menu as a parameter
* 3) Insert your (now full) popup menu wherever you wish
*
* The functionality of this class can be disabled with the "action/bookmarks"
* Kiosk action (see the KAuthorized namespace).
*/
class KBOOKMARKSWIDGETS_EXPORT KBookmarkMenu : public QObject
{
Q_OBJECT
public:
/**
* Fills a bookmark menu
* (one instance of KBookmarkMenu is created for the toplevel menu,
* but also one per submenu).
*
* @param manager the bookmark manager to use (i.e. for reading and writing)
* @param owner implementation of the KBookmarkOwner callback interface.
* @note If you pass a null KBookmarkOwner to the constructor, the
* openBookmark signal is not emitted, instead QDesktopServices::openUrl is used to open the bookmark.
* @param parentMenu menu to be filled
* @since 5.69
*/
KBookmarkMenu(KBookmarkManager *manager, KBookmarkOwner *owner, QMenu *parentMenu);
/**
* Creates a bookmark submenu
*
* @todo KF6: give ownership of the bookmarkmenu to another qobject, e.g. parentMenu.
* Currently this is a QObject without a parent, use setParent to benefit from automatic deletion.
*/
KBookmarkMenu(KBookmarkManager *mgr, KBookmarkOwner *owner, QMenu *parentMenu, const QString &parentAddress);
~KBookmarkMenu() override;
/**
* Call ensureUpToDate() if you need KBookmarkMenu to adjust to its
* final size before it is executed.
**/
void ensureUpToDate();
/**
* Returns the action for adding a bookmark. If you are using KXmlGui, you can add it to your
* action collection.
* @code
* KBookmarkMenu *menu = new KBookmarkMenu(manager, owner, parentMenu);
* QAction *addAction = menu->addBookmarkAction();
* actionCollection()->addAction(addAction->objectName(), addAction);
* @endcode
* @return the action for adding a bookmark.
* @since 5.69
*/
QAction *addBookmarkAction() const;
/**
* Returns the action for adding all current tabs as bookmarks. If you are using KXmlGui, you can
* add it to your action collection.
* @code
* KBookmarkMenu *menu = new KBookmarkMenu(manager, owner, parentMenu);
* QAction *bookmarkTabsAction = menu->bookmarkTabsAsFolderAction();
* actionCollection()->addAction(bookmarkTabsAction->objectName(), bookmarkTabsAction);
* @endcode
* @return the action for adding all current tabs as bookmarks.
* @since 5.69
*/
QAction *bookmarkTabsAsFolderAction() const;
/**
* Returns the action for adding a new bookmarks folder. If you are using KXmlGui, you can add it
* to your action collection.
* @code
* KBookmarkMenu *menu = new KBookmarkMenu(manager, owner, parentMenu);
* QAction *newBookmarkFolderAction = menu->bookmarkTabsAsFolderAction();
* actionCollection()->addAction(newBookmarkFolderAction->objectName(), newBookmarkFolderAction);
* @endcode
* @return the action for adding a new bookmarks folder
* @since 5.70
*/
QAction *newBookmarkFolderAction() const;
/**
* Returns the action for editing bookmarks. If you are using KXmlGui, you can add it to your
* action collection.
* @code
* KBookmarkMenu *menu = new KBookmarkMenu(manager, owner, parentMenu);
* QAction *editAction = menu->editBookmarksAction();
* actionCollection()->addAction(editAction->objectName(), editAction);
* @endcode
* @return the action for editing bookmarks.
* @since 5.69
*/
QAction *editBookmarksAction() const;
/**
* Set this to true to make any "Edit Bookmarks" dialog
* show UI elements that are specific to browsers.
*
* @since 6.0
*/
void setBrowserMode(bool browserMode);
/**
* Whether any "Edit Bookmarks" dialog shows UI elements
* that are specific to browsers.
*
* @since 6.0
*/
bool browserMode() const;
public Q_SLOTS:
// public for KonqBookmarkBar
void slotBookmarksChanged(const QString &);
protected Q_SLOTS:
void slotAboutToShow();
void slotAddBookmarksList();
void slotAddBookmark();
void slotNewFolder();
void slotOpenFolderInTabs();
protected:
virtual void clear();
virtual void refill();
virtual QAction *actionForBookmark(const KBookmark &bm);
virtual QMenu *contextMenu(QAction *action);
void addActions();
void fillBookmarks();
void addAddBookmark();
void addAddBookmarksList();
void addEditBookmarks();
void addNewFolder();
void addOpenInTabs();
bool isRoot() const;
bool isDirty() const;
/**
* Parent bookmark for this menu.
*/
QString parentAddress() const;
KBookmarkManager *manager() const;
KBookmarkOwner *owner() const;
/**
* The menu in which we insert our actions
* Supplied in the constructor.
*/
QMenu *parentMenu() const;
/**
* List of our sub menus
*/
QList<KBookmarkMenu *> m_lstSubMenus;
/**
* List of our actions.
*/
QList<QAction *> m_actions;
private Q_SLOTS:
KBOOKMARKSWIDGETS_NO_EXPORT void slotCustomContextMenu(const QPoint &);
private:
void slotEditBookmarks();
KBOOKMARKSWIDGETS_NO_EXPORT void init();
private:
std::unique_ptr<KBookmarkMenuPrivate> const d;
};
#endif
@@ -0,0 +1,32 @@
// -*- c-basic-offset:4; indent-tabs-mode:nil -*-
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2003 Alexander Kellett <lypanov@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef __kbookmarkmenu_p_h__
#define __kbookmarkmenu_p_h__
#include <QTreeWidget>
#include "kbookmark.h"
class QString;
class KBookmark;
class KBookmarkGroup;
class KBookmarkTreeItem : public QTreeWidgetItem
{
public:
explicit KBookmarkTreeItem(QTreeWidget *tree);
KBookmarkTreeItem(QTreeWidgetItem *parent, QTreeWidget *tree, const KBookmarkGroup &bk);
~KBookmarkTreeItem() override;
QString address();
private:
QString m_address;
};
#endif