File indexing completed on 2024-04-14 04:53:05

0001 /* This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2000 Simon Hausmann <hausmann@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "konqactions.h"
0008 
0009 #include "konqview.h"
0010 #include "konqsettingsxt.h"
0011 #include "konqpixmapprovider.h"
0012 
0013 #include "konqdebug.h"
0014 
0015 #include <kwidgetsaddons_version.h>
0016 
0017 #include <QIcon>
0018 #include <QMenu>
0019 #include <QAction>
0020 
0021 #include <algorithm>
0022 
0023 template class QList<KonqHistoryEntry *>;
0024 
0025 /////////////////
0026 
0027 //static - used by back/forward popups in KonqMainWindow
0028 void KonqActions::fillHistoryPopup(const QList<HistoryEntry *> &history, int historyIndex,
0029                                    QMenu *popup,
0030                                    bool onlyBack,
0031                                    bool onlyForward)
0032 {
0033     Q_ASSERT(popup);   // kill me if this 0... :/
0034 
0035     //qCDebug(KONQUEROR_LOG) << "fillHistoryPopup position: " << history.at();
0036     int index = 0;
0037     if (onlyBack || onlyForward) { // this if() is always true nowadays.
0038         index += historyIndex; // Jump to current item
0039         if (!onlyForward) {
0040             --index;
0041         } else {
0042             ++index;    // And move off it
0043         }
0044     }
0045 
0046     QFontMetrics fm = popup->fontMetrics();
0047     int i = 0;
0048     while (index < history.count() && index >= 0) {
0049         QString text = history[ index ]->title;
0050         text = fm.elidedText(text, Qt::ElideMiddle, fm.maxWidth() * 30);
0051         text.replace('&', QLatin1String("&&"));
0052         const QString iconName = KonqPixmapProvider::self()->iconNameFor(history[index]->url);
0053         QAction *action = new QAction(QIcon::fromTheme(iconName), text, popup);
0054         action->setData(index - historyIndex);
0055         //qCDebug(KONQUEROR_LOG) << text << index - historyIndex;
0056         popup->addAction(action);
0057         if (++i > 10) {
0058             break;
0059         }
0060         if (!onlyForward) {
0061             --index;
0062         } else {
0063             ++index;
0064         }
0065     }
0066     //qCDebug(KONQUEROR_LOG) << "After fillHistoryPopup position: " << history.at();
0067 }
0068 
0069 ///////////////////////////////
0070 
0071 static int s_maxEntries = 0;
0072 
0073 KonqMostOftenURLSAction::KonqMostOftenURLSAction(const QString &text,
0074         QObject *parent)
0075     : KActionMenu(QIcon::fromTheme(QStringLiteral("go-jump")), text, parent),
0076       m_parsingDone(false)
0077 {
0078     setPopupMode(QToolButton::InstantPopup);
0079     connect(menu(), SIGNAL(aboutToShow()), SLOT(slotFillMenu()));
0080     connect(menu(), SIGNAL(triggered(QAction*)), SLOT(slotActivated(QAction*)));
0081     // Need to do all this upfront for a correct initial state
0082     init();
0083 }
0084 
0085 KonqMostOftenURLSAction::~KonqMostOftenURLSAction()
0086 {
0087 }
0088 
0089 void KonqMostOftenURLSAction::init()
0090 {
0091     s_maxEntries = KonqSettings::numberofmostvisitedURLs();
0092 
0093     KonqHistoryManager *mgr = KonqHistoryManager::kself();
0094     setEnabled(!mgr->entries().isEmpty() && s_maxEntries > 0);
0095 }
0096 
0097 Q_GLOBAL_STATIC(KonqHistoryList, s_mostEntries)
0098 
0099 void KonqMostOftenURLSAction::inSort(const KonqHistoryEntry &entry)
0100 {
0101     KonqHistoryList::iterator it = std::lower_bound(s_mostEntries->begin(),
0102                                    s_mostEntries->end(),
0103                                    entry,
0104                                    numberOfVisitOrder);
0105     s_mostEntries->insert(it, entry);
0106 }
0107 
0108 void KonqMostOftenURLSAction::parseHistory() // only ever called once
0109 {
0110     KonqHistoryManager *mgr = KonqHistoryManager::kself();
0111 
0112     connect(mgr, SIGNAL(entryAdded(KonqHistoryEntry)),
0113             SLOT(slotEntryAdded(KonqHistoryEntry)));
0114     connect(mgr, SIGNAL(entryRemoved(KonqHistoryEntry)),
0115             SLOT(slotEntryRemoved(KonqHistoryEntry)));
0116     connect(mgr, SIGNAL(cleared()), SLOT(slotHistoryCleared()));
0117 
0118     const KonqHistoryList mgrEntries = mgr->entries();
0119     KonqHistoryList::const_iterator it = mgrEntries.begin();
0120     const KonqHistoryList::const_iterator end = mgrEntries.end();
0121     for (int i = 0; it != end && i < s_maxEntries; ++i, ++it) {
0122         s_mostEntries->append(*it);
0123     }
0124     std::sort(s_mostEntries->begin(), s_mostEntries->end(), numberOfVisitOrder);
0125 
0126     while (it != end) {
0127         const KonqHistoryEntry &leastOften = s_mostEntries->first();
0128         const KonqHistoryEntry &entry = *it;
0129         if (leastOften.numberOfTimesVisited < entry.numberOfTimesVisited) {
0130             s_mostEntries->removeFirst();
0131             inSort(entry);
0132         }
0133 
0134         ++it;
0135     }
0136 }
0137 
0138 void KonqMostOftenURLSAction::slotEntryAdded(const KonqHistoryEntry &entry)
0139 {
0140     // if it's already present, remove it, and inSort it
0141     s_mostEntries->removeEntry(entry.url);
0142 
0143     if (s_mostEntries->count() >= s_maxEntries) {
0144         const KonqHistoryEntry &leastOften = s_mostEntries->first();
0145         if (leastOften.numberOfTimesVisited < entry.numberOfTimesVisited) {
0146             s_mostEntries->removeFirst();
0147             inSort(entry);
0148         }
0149     }
0150 
0151     else {
0152         inSort(entry);
0153     }
0154     setEnabled(!s_mostEntries->isEmpty());
0155 }
0156 
0157 void KonqMostOftenURLSAction::slotEntryRemoved(const KonqHistoryEntry &entry)
0158 {
0159     s_mostEntries->removeEntry(entry.url);
0160     setEnabled(!s_mostEntries->isEmpty());
0161 }
0162 
0163 void KonqMostOftenURLSAction::slotHistoryCleared()
0164 {
0165     s_mostEntries->clear();
0166     setEnabled(false);
0167 }
0168 
0169 static void createHistoryAction(const KonqHistoryEntry &entry, QMenu *menu)
0170 {
0171     // we take either title, typedUrl or URL (in this order)
0172     const QString text = entry.title.isEmpty() ? (entry.typedUrl.isEmpty() ?
0173                          entry.url.toDisplayString() :
0174                          entry.typedUrl) :
0175                          entry.title;
0176     QAction *action = new QAction(
0177         QIcon::fromTheme(KonqPixmapProvider::self()->iconNameFor(entry.url)),
0178         text, menu);
0179     action->setData(entry.url);
0180     menu->addAction(action);
0181 }
0182 
0183 void KonqMostOftenURLSAction::slotFillMenu()
0184 {
0185     if (!m_parsingDone) { // first time
0186         parseHistory();
0187         m_parsingDone = true;
0188     }
0189 
0190     menu()->clear();
0191 
0192     for (int id = s_mostEntries->count() - 1; id >= 0; --id) {
0193         createHistoryAction(s_mostEntries->at(id), menu());
0194     }
0195     setEnabled(!s_mostEntries->isEmpty());
0196 }
0197 
0198 void KonqMostOftenURLSAction::slotActivated(QAction *action)
0199 {
0200     emit activated(action->data().value<QUrl>());
0201 }
0202 
0203 ///////////////////////////////
0204 
0205 KonqHistoryAction::KonqHistoryAction(const QString &text, QObject *parent)
0206     : KActionMenu(QIcon::fromTheme(QStringLiteral("go-jump")), text, parent)
0207 {
0208     setPopupMode(QToolButton::InstantPopup);
0209     connect(menu(), SIGNAL(aboutToShow()), SLOT(slotFillMenu()));
0210     connect(menu(), SIGNAL(triggered(QAction*)), SLOT(slotActivated(QAction*)));
0211     setEnabled(!KonqHistoryManager::kself()->entries().isEmpty());
0212 }
0213 
0214 KonqHistoryAction::~KonqHistoryAction()
0215 {
0216 }
0217 
0218 void KonqHistoryAction::slotFillMenu()
0219 {
0220     menu()->clear();
0221 
0222     // Use the same configuration as the "most visited urls" action
0223     s_maxEntries = KonqSettings::numberofmostvisitedURLs();
0224 
0225     KonqHistoryManager *mgr = KonqHistoryManager::kself();
0226     const KonqHistoryList mgrEntries = mgr->entries();
0227     int idx = mgrEntries.count() - 1;
0228     // mgrEntries is "oldest first", so take the last s_maxEntries entries.
0229     for (int n = 0; idx >= 0 && n < s_maxEntries; --idx, ++n) {
0230         createHistoryAction(mgrEntries.at(idx), menu());
0231     }
0232 }
0233 
0234 void KonqHistoryAction::slotActivated(QAction *action)
0235 {
0236     emit activated(action->data().value<QUrl>());
0237 }