1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Assistant of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 #include "bookmarkdialog.h"
29 #include "bookmarkfiltermodel.h"
30 #include "bookmarkitem.h"
31 #include "bookmarkmodel.h"
32 #include "helpenginewrapper.h"
33 #include "tracer.h"
34 
35 #include <QtGui/QKeyEvent>
36 #include <QtWidgets/QMenu>
37 
38 QT_BEGIN_NAMESPACE
39 
BookmarkDialog(BookmarkModel * sourceModel,const QString & title,const QString & url,QWidget * parent)40 BookmarkDialog::BookmarkDialog(BookmarkModel *sourceModel, const QString &title,
41         const QString &url, QWidget *parent)
42     : QDialog(parent)
43     , m_url(url)
44     , m_title(title)
45     , bookmarkModel(sourceModel)
46 {
47     TRACE_OBJ
48     ui.setupUi(this);
49 
50     ui.bookmarkEdit->setText(m_title);
51     ui.newFolderButton->setVisible(false);
52     ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
53 
54     connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &BookmarkDialog::accepted);
55     connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &BookmarkDialog::rejected);
56     connect(ui.newFolderButton, &QAbstractButton::clicked, this, &BookmarkDialog::addFolder);
57     connect(ui.toolButton, &QAbstractButton::clicked, this, &BookmarkDialog::toolButtonClicked);
58     connect(ui.bookmarkEdit, &QLineEdit::textChanged, this, &BookmarkDialog::textChanged);
59 
60     bookmarkProxyModel = new BookmarkFilterModel(this);
61     bookmarkProxyModel->setSourceModel(bookmarkModel);
62     ui.bookmarkFolders->setModel(bookmarkProxyModel);
63     connect(ui.bookmarkFolders, QOverload<int>::of(&QComboBox::currentIndexChanged),
64             this, QOverload<int>::of(&BookmarkDialog::currentIndexChanged));
65 
66     bookmarkTreeModel = new BookmarkTreeModel(this);
67     bookmarkTreeModel->setSourceModel(bookmarkModel);
68     ui.treeView->setModel(bookmarkTreeModel);
69 
70     ui.treeView->expandAll();
71     ui.treeView->setVisible(false);
72     ui.treeView->installEventFilter(this);
73     ui.treeView->viewport()->installEventFilter(this);
74     ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
75 
76     connect(ui.treeView, &QWidget::customContextMenuRequested,
77             this, &BookmarkDialog::customContextMenuRequested);
78     connect(ui.treeView->selectionModel(), &QItemSelectionModel::currentChanged,
79             this, QOverload<const QModelIndex &>::of(&BookmarkDialog::currentIndexChanged));
80 
81     ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->count() > 1 ? 1 : 0);
82 
83     const HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance();
84     if (helpEngine.usesAppFont())
85         setFont(helpEngine.appFont());
86 }
87 
~BookmarkDialog()88 BookmarkDialog::~BookmarkDialog()
89 {
90     TRACE_OBJ
91 }
92 
isRootItem(const QModelIndex & index) const93 bool BookmarkDialog::isRootItem(const QModelIndex &index) const
94 {
95     return !bookmarkTreeModel->parent(index).isValid();
96 }
97 
eventFilter(QObject * object,QEvent * event)98 bool BookmarkDialog::eventFilter(QObject *object, QEvent *event)
99 {
100     TRACE_OBJ
101     if (object != ui.treeView && object != ui.treeView->viewport())
102         return QWidget::eventFilter(object, event);
103 
104     if (event->type() == QEvent::KeyPress) {
105         QKeyEvent *ke = static_cast<QKeyEvent*>(event);
106         switch (ke->key()) {
107             case Qt::Key_F2: {
108                 const QModelIndex &index = ui.treeView->currentIndex();
109                 if (!isRootItem(index)) {
110                     bookmarkModel->setItemsEditable(true);
111                     ui.treeView->edit(index);
112                     bookmarkModel->setItemsEditable(false);
113                 }
114             }   break;
115             default: break;
116         }
117     }
118 
119     return QObject::eventFilter(object, event);
120 }
121 
currentIndexChanged(int row)122 void BookmarkDialog::currentIndexChanged(int row)
123 {
124     TRACE_OBJ
125     QModelIndex next = bookmarkProxyModel->index(row, 0, QModelIndex());
126     if (next.isValid()) {
127         next = bookmarkProxyModel->mapToSource(next);
128         ui.treeView->setCurrentIndex(bookmarkTreeModel->mapFromSource(next));
129     }
130 }
131 
currentIndexChanged(const QModelIndex & index)132 void BookmarkDialog::currentIndexChanged(const QModelIndex &index)
133 {
134     TRACE_OBJ
135     const QModelIndex current = bookmarkTreeModel->mapToSource(index);
136     if (current.isValid()) {
137         const int row = bookmarkProxyModel->mapFromSource(current).row();
138         ui.bookmarkFolders->setCurrentIndex(row);
139     }
140 }
141 
accepted()142 void BookmarkDialog::accepted()
143 {
144     TRACE_OBJ
145     QModelIndex index = ui.treeView->currentIndex();
146     if (index.isValid()) {
147         index = bookmarkModel->addItem(bookmarkTreeModel->mapToSource(index));
148         bookmarkModel->setData(index, DataVector() << m_title << m_url << false);
149     } else
150         rejected();
151 
152     accept();
153 }
154 
rejected()155 void BookmarkDialog::rejected()
156 {
157     TRACE_OBJ
158     for (const QPersistentModelIndex &index : qAsConst(cache))
159         bookmarkModel->removeItem(index);
160     reject();
161 }
162 
addFolder()163 void BookmarkDialog::addFolder()
164 {
165     TRACE_OBJ
166     QModelIndex index = ui.treeView->currentIndex();
167     if (index.isValid()) {
168         index = bookmarkModel->addItem(bookmarkTreeModel->mapToSource(index),
169             true);
170         cache.append(index);
171 
172         index = bookmarkTreeModel->mapFromSource(index);
173         if (index.isValid()) {
174             bookmarkModel->setItemsEditable(true);
175             ui.treeView->edit(index);
176             ui.treeView->expand(index);
177             ui.treeView->setCurrentIndex(index);
178             bookmarkModel->setItemsEditable(false);
179         }
180     }
181 }
182 
toolButtonClicked()183 void BookmarkDialog::toolButtonClicked()
184 {
185     TRACE_OBJ
186     const bool visible = !ui.treeView->isVisible();
187     ui.treeView->setVisible(visible);
188     ui.newFolderButton->setVisible(visible);
189 
190     if (visible) {
191         resize(QSize(width(), 400));
192         ui.toolButton->setText(QLatin1String("-"));
193     } else {
194         resize(width(), minimumHeight());
195         ui.toolButton->setText(QLatin1String("+"));
196     }
197 }
198 
textChanged(const QString & text)199 void BookmarkDialog::textChanged(const QString& text)
200 {
201     m_title = text;
202 }
203 
customContextMenuRequested(const QPoint & point)204 void BookmarkDialog::customContextMenuRequested(const QPoint &point)
205 {
206     TRACE_OBJ
207     const QModelIndex &index = ui.treeView->currentIndex();
208     if (isRootItem(index))
209         return; // check if we go to rename the "Bookmarks Menu", bail
210 
211     QMenu menu(QString(), this);
212     QAction *renameItem = menu.addAction(tr("Rename Folder"));
213 
214     QAction *picked = menu.exec(ui.treeView->mapToGlobal(point));
215     if (picked == renameItem) {
216         bookmarkModel->setItemsEditable(true);
217         ui.treeView->edit(index);
218         bookmarkModel->setItemsEditable(false);
219     }
220 }
221 
222 QT_END_NAMESPACE
223