1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 **************************************************************************/
19 
20 #include "TabHistoryContentsWidget.h"
21 #include "../../../core/ThemesManager.h"
22 #include "../../../ui/Action.h"
23 #include "../../../ui/MainWindow.h"
24 #include "../../../ui/Window.h"
25 
26 #include "ui_TabHistoryContentsWidget.h"
27 
28 #include <QtWidgets/QDesktopWidget>
29 #include <QtWidgets/QToolTip>
30 
31 namespace Otter
32 {
33 
TabHistoryContentsWidget(const QVariantMap & parameters,QWidget * parent)34 TabHistoryContentsWidget::TabHistoryContentsWidget(const QVariantMap &parameters, QWidget *parent) : ContentsWidget(parameters, nullptr, parent),
35 	m_window(nullptr),
36 	m_ui(new Ui::TabHistoryContentsWidget)
37 {
38 	m_ui->setupUi(this);
39 	m_ui->filterLineEditWidget->setClearOnEscape(true);
40 	m_ui->historyViewWidget->setModel(new QStandardItemModel(this));
41 	m_ui->historyViewWidget->viewport()->installEventFilter(this);
42 	m_ui->historyViewWidget->viewport()->setMouseTracking(true);
43 
44 	const MainWindow *mainWindow(MainWindow::findMainWindow(parentWidget()));
45 
46 	if (mainWindow)
47 	{
48 		m_window = mainWindow->getActiveWindow();
49 
50 		connect(mainWindow, &MainWindow::currentWindowChanged, this, [=]()
51 		{
52 			Window *window(mainWindow->getActiveWindow());
53 
54 			if (window != m_window)
55 			{
56 				if (m_window)
57 				{
58 					disconnect(m_window, &Window::loadingStateChanged, this, &TabHistoryContentsWidget::updateHistory);
59 				}
60 
61 				m_window = window;
62 
63 				if (window)
64 				{
65 					connect(window, &Window::loadingStateChanged, this, &TabHistoryContentsWidget::updateHistory);
66 				}
67 			}
68 
69 			updateHistory();
70 		});
71 	}
72 
73 	updateHistory();
74 
75 	connect(m_ui->filterLineEditWidget, &LineEditWidget::textChanged, m_ui->historyViewWidget, &ItemViewWidget::setFilterString);
76 	connect(m_ui->historyViewWidget, &ItemViewWidget::customContextMenuRequested, this, &TabHistoryContentsWidget::showContextMenu);
77 	connect(m_ui->historyViewWidget, &ItemViewWidget::clicked, [&](const QModelIndex &index)
78 	{
79 		if (m_window && m_window->getWebWidget())
80 		{
81 			m_window->triggerAction(ActionsManager::GoToHistoryIndexAction, {{QLatin1String("index"), index.row()}});
82 		}
83 	});
84 }
85 
~TabHistoryContentsWidget()86 TabHistoryContentsWidget::~TabHistoryContentsWidget()
87 {
88 	delete m_ui;
89 }
90 
changeEvent(QEvent * event)91 void TabHistoryContentsWidget::changeEvent(QEvent *event)
92 {
93 	ContentsWidget::changeEvent(event);
94 
95 	if (event->type() == QEvent::LanguageChange)
96 	{
97 		m_ui->retranslateUi(this);
98 	}
99 }
100 
updateHistory()101 void TabHistoryContentsWidget::updateHistory()
102 {
103 	if (m_window)
104 	{
105 		const WindowHistoryInformation history(m_window->getHistory());
106 
107 		m_ui->historyViewWidget->getSourceModel()->clear();
108 
109 		for (int i = 0; i < history.entries.count(); ++i)
110 		{
111 			QStandardItem *item(new QStandardItem(history.entries.at(i).getTitle()));
112 			item->setData((history.entries.at(i).icon.isNull() ? ThemesManager::createIcon(QLatin1String("text-html")) : history.entries.at(i).icon), Qt::DecorationRole);
113 			item->setData(history.entries.at(i).url, UrlRole);
114 			item->setData(history.entries.at(i).time, TimeVisitedRole);
115 			item->setFlags(item->flags() | Qt::ItemNeverHasChildren);
116 
117 			if (i == history.index)
118 			{
119 				QFont font(item->font());
120 				font.setBold(true);
121 
122 				item->setFont(font);
123 			}
124 
125 			m_ui->historyViewWidget->getSourceModel()->appendRow(item);
126 		}
127 	}
128 	else
129 	{
130 		m_ui->historyViewWidget->getSourceModel()->clear();
131 	}
132 }
133 
showContextMenu(const QPoint & position)134 void TabHistoryContentsWidget::showContextMenu(const QPoint &position)
135 {
136 	const QModelIndex index(m_ui->historyViewWidget->indexAt(position));
137 	ActionExecutor::Object executor(m_window, m_window);
138 	QMenu menu(this);
139 
140 	if (index.isValid())
141 	{
142 		menu.addAction(new Action(ActionsManager::GoToHistoryIndexAction, {{QLatin1String("index"), index.row()}}, {{QLatin1String("icon"), {}}, {QLatin1String("text"), QCoreApplication::translate("actions", "Go to History Entry")}}, executor, &menu));
143 		menu.addSeparator();
144 		menu.addAction(new Action(ActionsManager::RemoveHistoryIndexAction, {{QLatin1String("index"), index.row()}}, executor, &menu));
145 		menu.addAction(new Action(ActionsManager::RemoveHistoryIndexAction, {{QLatin1String("index"), index.row()}, {QLatin1String("clearGlobalHistory"), true}}, executor, &menu));
146 		menu.addSeparator();
147 	}
148 
149 	menu.addAction(new Action(ActionsManager::ClearTabHistoryAction, {}, executor, &menu));
150 	menu.addAction(new Action(ActionsManager::ClearTabHistoryAction, {{QLatin1String("clearGlobalHistory"), true}}, {{QLatin1String("text"), QT_TRANSLATE_NOOP("actions", "Purge Tab History")}}, executor, &menu));
151 	menu.exec(m_ui->historyViewWidget->mapToGlobal(position));
152 }
153 
getTitle() const154 QString TabHistoryContentsWidget::getTitle() const
155 {
156 	return tr("Tab History");
157 }
158 
getType() const159 QLatin1String TabHistoryContentsWidget::getType() const
160 {
161 	return QLatin1String("tabHistory");
162 }
163 
getUrl() const164 QUrl TabHistoryContentsWidget::getUrl() const
165 {
166 	return {};
167 }
168 
getIcon() const169 QIcon TabHistoryContentsWidget::getIcon() const
170 {
171 	return ThemesManager::createIcon(QLatin1String("tab-history"), false);
172 }
173 
eventFilter(QObject * object,QEvent * event)174 bool TabHistoryContentsWidget::eventFilter(QObject *object, QEvent *event)
175 {
176 	if (object == m_ui->historyViewWidget->viewport() && event->type() == QEvent::ToolTip)
177 	{
178 		const QHelpEvent *helpEvent(static_cast<QHelpEvent*>(event));
179 		const QModelIndex index(m_ui->historyViewWidget->indexAt(helpEvent->pos()));
180 		QString toolTip;
181 
182 		if (index.isValid())
183 		{
184 			toolTip = tr("Title: %1").arg(index.data(TitleRole).toString()) + QLatin1Char('\n') + tr("Address: %1").arg(index.data(UrlRole).toUrl().toDisplayString());
185 
186 			if (!index.data(TimeVisitedRole).isNull())
187 			{
188 				toolTip.append(QLatin1Char('\n') + tr("Date: %1").arg(Utils::formatDateTime(index.data(TimeVisitedRole).toDateTime())));
189 			}
190 		}
191 
192 		QToolTip::showText(helpEvent->globalPos(), QFontMetrics(QToolTip::font()).elidedText(toolTip, Qt::ElideRight, (QApplication::desktop()->screenGeometry(m_ui->historyViewWidget).width() / 2)), m_ui->historyViewWidget, m_ui->historyViewWidget->visualRect(index));
193 
194 		return true;
195 	}
196 
197 	return ContentsWidget::eventFilter(object, event);
198 }
199 
200 }
201