File indexing completed on 2024-12-22 04:41:07

0001 /* ============================================================
0002 * Falkon - Qt web browser
0003 * Copyright (C) 2010-2017 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 "locationcompletermodel.h"
0019 #include "mainapplication.h"
0020 #include "iconprovider.h"
0021 #include "bookmarkitem.h"
0022 #include "bookmarks.h"
0023 #include "qzsettings.h"
0024 #include "browserwindow.h"
0025 #include "tabwidget.h"
0026 #include "sqldatabase.h"
0027 
0028 LocationCompleterModel::LocationCompleterModel(QObject* parent)
0029     : QStandardItemModel(parent)
0030 {
0031 }
0032 
0033 void LocationCompleterModel::setCompletions(const QList<QStandardItem*> &items)
0034 {
0035     clear();
0036     addCompletions(items);
0037 }
0038 
0039 void LocationCompleterModel::addCompletions(const QList<QStandardItem*> &items)
0040 {
0041     for (QStandardItem *item : items) {
0042         item->setIcon(QPixmap::fromImage(item->data(ImageRole).value<QImage>()));
0043         setTabPosition(item);
0044         if (item->icon().isNull()) {
0045             item->setIcon(IconProvider::emptyWebIcon());
0046         }
0047         appendRow(QList<QStandardItem*>{item});
0048     }
0049 }
0050 
0051 QList<QStandardItem*> LocationCompleterModel::suggestionItems() const
0052 {
0053     QList<QStandardItem*> items;
0054     for (int i = 0; i < rowCount(); ++i) {
0055         QStandardItem *it = item(i);
0056         if (it->data(SearchSuggestionRole).toBool()) {
0057             items.append(it);
0058         }
0059     }
0060     return items;
0061 }
0062 
0063 QSqlQuery LocationCompleterModel::createDomainQuery(const QString &text)
0064 {
0065     if (text.isEmpty() || text == QLatin1String("www.")) {
0066         return QSqlQuery(SqlDatabase::instance()->database());
0067     }
0068 
0069     bool withoutWww = text.startsWith(QLatin1Char('w')) && !text.startsWith(QLatin1String("www."));
0070     QString query = QSL("SELECT url FROM history WHERE ");
0071 
0072     if (withoutWww) {
0073         query.append(QLatin1String("url NOT LIKE ? AND url NOT LIKE ? AND "));
0074     }
0075     else {
0076         query.append(QLatin1String("url LIKE ? OR url LIKE ? OR "));
0077     }
0078 
0079     query.append(QLatin1String("(url LIKE ? OR url LIKE ?) ORDER BY date DESC LIMIT 1"));
0080 
0081     QSqlQuery sqlQuery(SqlDatabase::instance()->database());
0082     sqlQuery.prepare(query);
0083 
0084     if (withoutWww) {
0085         sqlQuery.addBindValue(QSL("http://www.%"));
0086         sqlQuery.addBindValue(QSL("https://www.%"));
0087         sqlQuery.addBindValue(QSL("http://%1%").arg(text));
0088         sqlQuery.addBindValue(QSL("https://%1%").arg(text));
0089     }
0090     else {
0091         sqlQuery.addBindValue(QSL("http://%1%").arg(text));
0092         sqlQuery.addBindValue(QSL("https://%1%").arg(text));
0093         sqlQuery.addBindValue(QSL("http://www.%1%").arg(text));
0094         sqlQuery.addBindValue(QSL("https://www.%1%").arg(text));
0095     }
0096 
0097     return sqlQuery;
0098 }
0099 
0100 QSqlQuery LocationCompleterModel::createHistoryQuery(const QString &searchString, int limit, bool exactMatch)
0101 {
0102     QStringList searchList;
0103     QString query = QLatin1String("SELECT id, url, title, count FROM history WHERE ");
0104 
0105     if (exactMatch) {
0106         query.append(QLatin1String("title LIKE ? OR url LIKE ? "));
0107     }
0108     else {
0109         searchList = searchString.split(QLatin1Char(' '), Qt::SkipEmptyParts);
0110         const int slSize = searchList.size();
0111         for (int i = 0; i < slSize; ++i) {
0112             query.append(QLatin1String("(title LIKE ? OR url LIKE ?) "));
0113             if (i < slSize - 1) {
0114                 query.append(QLatin1String("AND "));
0115             }
0116         }
0117     }
0118 
0119     query.append(QLatin1String("ORDER BY date DESC LIMIT ?"));
0120 
0121     QSqlQuery sqlQuery(SqlDatabase::instance()->database());
0122     sqlQuery.prepare(query);
0123 
0124     if (exactMatch) {
0125         sqlQuery.addBindValue(QSL("%%1%").arg(searchString));
0126         sqlQuery.addBindValue(QSL("%%1%").arg(searchString));
0127     }
0128     else {
0129         for (const QString &str : std::as_const(searchList)) {
0130             sqlQuery.addBindValue(QSL("%%1%").arg(str));
0131             sqlQuery.addBindValue(QSL("%%1%").arg(str));
0132         }
0133     }
0134 
0135     sqlQuery.addBindValue(limit);
0136 
0137     return sqlQuery;
0138 }
0139 
0140 void LocationCompleterModel::setTabPosition(QStandardItem* item) const
0141 {
0142     Q_ASSERT(item);
0143 
0144     item->setData(-1, TabPositionTabRole);
0145 
0146     if (!qzSettings->showSwitchTab || item->data(VisitSearchItemRole).toBool()) {
0147         return;
0148     }
0149 
0150     const QUrl url = item->data(UrlRole).toUrl();
0151     const QList<BrowserWindow*> windows = mApp->windows();
0152 
0153     for (BrowserWindow* window : windows) {
0154         QList<WebTab*> tabs = window->tabWidget()->allTabs();
0155         for (int i = 0; i < tabs.count(); ++i) {
0156             WebTab* tab = tabs.at(i);
0157             if (tab->url() == url) {
0158                 item->setData(QVariant::fromValue<void*>(static_cast<void*>(window)), TabPositionWindowRole);
0159                 item->setData(i, TabPositionTabRole);
0160                 return;
0161             }
0162         }
0163     }
0164 }
0165 
0166 void LocationCompleterModel::refreshTabPositions() const
0167 {
0168     for (int row = 0; row < rowCount(); ++row) {
0169         QStandardItem* itm = item(row);
0170         if (itm) {
0171             setTabPosition(itm);
0172         }
0173     }
0174 }