1 // -*- c-basic-offset:4; indent-tabs-mode:nil -*-
2 /*
3 This file is part of the KDE libraries
4 SPDX-FileCopyrightText: 2007 Daniel Teske <teske@squorn.de>
5
6 SPDX-License-Identifier: LGPL-2.0-only
7 */
8
9 #include "kbookmarkdialog.h"
10 #include "kbookmarkdialog_p.h"
11 #include "kbookmarkmanager.h"
12 #include "kbookmarkmenu.h"
13 #include "kbookmarkmenu_p.h"
14
15 #include <QDialogButtonBox>
16 #include <QFormLayout>
17 #include <QHeaderView>
18 #include <QIcon>
19 #include <QInputDialog>
20 #include <QLabel>
21 #include <QLineEdit>
22 #include <QPushButton>
23 #include <QTreeWidget>
24
25 #include <KGuiItem>
26
KBookmarkDialogPrivate(KBookmarkDialog * qq)27 KBookmarkDialogPrivate::KBookmarkDialogPrivate(KBookmarkDialog *qq)
28 : q(qq)
29 , folderTree(nullptr)
30 , layout(false)
31 {
32 }
33
~KBookmarkDialogPrivate()34 KBookmarkDialogPrivate::~KBookmarkDialogPrivate()
35 {
36 }
37
initLayout()38 void KBookmarkDialogPrivate::initLayout()
39 {
40 QBoxLayout *vbox = new QVBoxLayout(q);
41
42 QFormLayout *form = new QFormLayout();
43 vbox->addLayout(form);
44
45 form->addRow(titleLabel, title);
46 form->addRow(urlLabel, url);
47 form->addRow(commentLabel, comment);
48
49 vbox->addWidget(folderTree);
50 vbox->addWidget(buttonBox);
51 }
52
initLayoutPrivate()53 void KBookmarkDialogPrivate::initLayoutPrivate()
54 {
55 title = new QLineEdit(q);
56 title->setMinimumWidth(300);
57 titleLabel = new QLabel(KBookmarkDialog::tr("Name:", "@label:textbox"), q);
58 titleLabel->setBuddy(title);
59
60 url = new QLineEdit(q);
61 url->setMinimumWidth(300);
62 urlLabel = new QLabel(KBookmarkDialog::tr("Location:", "@label:textbox"), q);
63 urlLabel->setBuddy(url);
64
65 comment = new QLineEdit(q);
66 comment->setMinimumWidth(300);
67 commentLabel = new QLabel(KBookmarkDialog::tr("Comment:", "@label:textbox"), q);
68 commentLabel->setBuddy(comment);
69
70 folderTree = new QTreeWidget(q);
71 folderTree->setColumnCount(1);
72 folderTree->header()->hide();
73 folderTree->setSortingEnabled(false);
74 folderTree->setSelectionMode(QTreeWidget::SingleSelection);
75 folderTree->setSelectionBehavior(QTreeWidget::SelectRows);
76 folderTree->setMinimumSize(60, 100);
77 QTreeWidgetItem *root = new KBookmarkTreeItem(folderTree);
78 fillGroup(root, mgr->root());
79
80 buttonBox = new QDialogButtonBox(q);
81 buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
82 q->connect(buttonBox, &QDialogButtonBox::accepted, q, &KBookmarkDialog::accept);
83 q->connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);
84
85 initLayout();
86 layout = true;
87 }
88
fillGroup(QTreeWidgetItem * parentItem,const KBookmarkGroup & group,const KBookmarkGroup & selectGroup)89 void KBookmarkDialogPrivate::fillGroup(QTreeWidgetItem *parentItem, const KBookmarkGroup &group, const KBookmarkGroup &selectGroup)
90 {
91 for (KBookmark bk = group.first(); !bk.isNull(); bk = group.next(bk)) {
92 if (bk.isGroup()) {
93 const KBookmarkGroup bkGroup = bk.toGroup();
94 QTreeWidgetItem *item = new KBookmarkTreeItem(parentItem, folderTree, bkGroup);
95 if (selectGroup == bkGroup) {
96 folderTree->setCurrentItem(item);
97 }
98 fillGroup(item, bkGroup, selectGroup);
99 }
100 }
101 }
102
setParentBookmark(const KBookmark & bm)103 void KBookmarkDialogPrivate::setParentBookmark(const KBookmark &bm)
104 {
105 QString address = bm.address();
106 KBookmarkTreeItem *item = static_cast<KBookmarkTreeItem *>(folderTree->topLevelItem(0));
107 while (true) {
108 if (item->address() == bm.address()) {
109 folderTree->setCurrentItem(item);
110 return;
111 }
112 for (int i = 0; i < item->childCount(); ++i) {
113 KBookmarkTreeItem *child = static_cast<KBookmarkTreeItem *>(item->child(i));
114 if (KBookmark::commonParent(child->address(), address) == child->address()) {
115 item = child;
116 break;
117 }
118 }
119 }
120 }
121
parentBookmark()122 KBookmarkGroup KBookmarkDialogPrivate::parentBookmark()
123 {
124 KBookmarkTreeItem *item = dynamic_cast<KBookmarkTreeItem *>(folderTree->currentItem());
125 if (!item) {
126 return mgr->root();
127 }
128 const QString &address = item->address();
129 return mgr->findByAddress(address).toGroup();
130 }
131
accept()132 void KBookmarkDialog::accept()
133 {
134 if (d->mode == KBookmarkDialogPrivate::NewFolder) {
135 KBookmarkGroup parent = d->parentBookmark();
136 if (d->title->text().isEmpty()) {
137 d->title->setText(QStringLiteral("New Folder"));
138 }
139 d->bm = parent.createNewFolder(d->title->text());
140 d->bm.setDescription(d->comment->text());
141 d->mgr->emitChanged(parent);
142 } else if (d->mode == KBookmarkDialogPrivate::NewBookmark) {
143 KBookmarkGroup parent = d->parentBookmark();
144 if (d->title->text().isEmpty()) {
145 d->title->setText(QStringLiteral("New Bookmark"));
146 }
147 d->bm = parent.addBookmark(d->title->text(), QUrl(d->url->text()), d->icon);
148 d->bm.setDescription(d->comment->text());
149 d->mgr->emitChanged(parent);
150 } else if (d->mode == KBookmarkDialogPrivate::NewMultipleBookmarks) {
151 KBookmarkGroup parent = d->parentBookmark();
152 if (d->title->text().isEmpty()) {
153 d->title->setText(QStringLiteral("New Folder"));
154 }
155 d->bm = parent.createNewFolder(d->title->text());
156 d->bm.setDescription(d->comment->text());
157 for (const KBookmarkOwner::FutureBookmark &fb : std::as_const(d->list)) {
158 d->bm.toGroup().addBookmark(fb.title(), fb.url(), fb.icon());
159 }
160 d->mgr->emitChanged(parent);
161 } else if (d->mode == KBookmarkDialogPrivate::EditBookmark) {
162 d->bm.setFullText(d->title->text());
163 d->bm.setUrl(QUrl(d->url->text()));
164 d->bm.setDescription(d->comment->text());
165 d->mgr->emitChanged(d->bm.parentGroup());
166 } else if (d->mode == d->SelectFolder) {
167 d->bm = d->parentBookmark();
168 }
169 QDialog::accept();
170 }
171
editBookmark(const KBookmark & bm)172 KBookmark KBookmarkDialog::editBookmark(const KBookmark &bm)
173 {
174 if (!d->layout) {
175 d->initLayoutPrivate();
176 }
177
178 KGuiItem::assign(d->buttonBox->button(QDialogButtonBox::Ok), KGuiItem(tr("Update", "@action:button")));
179 setWindowTitle(tr("Bookmark Properties", "@title:window"));
180 d->url->setVisible(!bm.isGroup());
181 d->urlLabel->setVisible(!bm.isGroup());
182 d->bm = bm;
183 d->title->setText(bm.fullText());
184 d->url->setText(bm.url().toString());
185 d->comment->setVisible(true);
186 d->commentLabel->setVisible(true);
187 d->comment->setText(bm.description());
188 d->folderTree->setVisible(false);
189
190 d->mode = KBookmarkDialogPrivate::EditBookmark;
191
192 if (exec() == QDialog::Accepted) {
193 return d->bm;
194 } else {
195 return KBookmark();
196 }
197 }
198
addBookmark(const QString & title,const QUrl & url,const QString & icon,KBookmark parent)199 KBookmark KBookmarkDialog::addBookmark(const QString &title, const QUrl &url, const QString &icon, KBookmark parent)
200 {
201 if (!d->layout) {
202 d->initLayoutPrivate();
203 }
204 if (parent.isNull()) {
205 parent = d->mgr->root();
206 }
207
208 QPushButton *newButton = new QPushButton;
209 KGuiItem::assign(newButton, KGuiItem(tr("&New Folder...", "@action:button"), QStringLiteral("folder-new")));
210 d->buttonBox->addButton(newButton, QDialogButtonBox::ActionRole);
211 connect(newButton, &QAbstractButton::clicked, this, &KBookmarkDialog::newFolderButton);
212
213 KGuiItem::assign(d->buttonBox->button(QDialogButtonBox::Ok), KGuiItem(tr("Add", "@action:button"), QStringLiteral("bookmark-new")));
214 setWindowTitle(tr("Add Bookmark", "@title:window"));
215 d->url->setVisible(true);
216 d->urlLabel->setVisible(true);
217 d->title->setText(title);
218 d->url->setText(url.toString());
219 d->comment->setText(QString());
220 d->comment->setVisible(true);
221 d->commentLabel->setVisible(true);
222 d->setParentBookmark(parent);
223 d->folderTree->setVisible(true);
224 d->icon = icon;
225
226 d->mode = KBookmarkDialogPrivate::NewBookmark;
227
228 if (exec() == QDialog::Accepted) {
229 return d->bm;
230 } else {
231 return KBookmark();
232 }
233 }
234
addBookmarks(const QList<KBookmarkOwner::FutureBookmark> & list,const QString & name,KBookmarkGroup parent)235 KBookmarkGroup KBookmarkDialog::addBookmarks(const QList<KBookmarkOwner::FutureBookmark> &list, const QString &name, KBookmarkGroup parent)
236 {
237 if (!d->layout) {
238 d->initLayoutPrivate();
239 }
240 if (parent.isNull()) {
241 parent = d->mgr->root();
242 }
243
244 d->list = list;
245
246 QPushButton *newButton = new QPushButton;
247 KGuiItem::assign(newButton, KGuiItem(tr("&New Folder...", "@action:button"), QStringLiteral("folder-new")));
248 d->buttonBox->addButton(newButton, QDialogButtonBox::ActionRole);
249 connect(newButton, &QAbstractButton::clicked, this, &KBookmarkDialog::newFolderButton);
250
251 KGuiItem::assign(d->buttonBox->button(QDialogButtonBox::Ok), KGuiItem(tr("Add", "@action:button"), QStringLiteral("bookmark-new")));
252 setWindowTitle(tr("Add Bookmarks", "@title:window"));
253 d->url->setVisible(false);
254 d->urlLabel->setVisible(false);
255 d->title->setText(name);
256 d->comment->setVisible(true);
257 d->commentLabel->setVisible(true);
258 d->comment->setText(QString());
259 d->setParentBookmark(parent);
260 d->folderTree->setVisible(true);
261
262 d->mode = KBookmarkDialogPrivate::NewMultipleBookmarks;
263
264 if (exec() == QDialog::Accepted) {
265 return d->bm.toGroup();
266 } else {
267 return KBookmarkGroup();
268 }
269 }
270
selectFolder(KBookmark parent)271 KBookmarkGroup KBookmarkDialog::selectFolder(KBookmark parent)
272 {
273 if (!d->layout) {
274 d->initLayoutPrivate();
275 }
276 if (parent.isNull()) {
277 parent = d->mgr->root();
278 }
279
280 QPushButton *newButton = new QPushButton;
281 KGuiItem::assign(newButton, KGuiItem(tr("&New Folder...", "@action:button"), QStringLiteral("folder-new")));
282 d->buttonBox->addButton(newButton, QDialogButtonBox::ActionRole);
283 connect(newButton, &QAbstractButton::clicked, this, &KBookmarkDialog::newFolderButton);
284
285 setWindowTitle(tr("Select Folder", "@title:window"));
286 d->url->setVisible(false);
287 d->urlLabel->setVisible(false);
288 d->title->setVisible(false);
289 d->titleLabel->setVisible(false);
290 d->comment->setVisible(false);
291 d->commentLabel->setVisible(false);
292 d->setParentBookmark(parent);
293 d->folderTree->setVisible(true);
294
295 d->mode = d->SelectFolder;
296
297 if (exec() == QDialog::Accepted) {
298 return d->bm.toGroup();
299 } else {
300 return KBookmarkGroup();
301 }
302 }
303
createNewFolder(const QString & name,KBookmark parent)304 KBookmarkGroup KBookmarkDialog::createNewFolder(const QString &name, KBookmark parent)
305 {
306 if (!d->layout) {
307 d->initLayoutPrivate();
308 }
309 if (parent.isNull()) {
310 parent = d->mgr->root();
311 }
312
313 setWindowTitle(tr("New Folder", "@title:window"));
314 d->url->setVisible(false);
315 d->urlLabel->setVisible(false);
316 d->comment->setVisible(true);
317 d->commentLabel->setVisible(true);
318 d->comment->setText(QString());
319 d->title->setText(name);
320 d->setParentBookmark(parent);
321 d->folderTree->setVisible(true);
322
323 d->mode = KBookmarkDialogPrivate::NewFolder;
324
325 if (exec() == QDialog::Accepted) {
326 return d->bm.toGroup();
327 } else {
328 return KBookmarkGroup();
329 }
330 }
331
KBookmarkDialog(KBookmarkManager * mgr,QWidget * parent)332 KBookmarkDialog::KBookmarkDialog(KBookmarkManager *mgr, QWidget *parent)
333 : QDialog(parent)
334 , d(new KBookmarkDialogPrivate(this))
335 {
336 d->mgr = mgr;
337 }
338
339 KBookmarkDialog::~KBookmarkDialog() = default;
340
newFolderButton()341 void KBookmarkDialog::newFolderButton()
342 {
343 QString caption = d->parentBookmark().fullText().isEmpty() ? tr("Create New Bookmark Folder", "@title:window")
344 : tr("Create New Bookmark Folder in %1", "@title:window").arg(d->parentBookmark().text());
345 bool ok;
346 QString text = QInputDialog::getText(this, caption, tr("New folder:", "@label:textbox"), QLineEdit::Normal, QString(), &ok);
347 if (!ok) {
348 return;
349 }
350
351 KBookmarkGroup group = d->parentBookmark().createNewFolder(text);
352 if (!group.isNull()) {
353 KBookmarkGroup parentGroup = group.parentGroup();
354 d->mgr->emitChanged(parentGroup);
355 d->folderTree->clear();
356 QTreeWidgetItem *root = new KBookmarkTreeItem(d->folderTree);
357 d->fillGroup(root, d->mgr->root(), group);
358 }
359 }
360
361 /********************************************************************/
362
KBookmarkTreeItem(QTreeWidget * tree)363 KBookmarkTreeItem::KBookmarkTreeItem(QTreeWidget *tree)
364 : QTreeWidgetItem(tree)
365 , m_address(QLatin1String(""))
366 {
367 setText(0, KBookmarkDialog::tr("Bookmarks", "name of the container of all browser bookmarks"));
368 setIcon(0, QIcon::fromTheme(QStringLiteral("bookmarks")));
369 tree->expandItem(this);
370 tree->setCurrentItem(this);
371 setSelected(true);
372 }
373
KBookmarkTreeItem(QTreeWidgetItem * parent,QTreeWidget * tree,const KBookmarkGroup & bk)374 KBookmarkTreeItem::KBookmarkTreeItem(QTreeWidgetItem *parent, QTreeWidget *tree, const KBookmarkGroup &bk)
375 : QTreeWidgetItem(parent)
376 {
377 setIcon(0, QIcon::fromTheme(bk.icon()));
378 setText(0, bk.fullText());
379 tree->expandItem(this);
380 m_address = bk.address();
381 }
382
~KBookmarkTreeItem()383 KBookmarkTreeItem::~KBookmarkTreeItem()
384 {
385 }
386
address()387 QString KBookmarkTreeItem::address()
388 {
389 return m_address;
390 }
391