File indexing completed on 2024-05-12 04:58:05
0001 /* ============================================================ 0002 * Falkon - Qt web browser 0003 * Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 * ============================================================ */ 0018 #include "history.h" 0019 #include "historymodel.h" 0020 #include "browserwindow.h" 0021 #include "iconprovider.h" 0022 #include "settings.h" 0023 #include "mainapplication.h" 0024 #include "sqldatabase.h" 0025 #include "webview.h" 0026 #include "qzsettings.h" 0027 0028 #include <QWebEngineProfile> 0029 0030 History::History(QObject* parent) 0031 : QObject(parent) 0032 , m_isSaving(true) 0033 , m_model(nullptr) 0034 { 0035 loadSettings(); 0036 } 0037 0038 HistoryModel* History::model() 0039 { 0040 if (!m_model) { 0041 m_model = new HistoryModel(this); 0042 } 0043 0044 return m_model; 0045 } 0046 0047 void History::loadSettings() 0048 { 0049 Settings settings; 0050 settings.beginGroup(QSL("Web-Browser-Settings")); 0051 m_isSaving = settings.value(QSL("allowHistory"), true).toBool(); 0052 settings.endGroup(); 0053 } 0054 0055 // AddHistoryEntry 0056 void History::addHistoryEntry(WebView* view) 0057 { 0058 if (!m_isSaving) { 0059 return; 0060 } 0061 0062 const QUrl url = view->url(); 0063 const QString title = view->title(); 0064 0065 addHistoryEntry(url, title); 0066 } 0067 0068 void History::addHistoryEntry(const QUrl &url, QString title) 0069 { 0070 if (!m_isSaving) { 0071 return; 0072 } 0073 0074 const QStringList schemes = { 0075 QSL("http"), QSL("https"), QSL("ftp"), QSL("file") 0076 }; 0077 0078 if (!schemes.contains(url.scheme()) && !qzSettings->allowedSchemes.contains(url.scheme())) { 0079 return; 0080 } 0081 0082 if (title.isEmpty()) { 0083 title = tr("Empty Page"); 0084 } 0085 0086 auto job = new SqlQueryJob(QSL("SELECT id, count, date, title FROM history WHERE url=?"), this); 0087 job->addBindValue(url); 0088 connect(job, &SqlQueryJob::finished, this, [=]() { 0089 if (job->records().isEmpty()) { 0090 auto job = new SqlQueryJob(QSL("INSERT INTO history (count, date, url, title) VALUES (1,?,?,?)"), this); 0091 job->addBindValue(QDateTime::currentMSecsSinceEpoch()); 0092 job->addBindValue(url); 0093 job->addBindValue(title); 0094 connect(job, &SqlQueryJob::finished, this, [=]() { 0095 HistoryEntry entry; 0096 entry.id = job->lastInsertId().toInt(); 0097 entry.count = 1; 0098 entry.date = QDateTime::currentDateTime(); 0099 entry.url = url; 0100 entry.urlString = QString::fromUtf8(url.toEncoded()); 0101 entry.title = title; 0102 Q_EMIT historyEntryAdded(entry); 0103 }); 0104 job->start(); 0105 } else { 0106 const auto record = job->records().at(0); 0107 const int id = record.value(0).toInt(); 0108 const int count = record.value(1).toInt(); 0109 const QDateTime date = QDateTime::fromMSecsSinceEpoch(record.value(2).toLongLong()); 0110 const QString oldTitle = record.value(3).toString(); 0111 0112 auto job = new SqlQueryJob(QSL("UPDATE history SET count = count + 1, date=?, title=? WHERE url=?"), this); 0113 job->addBindValue(QDateTime::currentMSecsSinceEpoch()); 0114 job->addBindValue(title); 0115 job->addBindValue(url); 0116 connect(job, &SqlQueryJob::finished, this, [=]() { 0117 HistoryEntry before; 0118 before.id = id; 0119 before.count = count; 0120 before.date = date; 0121 before.url = url; 0122 before.urlString = QString::fromUtf8(url.toEncoded()); 0123 before.title = oldTitle; 0124 0125 HistoryEntry after = before; 0126 after.count = count + 1; 0127 after.date = QDateTime::currentDateTime(); 0128 after.title = title; 0129 0130 Q_EMIT historyEntryEdited(before, after); 0131 }); 0132 job->start(); 0133 } 0134 }); 0135 job->start(); 0136 } 0137 0138 // DeleteHistoryEntry 0139 void History::deleteHistoryEntry(int index) 0140 { 0141 QList<int> list; 0142 list.append(index); 0143 0144 deleteHistoryEntry(list); 0145 } 0146 0147 void History::deleteHistoryEntry(const QList<int> &list) 0148 { 0149 QSqlDatabase db = SqlDatabase::instance()->database(); 0150 db.transaction(); 0151 0152 for (int index : list) { 0153 QSqlQuery query(SqlDatabase::instance()->database()); 0154 query.prepare(QSL("SELECT count, date, url, title FROM history WHERE id=?")); 0155 query.addBindValue(index); 0156 query.exec(); 0157 0158 if (!query.isActive() || !query.next()) { 0159 continue; 0160 } 0161 0162 HistoryEntry entry; 0163 entry.id = index; 0164 entry.count = query.value(0).toInt(); 0165 entry.date = QDateTime::fromMSecsSinceEpoch(query.value(1).toLongLong()); 0166 entry.url = query.value(2).toUrl(); 0167 entry.urlString = QString::fromUtf8(entry.url.toEncoded()); 0168 entry.title = query.value(3).toString(); 0169 0170 query.prepare(QSL("DELETE FROM history WHERE id=?")); 0171 query.addBindValue(index); 0172 query.exec(); 0173 0174 query.prepare(QSL("DELETE FROM icons WHERE url=?")); 0175 query.addBindValue(entry.url.toEncoded(QUrl::RemoveFragment)); 0176 query.exec(); 0177 0178 Q_EMIT historyEntryDeleted(entry); 0179 } 0180 0181 db.commit(); 0182 } 0183 0184 void History::deleteHistoryEntry(const QString &url) 0185 { 0186 QSqlQuery query(SqlDatabase::instance()->database()); 0187 query.prepare(QSL("SELECT id FROM history WHERE url=?")); 0188 query.bindValue(0, url); 0189 query.exec(); 0190 if (query.next()) { 0191 int id = query.value(0).toInt(); 0192 deleteHistoryEntry(id); 0193 } 0194 } 0195 0196 void History::deleteHistoryEntry(const QString &url, const QString &title) 0197 { 0198 QSqlQuery query(SqlDatabase::instance()->database()); 0199 query.prepare(QSL("SELECT id FROM history WHERE url=? AND title=?")); 0200 query.bindValue(0, url); 0201 query.bindValue(1, title); 0202 query.exec(); 0203 if (query.next()) { 0204 int id = query.value(0).toInt(); 0205 deleteHistoryEntry(id); 0206 } 0207 } 0208 0209 QList<int> History::indexesFromTimeRange(qint64 start, qint64 end) 0210 { 0211 QList<int> list; 0212 0213 if (start < 0 || end < 0) { 0214 return list; 0215 } 0216 0217 QSqlQuery query(SqlDatabase::instance()->database()); 0218 query.prepare(QSL("SELECT id FROM history WHERE date BETWEEN ? AND ?")); 0219 query.addBindValue(end); 0220 query.addBindValue(start); 0221 query.exec(); 0222 0223 while (query.next()) { 0224 list.append(query.value(0).toInt()); 0225 } 0226 0227 return list; 0228 } 0229 0230 QVector<HistoryEntry> History::mostVisited(int count) 0231 { 0232 QVector<HistoryEntry> list; 0233 QSqlQuery query(SqlDatabase::instance()->database()); 0234 query.prepare(QSL("SELECT count, date, id, title, url FROM history ORDER BY count DESC LIMIT %1").arg(count)); 0235 query.exec(); 0236 while (query.next()) { 0237 HistoryEntry entry; 0238 entry.count = query.value(0).toInt(); 0239 entry.date = query.value(1).toDateTime(); 0240 entry.id = query.value(2).toInt(); 0241 entry.title = query.value(3).toString(); 0242 entry.url = query.value(4).toUrl(); 0243 list.append(entry); 0244 } 0245 return list; 0246 } 0247 0248 void History::clearHistory() 0249 { 0250 QSqlQuery query(SqlDatabase::instance()->database()); 0251 query.exec(QSL("DELETE FROM history")); 0252 query.exec(QSL("VACUUM")); 0253 0254 mApp->webProfile()->clearAllVisitedLinks(); 0255 0256 Q_EMIT resetHistory(); 0257 } 0258 0259 void History::setSaving(bool state) 0260 { 0261 m_isSaving = state; 0262 } 0263 0264 bool History::isSaving() 0265 { 0266 return m_isSaving; 0267 } 0268 0269 QString History::titleCaseLocalizedMonth(int month) 0270 { 0271 switch (month) { 0272 case 1: 0273 return tr("January"); 0274 case 2: 0275 return tr("February"); 0276 case 3: 0277 return tr("March"); 0278 case 4: 0279 return tr("April"); 0280 case 5: 0281 return tr("May"); 0282 case 6: 0283 return tr("June"); 0284 case 7: 0285 return tr("July"); 0286 case 8: 0287 return tr("August"); 0288 case 9: 0289 return tr("September"); 0290 case 10: 0291 return tr("October"); 0292 case 11: 0293 return tr("November"); 0294 case 12: 0295 return tr("December"); 0296 default: 0297 qWarning("Month number out of range!"); 0298 return {}; 0299 } 0300 } 0301 0302 QList<HistoryEntry> History::searchHistoryEntry(const QString &text) 0303 { 0304 QList<HistoryEntry> list; 0305 QSqlQuery query(SqlDatabase::instance()->database()); 0306 query.prepare(QSL("SELECT count, date, id, title, url FROM history WHERE title LIKE ? OR url LIKE ?")); 0307 query.bindValue(0, QSL("%%1%").arg(text)); 0308 query.bindValue(1, QSL("%%1%").arg(text)); 0309 query.exec(); 0310 while (query.next()) { 0311 HistoryEntry entry; 0312 entry.count = query.value(0).toInt(); 0313 entry.date = query.value(1).toDateTime(); 0314 entry.id = query.value(2).toInt(); 0315 entry.title = query.value(3).toString(); 0316 entry.url = query.value(4).toUrl(); 0317 list.append(entry); 0318 } 0319 return list; 0320 } 0321 0322 HistoryEntry History::getHistoryEntry(const QString &text) 0323 { 0324 QSqlQuery query(SqlDatabase::instance()->database()); 0325 query.prepare(QSL("SELECT count, date, id, title, url FROM history WHERE url = ?")); 0326 query.bindValue(0, text); 0327 query.exec(); 0328 0329 HistoryEntry entry; 0330 if (query.next()) { 0331 entry.count = query.value(0).toInt(); 0332 entry.date = query.value(1).toDateTime(); 0333 entry.id = query.value(2).toInt(); 0334 entry.title = query.value(3).toString(); 0335 entry.url = query.value(4).toUrl(); 0336 } 0337 return entry; 0338 }