File indexing completed on 2024-04-21 04:58:16
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2009 Pino Toscano <pino@kde.org> 0003 SPDX-FileCopyrightText: 2009 Daivd Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "konqhistoryview.h" 0009 #include "konqhistory.h" 0010 #include "konq_historyprovider.h" 0011 #include "konqhistorymodel.h" 0012 #include "konqhistoryproxymodel.h" 0013 #include "konqhistorysettings.h" 0014 0015 #include <KDialogJobUiDelegate> 0016 #include <QAction> 0017 #include <QApplication> 0018 #include <QClipboard> 0019 #include <QIcon> 0020 #include <QLineEdit> 0021 #include <QMenu> 0022 #include <QMimeData> 0023 #include <QTimer> 0024 #include <QTreeView> 0025 #include <QVBoxLayout> 0026 #include <QActionGroup> 0027 0028 #include <kactioncollection.h> 0029 #include "konqdebug.h" 0030 #include <KLocalizedString> 0031 #include <kmessagebox.h> 0032 0033 #include <KIO/CommandLauncherJob> 0034 0035 KonqHistoryView::KonqHistoryView(QWidget *parent) 0036 : QWidget(parent) 0037 , m_searchTimer(nullptr) 0038 { 0039 m_treeView = new QTreeView(this); 0040 m_treeView->setContextMenuPolicy(Qt::CustomContextMenu); 0041 m_treeView->setHeaderHidden(true); 0042 0043 m_historyProxyModel = new KonqHistoryProxyModel(KonqHistorySettings::self(), m_treeView); 0044 connect(m_treeView, &QTreeView::customContextMenuRequested, this, &KonqHistoryView::slotContextMenu); 0045 m_historyModel = new KonqHistoryModel(m_historyProxyModel); 0046 m_treeView->setModel(m_historyProxyModel); 0047 m_historyProxyModel->setSourceModel(m_historyModel); 0048 m_historyProxyModel->sort(0); 0049 0050 m_collection = new KActionCollection(this); 0051 m_collection->addAssociatedWidget(m_treeView); // make shortcuts work 0052 QAction *action = m_collection->addAction(QStringLiteral("open_new")); 0053 action->setIcon(QIcon::fromTheme(QStringLiteral("window-new"))); 0054 action->setText(i18n("Open in New &Window")); 0055 connect(action, &QAction::triggered, this, &KonqHistoryView::slotNewWindow); 0056 0057 action = m_collection->addAction(QStringLiteral("open_tab")); 0058 action->setIcon(QIcon::fromTheme(QStringLiteral("tab-new"))); 0059 action->setText(i18n("Open in New Tab")); 0060 connect(action, &QAction::triggered, this, &KonqHistoryView::slotNewTab); 0061 0062 action = m_collection->addAction(QStringLiteral("open_current_tab")); 0063 action->setIcon(QIcon::fromTheme(QStringLiteral("window"))); 0064 action->setText(i18n("Open in Current Tab")); 0065 connect(action, &QAction::triggered, this, &KonqHistoryView::slotCurrentTab); 0066 0067 action = m_collection->addAction(QStringLiteral("copylinklocation")); 0068 action->setText(i18n("&Copy Link Address")); 0069 connect(action, &QAction::triggered, this, &KonqHistoryView::slotCopyLinkLocation); 0070 0071 action = m_collection->addAction(QStringLiteral("remove")); 0072 action->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); 0073 action->setText(i18n("&Remove Entry")); 0074 m_collection->setDefaultShortcut(action, QKeySequence(Qt::Key_Delete)); // #135966 0075 action->setShortcutContext(Qt::WidgetWithChildrenShortcut); 0076 connect(action, &QAction::triggered, this, &KonqHistoryView::slotRemoveEntry); 0077 0078 action = m_collection->addAction(QStringLiteral("clear")); 0079 action->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear-history"))); 0080 action->setText(i18n("C&lear History")); 0081 connect(action, &QAction::triggered, this, &KonqHistoryView::slotClearHistory); 0082 0083 action = m_collection->addAction(QStringLiteral("preferences")); 0084 action->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); 0085 action->setText(i18n("&Preferences...")); 0086 connect(action, &QAction::triggered, this, &KonqHistoryView::slotPreferences); 0087 0088 QActionGroup *sortGroup = new QActionGroup(this); 0089 sortGroup->setExclusive(true); 0090 0091 action = m_collection->addAction(QStringLiteral("byName")); 0092 action->setText(i18n("By &Name")); 0093 action->setCheckable(true); 0094 action->setData(QVariant::fromValue(0)); 0095 sortGroup->addAction(action); 0096 0097 action = m_collection->addAction(QStringLiteral("byDate")); 0098 action->setText(i18n("By &Date")); 0099 action->setCheckable(true); 0100 action->setData(QVariant::fromValue(1)); 0101 sortGroup->addAction(action); 0102 0103 KonqHistorySettings *settings = KonqHistorySettings::self(); 0104 sortGroup->actions().at(settings->m_sortsByName ? 0 : 1)->setChecked(true); 0105 connect(sortGroup, &QActionGroup::triggered, this, &KonqHistoryView::slotSortChange); 0106 0107 m_searchLineEdit = new QLineEdit(this); 0108 m_searchLineEdit->setPlaceholderText(i18n("Search in history")); 0109 m_searchLineEdit->setClearButtonEnabled(true); 0110 0111 connect(m_searchLineEdit, &QLineEdit::textChanged, this, &KonqHistoryView::slotFilterTextChanged); 0112 0113 QVBoxLayout *mainLayout = new QVBoxLayout(this); 0114 mainLayout->setContentsMargins(0, 0, 0, 0); 0115 mainLayout->addWidget(m_searchLineEdit); 0116 mainLayout->addWidget(m_treeView); 0117 } 0118 0119 void KonqHistoryView::slotContextMenu(const QPoint &pos) 0120 { 0121 const QModelIndex index = m_treeView->indexAt(pos); 0122 if (!index.isValid()) { 0123 return; 0124 } 0125 0126 const int nodeType = index.data(KonqHistory::TypeRole).toInt(); 0127 0128 QMenu *menu = new QMenu(this); 0129 0130 if (nodeType == KonqHistory::HistoryType) { 0131 menu->addAction(m_collection->action(QStringLiteral("open_new"))); 0132 menu->addAction(m_collection->action(QStringLiteral("open_tab"))); 0133 menu->addAction(m_collection->action(QStringLiteral("open_current_tab"))); 0134 menu->addAction(m_collection->action(QStringLiteral("copylinklocation"))); 0135 menu->addSeparator(); 0136 } 0137 0138 menu->addAction(m_collection->action(QStringLiteral("remove"))); 0139 menu->addAction(m_collection->action(QStringLiteral("clear"))); 0140 menu->addSeparator(); 0141 QMenu *sortMenu = menu->addMenu(i18nc("@action:inmenu Parent of 'By Name' and 'By Date'", "Sort")); 0142 sortMenu->addAction(m_collection->action(QStringLiteral("byName"))); 0143 sortMenu->addAction(m_collection->action(QStringLiteral("byDate"))); 0144 menu->addSeparator(); 0145 menu->addAction(m_collection->action(QStringLiteral("preferences"))); 0146 0147 menu->exec(m_treeView->viewport()->mapToGlobal(pos)); 0148 0149 delete menu; 0150 } 0151 0152 void KonqHistoryView::slotRemoveEntry() 0153 { 0154 const QModelIndex index = m_treeView->currentIndex(); 0155 if (!index.isValid()) { 0156 return; 0157 } 0158 0159 // TODO undo/redo support 0160 m_historyModel->deleteItem(m_historyProxyModel->mapToSource(index)); 0161 } 0162 0163 void KonqHistoryView::slotClearHistory() 0164 { 0165 KGuiItem guiitem = KStandardGuiItem::clear(); 0166 guiitem.setIcon(QIcon::fromTheme(QStringLiteral("edit-clear-history"))); 0167 0168 if (KMessageBox::warningContinueCancel(this, 0169 i18n("Do you really want to clear the entire history?"), 0170 i18nc("@title:window", "Clear History?"), guiitem) 0171 == KMessageBox::Continue) { 0172 KonqHistoryProvider::self()->emitClear(); 0173 } 0174 } 0175 0176 void KonqHistoryView::slotPreferences() 0177 { 0178 // Run the history sidebar settings. 0179 KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob(QStringLiteral("kcmshell5 kcmhistory")); 0180 job->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this)); 0181 job->start(); 0182 } 0183 0184 void KonqHistoryView::slotSortChange(QAction *action) 0185 { 0186 if (!action) { 0187 return; 0188 } 0189 0190 const int which = action->data().toInt(); 0191 KonqHistorySettings *settings = KonqHistorySettings::self(); 0192 settings->m_sortsByName = (which == 0); 0193 settings->applySettings(); 0194 } 0195 0196 void KonqHistoryView::slotFilterTextChanged(const QString &text) 0197 { 0198 Q_UNUSED(text); 0199 if (!m_searchTimer) { 0200 m_searchTimer = new QTimer(this); 0201 m_searchTimer->setSingleShot(true); 0202 connect(m_searchTimer, &QTimer::timeout, this, &KonqHistoryView::slotTimerTimeout); 0203 } 0204 m_searchTimer->start(600); 0205 } 0206 0207 void KonqHistoryView::slotTimerTimeout() 0208 { 0209 m_historyProxyModel->setFilterFixedString(m_searchLineEdit->text()); 0210 } 0211 0212 QTreeView *KonqHistoryView::treeView() const 0213 { 0214 return m_treeView; 0215 } 0216 0217 QLineEdit *KonqHistoryView::lineEdit() const 0218 { 0219 return m_searchLineEdit; 0220 } 0221 0222 void KonqHistoryView::slotNewWindow() 0223 { 0224 const QUrl url = urlForIndex(m_treeView->currentIndex()); 0225 if (url.isValid()) { 0226 emit openUrlInNewWindow(url); 0227 } 0228 } 0229 0230 void KonqHistoryView::slotNewTab() 0231 { 0232 const QUrl url = urlForIndex(m_treeView->currentIndex()); 0233 if (url.isValid()) { 0234 emit openUrlInNewTab(url); 0235 } 0236 } 0237 0238 void KonqHistoryView::slotCurrentTab() 0239 { 0240 const QUrl url = urlForIndex(m_treeView->currentIndex()); 0241 if (url.isValid()) { 0242 emit openUrlInCurrentTab(url); 0243 } 0244 } 0245 0246 QUrl KonqHistoryView::urlForIndex(const QModelIndex &index) const 0247 { 0248 if (!index.isValid() || (index.data(KonqHistory::TypeRole).toInt() != KonqHistory::HistoryType)) { 0249 return QUrl(); 0250 } 0251 0252 return index.data(KonqHistory::UrlRole).toUrl(); 0253 } 0254 0255 // Code taken from KHTMLPopupGUIClient::slotCopyLinkLocation 0256 void KonqHistoryView::slotCopyLinkLocation() 0257 { 0258 QUrl safeURL = urlForIndex(m_treeView->currentIndex()).adjusted(QUrl::RemovePassword); 0259 0260 // Set it in both the mouse selection and in the clipboard 0261 QMimeData *mimeData = new QMimeData; 0262 mimeData->setUrls(QList<QUrl>() << safeURL); 0263 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); 0264 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); 0265 }