1 /***************************************************************************
2     Private classes for the bookmark handler
3                              -------------------
4     begin                : Sun Mar 20 2011
5     copyright            : (C) 2011-2020 by Alexander Reinholdt
6     email                : alexander.reinholdt@kdemail.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful, but   *
16  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
18  *   General Public License for more details.                              *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, 51 Franklin Street, Suite 500, Boston,      *
23  *   MA 02110-1335, USA                                                    *
24  ***************************************************************************/
25 
26 // application specific includes
27 #include "smb4kbookmarkhandler_p.h"
28 #include "smb4ksettings.h"
29 #include "smb4kbookmark.h"
30 
31 // Qt includes
32 #include <QEvent>
33 #include <QTimer>
34 #include <QVBoxLayout>
35 #include <QHBoxLayout>
36 #include <QGridLayout>
37 #include <QLabel>
38 #include <QHeaderView>
39 #include <QTreeWidgetItemIterator>
40 #include <QPushButton>
41 #include <QMenu>
42 #include <QInputDialog>
43 #include <QDialogButtonBox>
44 #include <QDropEvent>
45 #include <QDragMoveEvent>
46 #include <QDragEnterEvent>
47 #include <QDragLeaveEvent>
48 #include <QWindow>
49 
50 // KDE includes
51 #define TRANSLATION_DOMAIN "smb4k-core"
52 #include <KI18n/KLocalizedString>
53 #include <KIconThemes/KIconLoader>
54 #include <KConfigGui/KWindowConfig>
55 #include <KCompletion/KComboBox>
56 #include <KCompletion/KLineEdit>
57 
58 
Smb4KBookmarkDialog(const QList<BookmarkPtr> & bookmarks,const QStringList & categories,QWidget * parent)59 Smb4KBookmarkDialog::Smb4KBookmarkDialog(const QList<BookmarkPtr> &bookmarks, const QStringList &categories, QWidget *parent)
60 : QDialog(parent)
61 {
62   //
63   // Set the window title
64   //
65   setWindowTitle(i18n("Add Bookmarks"));
66 
67   //
68   // Setup the view
69   //
70   setupView();
71 
72   //
73   // Load the list of bookmarks and categories
74   //
75   loadLists(bookmarks, categories);
76 
77   //
78   // Set the dialog size
79   //
80   create();
81 
82   KConfigGroup group(Smb4KSettings::self()->config(), "BookmarkDialog");
83   QSize dialogSize;
84 
85   if (group.exists())
86   {
87     KWindowConfig::restoreWindowSize(windowHandle(), group);
88     dialogSize = windowHandle()->size();
89   }
90   else
91   {
92     dialogSize = sizeHint();
93   }
94 
95   resize(dialogSize); // workaround for QTBUG-40584
96 
97   //
98   // Fill the completion objects
99   //
100   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
101 
102   if (group.hasKey("GroupCompletion"))
103   {
104     // For backward compatibility (since Smb4K 3.0.72).
105     categoryCombo->completionObject()->setItems(group.readEntry("GroupCompletion", m_categories));
106     group.deleteEntry("GroupCompletion");
107   }
108   else
109   {
110     categoryCombo->completionObject()->setItems(group.readEntry("CategoryCompletion", m_categories));
111   }
112 
113   KLineEdit *labelEdit = findChild<KLineEdit *>("LabelEdit");
114   labelEdit->completionObject()->setItems(group.readEntry("LabelCompletion", QStringList()));
115 
116   //
117   // Connections
118   //
119   connect(KIconLoader::global(), SIGNAL(iconChanged(int)), SLOT(slotIconSizeChanged(int)));
120 }
121 
122 
~Smb4KBookmarkDialog()123 Smb4KBookmarkDialog::~Smb4KBookmarkDialog()
124 {
125   while (!m_bookmarks.isEmpty())
126   {
127     m_bookmarks.takeFirst().clear();
128   }
129 }
130 
131 
bookmarks()132 const QList<BookmarkPtr> &Smb4KBookmarkDialog::bookmarks()
133 {
134   return m_bookmarks;
135 }
136 
137 
setupView()138 void Smb4KBookmarkDialog::setupView()
139 {
140   QVBoxLayout *layout = new QVBoxLayout(this);
141 
142   QWidget *description = new QWidget(this);
143   QHBoxLayout *descriptionLayout = new QHBoxLayout(description);
144   descriptionLayout->setContentsMargins(0, 0, 0, 0);
145 
146   QLabel *pixmap = new QLabel(description);
147   QPixmap sync_pix = KDE::icon("bookmark-new").pixmap(KIconLoader::SizeHuge);
148   pixmap->setPixmap(sync_pix);
149   pixmap->setAlignment(Qt::AlignBottom);
150 
151   QLabel *label = new QLabel(i18n("All listed shares will be bookmarked. To edit the label "
152                                   "or group, click the respective bookmark entry."), description);
153   label->setWordWrap(true);
154   label->setAlignment(Qt::AlignBottom);
155 
156   descriptionLayout->addWidget(pixmap, 0);
157   descriptionLayout->addWidget(label, Qt::AlignBottom);
158 
159   QListWidget *listWidget = new QListWidget(this);
160   listWidget->setObjectName("BookmarksListWidget");
161   listWidget->setSortingEnabled(true);
162   listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
163   int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
164   listWidget->setIconSize(QSize(iconSize, iconSize));
165 
166   QWidget *editorWidgets = new QWidget(this);
167   editorWidgets->setObjectName("EditorWidgets");
168   editorWidgets->setEnabled(false);
169 
170   QGridLayout *editorWidgetsLayout = new QGridLayout(editorWidgets);
171   editorWidgetsLayout->setContentsMargins(0, 0, 0, 0);
172 
173   //
174   // The label editor
175   //
176   QLabel *labelLabel = new QLabel(i18n("Label:"), editorWidgets);
177   KLineEdit *labelEdit = new KLineEdit(editorWidgets);
178   labelEdit->setObjectName("LabelEdit");
179   labelEdit->setClearButtonEnabled(true);
180 
181   //
182   // The category editor
183   //
184   QLabel *categoryLabel = new QLabel(i18n("Category:"), editorWidgets);
185   KComboBox *categoryCombo = new KComboBox(true, editorWidgets);
186   categoryCombo->setObjectName("CategoryCombo");
187 
188   editorWidgetsLayout->addWidget(labelLabel, 0, 0);
189   editorWidgetsLayout->addWidget(labelEdit, 0, 1);
190   editorWidgetsLayout->addWidget(categoryLabel, 1, 0);
191   editorWidgetsLayout->addWidget(categoryCombo, 1, 1);
192 
193   QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this);
194   QPushButton *okButton = buttonBox->addButton(QDialogButtonBox::Ok);
195   QPushButton *cancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);
196 
197   okButton->setShortcut(Qt::CTRL|Qt::Key_Return);
198   cancelButton->setShortcut(Qt::Key_Escape);
199 
200   okButton->setDefault(true);
201 
202   layout->addWidget(description, 0);
203   layout->addWidget(listWidget, 0);
204   layout->addWidget(editorWidgets, 0);
205   layout->addWidget(buttonBox, 0);
206 
207   //
208   // Connections
209   //
210   connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(slotBookmarkClicked(QListWidgetItem*)));
211   connect(labelEdit, SIGNAL(editingFinished()), this, SLOT(slotLabelEdited()));
212   connect(categoryCombo->lineEdit(), SIGNAL(editingFinished()), this, SLOT(slotCategoryEdited()));
213   connect(okButton, SIGNAL(clicked()), this, SLOT(slotDialogAccepted()));
214   connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
215 }
216 
217 
loadLists(const QList<BookmarkPtr> & bookmarks,const QStringList & categories)218 void Smb4KBookmarkDialog::loadLists(const QList<BookmarkPtr> &bookmarks, const QStringList &categories)
219 {
220   //
221   // Get the category combo box
222   //
223   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
224   QListWidget *listWidget = findChild<QListWidget *>("BookmarksListWidget");
225 
226   //
227   // Copy the bookmarks to the internal list and add them to
228   // the list widget afterwards.
229   //
230   for (const BookmarkPtr &b : bookmarks)
231   {
232     QListWidgetItem *item = new QListWidgetItem(b->icon(), b->displayString(), listWidget);
233     item->setData(Qt::UserRole, static_cast<QUrl>(b->url()));
234 
235     m_bookmarks << b;
236   }
237 
238   //
239   // Copy the categories
240   //
241   m_categories = categories;
242 
243   //
244   // Add the categories to the combo box
245   //
246   categoryCombo->addItems(m_categories);
247 }
248 
249 
findBookmark(const QUrl & url)250 BookmarkPtr Smb4KBookmarkDialog::findBookmark(const QUrl &url)
251 {
252   BookmarkPtr bookmark;
253 
254   for (const BookmarkPtr &b : m_bookmarks)
255   {
256     if (b->url() == url)
257     {
258       bookmark = b;
259       break;
260     }
261     else
262     {
263       continue;
264     }
265   }
266 
267   return bookmark;
268 }
269 
270 
slotBookmarkClicked(QListWidgetItem * bookmarkItem)271 void Smb4KBookmarkDialog::slotBookmarkClicked(QListWidgetItem *bookmarkItem)
272 {
273   //
274   // Get the widgets
275   //
276   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
277   KLineEdit *labelEdit = findChild<KLineEdit *>("LabelEdit");
278   QWidget *editorWidgets = findChild<QWidget *>("EditorWidgets");
279 
280   //
281   // Modify the widgets
282   //
283   if (bookmarkItem)
284   {
285     // Enable the editor widgets if necessary
286     if (!editorWidgets->isEnabled())
287     {
288       editorWidgets->setEnabled(true);
289     }
290 
291     QUrl url = bookmarkItem->data(Qt::UserRole).toUrl();
292     BookmarkPtr bookmark = findBookmark(url);
293 
294 
295     if (bookmark)
296     {
297       labelEdit->setText(bookmark->label());
298       categoryCombo->setCurrentItem(bookmark->categoryName());
299     }
300     else
301     {
302       labelEdit->clear();
303       categoryCombo->clearEditText();
304       editorWidgets->setEnabled(false);
305     }
306   }
307   else
308   {
309     labelEdit->clear();
310     categoryCombo->clearEditText();
311     editorWidgets->setEnabled(false);
312   }
313 }
314 
315 
slotLabelEdited()316 void Smb4KBookmarkDialog::slotLabelEdited()
317 {
318   //
319   // Get the label line edit
320   //
321   KLineEdit *labelEdit = findChild<KLineEdit *>("LabelEdit");
322   QListWidget *listWidget = findChild<QListWidget *>("BookmarksListWidget");
323 
324   //
325   // Set the label
326   //
327   QUrl url = listWidget->currentItem()->data(Qt::UserRole).toUrl();
328   BookmarkPtr bookmark = findBookmark(url);
329 
330   if (bookmark)
331   {
332     bookmark->setLabel(labelEdit->userText());
333   }
334 
335   //
336   // Add label to completion object
337   //
338   KCompletion *completion = labelEdit->completionObject();
339 
340   if (!labelEdit->userText().isEmpty())
341   {
342     completion->addItem(labelEdit->userText());
343   }
344 }
345 
346 
slotCategoryEdited()347 void Smb4KBookmarkDialog::slotCategoryEdited()
348 {
349   //
350   // Get the category combo box
351   //
352   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
353   QListWidget *listWidget = findChild<QListWidget *>("BookmarksListWidget");
354 
355   //
356   // Get the bookmark
357   //
358   QUrl url = listWidget->currentItem()->data(Qt::UserRole).toUrl();
359   BookmarkPtr bookmark = findBookmark(url);
360 
361   //
362   // Set the category name
363   //
364   if (bookmark)
365   {
366     bookmark->setCategoryName(categoryCombo->currentText());
367   }
368 
369   //
370   // Add the category name to the combo box
371   //
372   if (categoryCombo->findText(categoryCombo->currentText()) == -1)
373   {
374     categoryCombo->addItem(categoryCombo->currentText());
375   }
376 
377   // Add group to completion object
378   KCompletion *completion = categoryCombo->completionObject();
379 
380   if (!categoryCombo->currentText().isEmpty())
381   {
382     completion->addItem(categoryCombo->currentText());
383   }
384 }
385 
386 
slotDialogAccepted()387 void Smb4KBookmarkDialog::slotDialogAccepted()
388 {
389   //
390   // Get the widgets
391   //
392   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
393   KLineEdit *labelEdit = findChild<KLineEdit *>("LabelEdit");
394 
395   KConfigGroup group(Smb4KSettings::self()->config(), "BookmarkDialog");
396   KWindowConfig::saveWindowSize(windowHandle(), group);
397   group.writeEntry("LabelCompletion", labelEdit->completionObject()->items());
398   group.writeEntry("CategoryCompletion", categoryCombo->completionObject()->items());
399 
400   accept();
401 }
402 
403 
slotIconSizeChanged(int group)404 void Smb4KBookmarkDialog::slotIconSizeChanged(int group)
405 {
406   //
407   // Get the list widget
408   //
409   QListWidget *listWidget = findChild<QListWidget *>("BookmarksListWidget");
410 
411   //
412   // Change the icon size
413   //
414   switch (group)
415   {
416     case KIconLoader::Small:
417     {
418       int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
419       listWidget->setIconSize(QSize(iconSize, iconSize));
420       break;
421     }
422     default:
423     {
424       break;
425     }
426   }
427 }
428 
429 
Smb4KBookmarkEditor(const QList<BookmarkPtr> & bookmarks,QWidget * parent)430 Smb4KBookmarkEditor::Smb4KBookmarkEditor(const QList<BookmarkPtr> &bookmarks, QWidget *parent)
431 : QDialog(parent), m_bookmarks(bookmarks)
432 {
433   //
434   // Set the window title
435   //
436   setWindowTitle(i18n("Edit Bookmarks"));
437 
438   //
439   // Setup the view
440   //
441   setupView();
442 
443   //
444   // Load the bookmarks into the editor
445   //
446   loadBookmarks();
447 
448   //
449   // Set the dialog size
450   //
451   create();
452 
453   KConfigGroup group(Smb4KSettings::self()->config(), "BookmarkEditor");
454   QSize dialogSize;
455 
456   if (group.exists())
457   {
458     KWindowConfig::restoreWindowSize(windowHandle(), group);
459     dialogSize = windowHandle()->size();
460   }
461   else
462   {
463     dialogSize = sizeHint();
464   }
465 
466   resize(dialogSize); // workaround for QTBUG-40584
467 
468   //
469   // Fill the completion objects
470   //
471   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
472   KLineEdit *labelEdit = findChild<KLineEdit *>("LabelEdit");
473   KLineEdit *ipEdit = findChild<KLineEdit *>("IpEdit");
474   KLineEdit *loginEdit = findChild<KLineEdit *>("LoginEdit");
475   KLineEdit *workgroupEdit = findChild<KLineEdit *>("WorkgroupEdit");
476 
477   if (group.hasKey("GroupCompletion"))
478   {
479     // For backward compatibility (since Smb4K 3.0.72).
480     categoryCombo->completionObject()->setItems(group.readEntry("GroupCompletion", m_categories));
481     group.deleteEntry("GroupCompletion");
482   }
483   else
484   {
485     categoryCombo->completionObject()->setItems(group.readEntry("CategoryCompletion", m_categories));
486   }
487 
488   labelEdit->completionObject()->setItems(group.readEntry("LabelCompletion", QStringList()));
489   ipEdit->completionObject()->setItems(group.readEntry("IPCompletion", QStringList()));
490   loginEdit->completionObject()->setItems(group.readEntry("LoginCompletion", QStringList()));
491   workgroupEdit->completionObject()->setItems(group.readEntry("WorkgroupCompletion", QStringList()));
492 
493   //
494   // Connections
495   //
496   connect(KIconLoader::global(), SIGNAL(iconChanged(int)), SLOT(slotIconSizeChanged(int)));
497 }
498 
499 
~Smb4KBookmarkEditor()500 Smb4KBookmarkEditor::~Smb4KBookmarkEditor()
501 {
502   while (!m_bookmarks.isEmpty())
503   {
504     m_bookmarks.takeFirst().clear();
505   }
506 }
507 
508 
eventFilter(QObject * obj,QEvent * e)509 bool Smb4KBookmarkEditor::eventFilter(QObject *obj, QEvent *e)
510 {
511   //
512   // Get the widget
513   //
514   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
515 
516   if (obj == treeWidget->viewport())
517   {
518     switch (e->type())
519     {
520       case QEvent::DragEnter:
521       {
522         QDragEnterEvent *ev = static_cast<QDragEnterEvent *>(e);
523 
524         if (ev->source() == treeWidget->viewport())
525         {
526           e->accept();
527         }
528         else
529         {
530           e->ignore();
531         }
532         break;
533       }
534       case QEvent::DragLeave:
535       {
536         e->ignore();
537         break;
538       }
539       case QEvent::Drop:
540       {
541         QTimer::singleShot(50, this, SLOT(slotAdjust()));
542         break;
543       }
544       default:
545       {
546         break;
547       }
548     }
549   }
550 
551   return QDialog::eventFilter(obj, e);
552 }
553 
554 
setupView()555 void Smb4KBookmarkEditor::setupView()
556 {
557   QVBoxLayout *layout = new QVBoxLayout(this);
558 
559   QTreeWidget *treeWidget = new QTreeWidget(this);
560   treeWidget->setObjectName("BookmarksTreeWidget");
561   treeWidget->setColumnCount(2);
562   treeWidget->hideColumn((treeWidget->columnCount() - 1)); // for sorting purposes
563   treeWidget->headerItem()->setHidden(true);
564   treeWidget->setRootIsDecorated(true);
565   treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
566   treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
567   treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
568   treeWidget->setDragDropMode(QTreeWidget::InternalMove);
569   int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
570   treeWidget->setIconSize(QSize(iconSize, iconSize));
571   treeWidget->viewport()->installEventFilter(this);
572 
573   QAction *addCategoryAction = new QAction(KDE::icon("bookmark-add-folder"), i18n("Add Category"), treeWidget);
574   QAction *deleteAction = new QAction(KDE::icon("edit-delete"), i18n("Remove"), treeWidget);
575   deleteAction->setObjectName("DeleteAction");
576   QAction *clearAction = new QAction(KDE::icon("edit-clear"), i18n("Clear"), treeWidget);
577 
578   KActionMenu *actionMenu = new KActionMenu(treeWidget);
579   actionMenu->setObjectName("ActionMenu");
580   actionMenu->addAction(addCategoryAction);
581   actionMenu->addAction(deleteAction);
582   actionMenu->addAction(clearAction);
583 
584   //
585   // The editor widgets
586   //
587   QWidget *editorWidgets = new QWidget(this);
588   editorWidgets->setObjectName("EditorWidgets");
589   editorWidgets->setEnabled(false);
590 
591   QGridLayout *editorsLayout = new QGridLayout(editorWidgets);
592   editorsLayout->setContentsMargins(0, 0, 0, 0);
593 
594   //
595   // The label line edit
596   //
597   QLabel *labelLabel = new QLabel(i18n("Label:"), editorWidgets);
598   KLineEdit *labelEdit = new KLineEdit(editorWidgets);
599   labelEdit->setObjectName("LabelEdit");
600   labelEdit->setClearButtonEnabled(true);
601 
602   QLabel *loginLabel = new QLabel(i18n("Login:"), editorWidgets);
603   KLineEdit *loginEdit = new KLineEdit(editorWidgets);
604   loginEdit->setObjectName("LoginEdit");
605   loginEdit->setClearButtonEnabled(true);
606 
607   //
608   // The workgroup/domain edit line
609   //
610   QLabel *workgroupLabel = new QLabel(i18n("Workgroup:"), editorWidgets);
611   KLineEdit *workgroupEdit = new KLineEdit(editorWidgets);
612   workgroupEdit->setObjectName("WorkgroupEdit");
613   workgroupEdit->setClearButtonEnabled(true);
614 
615   //
616   // The IP address line edit
617   //
618   QLabel *ipLabel = new QLabel(i18n("IP Address:"), editorWidgets);
619   KLineEdit *ipEdit = new KLineEdit(editorWidgets);
620   ipEdit->setObjectName("IpEdit");
621   ipEdit->setClearButtonEnabled(true);
622 
623   //
624   // The category combo box
625   //
626   QLabel *categoryLabel = new QLabel(i18n("Category:"), editorWidgets);
627   KComboBox *categoryCombo = new KComboBox(true, editorWidgets);
628   categoryCombo->setObjectName("CategoryCombo");
629   categoryCombo->setDuplicatesEnabled(false);
630 
631   editorsLayout->addWidget(labelLabel, 0, 0);
632   editorsLayout->addWidget(labelEdit, 0, 1);
633   editorsLayout->addWidget(loginLabel, 1, 0);
634   editorsLayout->addWidget(loginEdit, 1, 1);
635   editorsLayout->addWidget(workgroupLabel, 2, 0);
636   editorsLayout->addWidget(workgroupEdit, 2, 1);
637   editorsLayout->addWidget(ipLabel, 3, 0);
638   editorsLayout->addWidget(ipEdit, 3, 1);
639   editorsLayout->addWidget(categoryLabel, 4, 0);
640   editorsLayout->addWidget(categoryCombo, 4, 1);
641 
642   QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this);
643   QPushButton *okButton = buttonBox->addButton(QDialogButtonBox::Ok);
644   QPushButton *cancelButton = buttonBox->addButton(QDialogButtonBox::Cancel);
645 
646   okButton->setShortcut(Qt::CTRL|Qt::Key_Return);
647   cancelButton->setShortcut(Qt::Key_Escape);
648 
649   okButton->setDefault(true);
650 
651   layout->addWidget(treeWidget);
652   layout->addWidget(editorWidgets);
653   layout->addWidget(buttonBox);
654 
655   //
656   // Connections
657   //
658   connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(slotItemClicked(QTreeWidgetItem*,int)));
659   connect(treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotContextMenuRequested(QPoint)));
660   connect(labelEdit, SIGNAL(editingFinished()), this, SLOT(slotLabelEdited()));
661   connect(ipEdit, SIGNAL(editingFinished()), this, SLOT(slotIpEdited()));
662   connect(workgroupEdit, SIGNAL(editingFinished()), this, SLOT(slotWorkgroupNameEdited()));
663   connect(loginEdit, SIGNAL(editingFinished()), this, SLOT(slotLoginEdited()));
664   connect(categoryCombo->lineEdit(), SIGNAL(editingFinished()), this, SLOT(slotCategoryEdited()));
665   connect(addCategoryAction, SIGNAL(triggered(bool)), this, SLOT(slotAddCategoryTriggered(bool)));
666   connect(deleteAction, SIGNAL(triggered(bool)), this, SLOT(slotDeleteTriggered(bool)));
667   connect(clearAction, SIGNAL(triggered(bool)), this, SLOT(slotClearTriggered(bool)));
668   connect(okButton, SIGNAL(clicked()), this, SLOT(slotDialogAccepted()));
669   connect(cancelButton, SIGNAL(clicked()), this, SLOT(slotDialogRejected()));
670 }
671 
672 
loadBookmarks()673 void Smb4KBookmarkEditor::loadBookmarks()
674 {
675   //
676   // Get the widgets
677   //
678   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
679   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
680 
681   //
682   // Clear the tree widget and the group combo box
683   //
684   treeWidget->clear();
685   categoryCombo->clear();
686 
687   //
688   // Copy the groups into the internal list
689   //
690   m_categories.clear();
691 
692   for (const BookmarkPtr &bookmark : m_bookmarks)
693   {
694     if (!m_categories.contains(bookmark->categoryName()))
695     {
696       m_categories << bookmark->categoryName();
697     }
698   }
699 
700   //
701   // Insert the groups into the tree widget
702   //
703   for (const QString &category : m_categories)
704   {
705     if (!category.isEmpty())
706     {
707       QTreeWidgetItem *categoryItem = new QTreeWidgetItem(QTreeWidgetItem::UserType);
708       categoryItem->setIcon(0, KDE::icon("folder-bookmark"));
709       categoryItem->setText(0, category);
710       categoryItem->setText((treeWidget->columnCount() - 1), QString("00_%1").arg(category));
711       categoryItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsDropEnabled);
712       treeWidget->addTopLevelItem(categoryItem);
713     }
714   }
715 
716   //
717   // Insert the bookmarks info the tree widget
718   //
719   for (const BookmarkPtr &bookmark : m_bookmarks)
720   {
721     QTreeWidgetItem *bookmarkItem = new QTreeWidgetItem(QTreeWidgetItem::UserType);
722     bookmarkItem->setData(0, QTreeWidgetItem::UserType, static_cast<QUrl>(bookmark->url()));
723     bookmarkItem->setIcon(0, bookmark->icon());
724     bookmarkItem->setText(0, bookmark->displayString());
725     bookmarkItem->setText((treeWidget->columnCount() - 1), QString("01_%1").arg(bookmark->url().toString(QUrl::RemoveUserInfo|QUrl::RemovePort)));
726     bookmarkItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsDragEnabled);
727 
728     if (!bookmark->categoryName().isEmpty())
729     {
730       QList<QTreeWidgetItem *> items = treeWidget->findItems(bookmark->categoryName(), Qt::MatchFixedString|Qt::MatchCaseSensitive, 0);
731 
732       if (!items.isEmpty())
733       {
734         items.first()->addChild(bookmarkItem);
735         items.first()->setExpanded(true);
736       }
737     }
738     else
739     {
740       treeWidget->addTopLevelItem(bookmarkItem);
741     }
742   }
743 
744   //
745   // Sort
746   //
747   for (int i = 0; i < treeWidget->topLevelItemCount(); ++i)
748   {
749     treeWidget->topLevelItem(i)->sortChildren((treeWidget->columnCount() - 1), Qt::AscendingOrder);
750   }
751 
752   treeWidget->sortItems((treeWidget->columnCount() - 1), Qt::AscendingOrder);
753 
754   //
755   // Check that an empty group entry is also present. If it is not there,
756   // add it now and insert the groups to the group combo box afterwards.
757   //
758   if (!m_categories.contains("") && !m_categories.contains(QString()))
759   {
760     m_categories << "";
761   }
762 
763   categoryCombo->addItems(m_categories);
764   categoryCombo->setCurrentItem("");
765 }
766 
767 
editedBookmarks()768 QList<BookmarkPtr> Smb4KBookmarkEditor::editedBookmarks()
769 {
770   return m_bookmarks;
771 }
772 
773 
774 
findBookmark(const QUrl & url)775 BookmarkPtr Smb4KBookmarkEditor::findBookmark(const QUrl &url)
776 {
777   BookmarkPtr bookmark;
778 
779   for (const BookmarkPtr &b : m_bookmarks)
780   {
781     if (b->url() == url)
782     {
783       bookmark = b;
784       break;
785     }
786     else
787     {
788       continue;
789     }
790   }
791 
792   return bookmark;
793 }
794 
795 
slotItemClicked(QTreeWidgetItem * item,int)796 void Smb4KBookmarkEditor::slotItemClicked(QTreeWidgetItem *item, int /*col*/)
797 {
798   //
799   // Get the widgets
800   //
801   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
802   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
803   QWidget *editorWidgets = findChild<QWidget *>("EditorWidgets");
804   KLineEdit *labelEdit = findChild<KLineEdit *>("LabelEdit");
805   KLineEdit *ipEdit = findChild<KLineEdit *>("IpEdit");
806   KLineEdit *loginEdit = findChild<KLineEdit *>("LoginEdit");
807   KLineEdit *workgroupEdit = findChild<KLineEdit *>("WorkgroupEdit");
808 
809   //
810   // Process the item
811   //
812   if (item)
813   {
814     if (treeWidget->indexOfTopLevelItem(item) != -1)
815     {
816       // This is a top-level item, i.e. it is either a bookmark without
817       // group or a group entry.
818       // Bookmarks have an URL stored, group folders not.
819       if (!item->data(0, QTreeWidgetItem::UserType).toUrl().isEmpty())
820       {
821         BookmarkPtr bookmark = findBookmark(item->data(0, QTreeWidgetItem::UserType).toUrl());
822 
823         if (bookmark)
824         {
825           labelEdit->setText(bookmark->label());
826           loginEdit->setText(bookmark->login());
827           ipEdit->setText(bookmark->hostIpAddress());
828           workgroupEdit->setText(bookmark->workgroupName());
829           categoryCombo->setCurrentItem(bookmark->categoryName());
830           editorWidgets->setEnabled(true);
831         }
832         else
833         {
834           labelEdit->clear();
835           loginEdit->clear();
836           ipEdit->clear();
837           workgroupEdit->clear();
838           categoryCombo->clearEditText();
839           editorWidgets->setEnabled(false);
840         }
841       }
842       else
843       {
844         labelEdit->clear();
845         loginEdit->clear();
846         ipEdit->clear();
847         workgroupEdit->clear();
848         categoryCombo->clearEditText();
849         editorWidgets->setEnabled(false);
850       }
851     }
852     else
853     {
854       // This can only be a bookmark.
855       BookmarkPtr bookmark = findBookmark(item->data(0, QTreeWidgetItem::UserType).toUrl());
856 
857       if (bookmark)
858       {
859         labelEdit->setText(bookmark->label());
860         loginEdit->setText(bookmark->login());
861         ipEdit->setText(bookmark->hostIpAddress());
862         workgroupEdit->setText(bookmark->workgroupName());
863         categoryCombo->setCurrentItem(bookmark->categoryName());
864         editorWidgets->setEnabled(true);
865       }
866       else
867       {
868         labelEdit->clear();
869         loginEdit->clear();
870         ipEdit->clear();
871         workgroupEdit->clear();
872         categoryCombo->clearEditText();
873         editorWidgets->setEnabled(false);
874       }
875     }
876   }
877   else
878   {
879     labelEdit->clear();
880     loginEdit->clear();
881     ipEdit->clear();
882     workgroupEdit->clear();
883     categoryCombo->clearEditText();
884     editorWidgets->setEnabled(false);
885   }
886 }
887 
888 
slotContextMenuRequested(const QPoint & pos)889 void Smb4KBookmarkEditor::slotContextMenuRequested(const QPoint &pos)
890 {
891   //
892   // Get the widgets
893   //
894   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
895   QAction *deleteAction = findChild<QAction *>("DeleteAction");
896   KActionMenu *actionMenu = findChild<KActionMenu *>("ActionMenu");
897 
898   //
899   // Open the context menu
900   //
901   QTreeWidgetItem *item = treeWidget->itemAt(pos);
902   deleteAction->setEnabled((item));
903   actionMenu->menu()->popup(treeWidget->viewport()->mapToGlobal(pos));
904 }
905 
906 
slotLabelEdited()907 void Smb4KBookmarkEditor::slotLabelEdited()
908 {
909   //
910   // Get the widgets
911   //
912   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
913   KLineEdit *labelEdit = findChild<KLineEdit *>("LabelEdit");
914 
915   //
916   // Find the bookmark
917   //
918   QUrl url = treeWidget->currentItem()->data(0, QTreeWidgetItem::UserType).toUrl();
919 
920   BookmarkPtr bookmark = findBookmark(url);
921 
922   //
923   // Set the label
924   //
925   if (bookmark)
926   {
927     bookmark->setLabel(labelEdit->userText());
928   }
929 
930   //
931   // Add the label to the completion object
932   //
933   KCompletion *completion = labelEdit->completionObject();
934 
935   if (!labelEdit->userText().isEmpty())
936   {
937     completion->addItem(labelEdit->userText());
938   }
939 }
940 
941 
slotLoginEdited()942 void Smb4KBookmarkEditor::slotLoginEdited()
943 {
944   //
945   // Get the widgets
946   //
947   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
948   KLineEdit *loginEdit = findChild<KLineEdit *>("LoginEdit");
949 
950   //
951   // Find the bookmark
952   //
953   QUrl url = treeWidget->currentItem()->data(0, QTreeWidgetItem::UserType).toUrl();
954 
955   BookmarkPtr bookmark = findBookmark(url);
956 
957   //
958   // Set the login
959   //
960   if (bookmark)
961   {
962     bookmark->setLogin(loginEdit->userText());
963   }
964 
965   //
966   // Add the login to the completion object
967   //
968   KCompletion *completion = loginEdit->completionObject();
969 
970   if (!loginEdit->userText().isEmpty())
971   {
972     completion->addItem(loginEdit->userText());
973   }
974 }
975 
976 
slotIpEdited()977 void Smb4KBookmarkEditor::slotIpEdited()
978 {
979   //
980   // Get the widgets
981   //
982   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
983   KLineEdit *ipEdit = findChild<KLineEdit *>("IpEdit");
984 
985   //
986   // Find the bookmark
987   //
988   QUrl url = treeWidget->currentItem()->data(0, QTreeWidgetItem::UserType).toUrl();
989 
990   BookmarkPtr bookmark = findBookmark(url);
991 
992   //
993   // Set the IP address
994   //
995   if (bookmark)
996   {
997     bookmark->setHostIpAddress(ipEdit->userText());
998   }
999 
1000   //
1001   // Add the IP address to the completion object
1002   //
1003   KCompletion *completion = ipEdit->completionObject();
1004 
1005   if (!ipEdit->userText().isEmpty())
1006   {
1007     completion->addItem(ipEdit->userText());
1008   }
1009 }
1010 
1011 
slotWorkgroupNameEdited()1012 void Smb4KBookmarkEditor::slotWorkgroupNameEdited()
1013 {
1014   //
1015   // Get the widgets
1016   //
1017   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
1018   KLineEdit *workgroupEdit = findChild<KLineEdit *>("WorkgroupEdit");
1019 
1020   //
1021   // Find the bookmark
1022   //
1023   QUrl url = treeWidget->currentItem()->data(0, QTreeWidgetItem::UserType).toUrl();
1024 
1025   BookmarkPtr bookmark = findBookmark(url);
1026 
1027   //
1028   // Set the workgroup name
1029   //
1030   if (bookmark)
1031   {
1032     bookmark->setWorkgroupName(workgroupEdit->userText());
1033   }
1034 
1035   //
1036   // Add the workgroup name to the completion object
1037   //
1038   KCompletion *completion = workgroupEdit->completionObject();
1039 
1040   if (!workgroupEdit->userText().isEmpty())
1041   {
1042     completion->addItem(workgroupEdit->userText());
1043   }
1044 }
1045 
1046 
slotCategoryEdited()1047 void Smb4KBookmarkEditor::slotCategoryEdited()
1048 {
1049   //
1050   // Get the widgets
1051   //
1052   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
1053   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
1054 
1055   //
1056   // Get the URL of the current item
1057   //
1058   QUrl url = treeWidget->currentItem()->data(0, QTreeWidgetItem::UserType).toUrl();
1059 
1060   //
1061   // Return here, if the current item is a group
1062   //
1063   if (url.isEmpty())
1064   {
1065     return;
1066   }
1067 
1068   //
1069   // Find the bookmark
1070   //
1071   BookmarkPtr bookmark = findBookmark(url);
1072 
1073   //
1074   // Set the category
1075   //
1076   if (bookmark)
1077   {
1078     bookmark->setCategoryName(categoryCombo->currentText());
1079   }
1080 
1081   //
1082   // Reload the bookmarks (The current item is cleared by this!)
1083   //
1084   loadBookmarks();
1085 
1086   //
1087   // Reset the current item
1088   //
1089   QTreeWidgetItemIterator it(treeWidget);
1090 
1091   while (*it)
1092   {
1093     if ((*it)->data(0, QTreeWidgetItem::UserType).toUrl() == url)
1094     {
1095       treeWidget->setCurrentItem(*it);
1096       slotItemClicked(*it, 0);
1097       break;
1098     }
1099 
1100     ++it;
1101   }
1102 
1103   //
1104   // Add the category to the completion object
1105   //
1106   KCompletion *completion = categoryCombo->completionObject();
1107 
1108   if (!categoryCombo->currentText().isEmpty())
1109   {
1110     completion->addItem(categoryCombo->currentText());
1111   }
1112 }
1113 
1114 
slotAddCategoryTriggered(bool)1115 void Smb4KBookmarkEditor::slotAddCategoryTriggered(bool /*checked*/)
1116 {
1117   //
1118   // Get the widgets
1119   //
1120   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
1121   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
1122 
1123   //
1124   // Process the category
1125   //
1126   bool ok = false;
1127 
1128   QString categoryName = QInputDialog::getText(this, i18n("Add Category"), i18n("Category name:"), QLineEdit::Normal, QString(), &ok);
1129 
1130   if (ok && !categoryName.isEmpty() && treeWidget->findItems(categoryName, Qt::MatchFixedString|Qt::MatchCaseSensitive, 0).isEmpty())
1131   {
1132     // Create a new category item and add it to the widget
1133     QTreeWidgetItem *categoryItem = new QTreeWidgetItem(QTreeWidgetItem::UserType);
1134     categoryItem->setIcon(0, KDE::icon("folder-bookmark"));
1135     categoryItem->setText(0, categoryName);
1136     categoryItem->setText((treeWidget->columnCount() - 1), QString("00_%1").arg(categoryName));
1137     categoryItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsDropEnabled) ;
1138     treeWidget->addTopLevelItem(categoryItem);
1139     treeWidget->sortItems((treeWidget->columnCount() - 1), Qt::AscendingOrder);
1140 
1141     // Add the group to the combo box
1142     categoryCombo->addItem(categoryName);
1143     categoryCombo->completionObject()->addItem(categoryName);
1144   }
1145 }
1146 
1147 
slotDeleteTriggered(bool)1148 void Smb4KBookmarkEditor::slotDeleteTriggered(bool /*checked*/)
1149 {
1150   //
1151   // Get the widget
1152   //
1153   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
1154 
1155   //
1156   // Remove the bookmarks from the view and the internal list
1157   //
1158   QList<QTreeWidgetItem *> selected = treeWidget->selectedItems();
1159 
1160   while (!selected.isEmpty())
1161   {
1162     QTreeWidgetItem *item = selected.takeFirst();
1163     QUrl url = item->data(0, QTreeWidgetItem::UserType).toUrl();
1164 
1165     QMutableListIterator<BookmarkPtr> it(m_bookmarks);
1166 
1167     while (it.hasNext())
1168     {
1169       BookmarkPtr bookmark = it.next();
1170 
1171       if (bookmark->url() == url)
1172       {
1173         it.remove();
1174         break;
1175       }
1176     }
1177 
1178     delete item;
1179   }
1180 }
1181 
1182 
slotClearTriggered(bool)1183 void Smb4KBookmarkEditor::slotClearTriggered(bool /*checked*/)
1184 {
1185   //
1186   // Get the widget
1187   //
1188   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
1189 
1190   //
1191   // Clear the widget and the lists
1192   //
1193   treeWidget->clear();
1194   m_bookmarks.clear();
1195   m_categories.clear();
1196 }
1197 
1198 
slotDialogAccepted()1199 void Smb4KBookmarkEditor::slotDialogAccepted()
1200 {
1201   //
1202   // Get the widgets
1203   //
1204   KComboBox *categoryCombo = findChild<KComboBox *>("CategoryCombo");
1205   KLineEdit *labelEdit = findChild<KLineEdit *>("LabelEdit");
1206   KLineEdit *ipEdit = findChild<KLineEdit *>("IpEdit");
1207   KLineEdit *loginEdit = findChild<KLineEdit *>("LoginEdit");
1208   KLineEdit *workgroupEdit = findChild<KLineEdit *>("WorkgroupEdit");
1209 
1210   //
1211   // Write the dialog properties to the config file
1212   //
1213   KConfigGroup group(Smb4KSettings::self()->config(), "BookmarkEditor");
1214   KWindowConfig::saveWindowSize(windowHandle(), group);
1215   group.writeEntry("LabelCompletion", labelEdit->completionObject()->items());
1216   group.writeEntry("LoginCompletion", loginEdit->completionObject()->items());
1217   group.writeEntry("IPCompletion", ipEdit->completionObject()->items());
1218   group.writeEntry("CategoryCompletion", categoryCombo->completionObject()->items());
1219   group.writeEntry("WorkgroupCompletion", workgroupEdit->completionObject()->items());
1220 
1221   //
1222   // Accept the dialog
1223   //
1224   accept();
1225 }
1226 
1227 
slotDialogRejected()1228 void Smb4KBookmarkEditor::slotDialogRejected()
1229 {
1230   //
1231   // Reject the dialog
1232   //
1233   reject();
1234 }
1235 
1236 
1237 
slotIconSizeChanged(int group)1238 void Smb4KBookmarkEditor::slotIconSizeChanged(int group)
1239 {
1240   //
1241   // Get the widget
1242   //
1243   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
1244 
1245   //
1246   // Change the icon size
1247   //
1248   switch (group)
1249   {
1250     case KIconLoader::Small:
1251     {
1252       int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
1253       treeWidget->setIconSize(QSize(iconSize, iconSize));
1254       break;
1255     }
1256     default:
1257     {
1258       break;
1259     }
1260   }
1261 }
1262 
1263 
slotAdjust()1264 void Smb4KBookmarkEditor::slotAdjust()
1265 {
1266   //
1267   // Get the widget
1268   //
1269   QTreeWidget *treeWidget = findChild<QTreeWidget *>("BookmarksTreeWidget");
1270 
1271   //
1272   // Do the necessary adjustments
1273   //
1274   QTreeWidgetItemIterator it(treeWidget);
1275 
1276   while (*it)
1277   {
1278     if (!(*it)->parent())
1279     {
1280       if ((*it)->data(0, QTreeWidgetItem::UserType).toUrl().isEmpty())
1281       {
1282         if ((*it)->childCount() == 0)
1283         {
1284           delete *it;
1285         }
1286       }
1287       else
1288       {
1289         BookmarkPtr bookmark = findBookmark((*it)->data(0, QTreeWidgetItem::UserType).toUrl());
1290 
1291         if (bookmark)
1292         {
1293           bookmark->setCategoryName("");
1294         }
1295       }
1296     }
1297     else
1298     {
1299       BookmarkPtr bookmark = findBookmark((*it)->data(0, QTreeWidgetItem::UserType).toUrl());
1300 
1301       if (bookmark)
1302       {
1303         bookmark->setCategoryName((*it)->parent()->text(0));
1304       }
1305     }
1306     ++it;
1307   }
1308 }
1309 
1310 
1311