1 //=============================================================================
2 //
3 //   File : KviIrcView_tools.cpp
4 //   Creation date : Sat Oct 9 2004 16:03:01 by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2004-2010 Szymon Stefanek (pragma at kvirc dot net)
8 //
9 //   This program is FREE software. You can redistribute it and/or
10 //   modify it under the terms of the GNU General Public License
11 //   as published by the Free Software Foundation; either version 2
12 //   of the License, or (at your option) any later version.
13 //
14 //   This program is distributed in the HOPE that it will be USEFUL,
15 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 //   See the GNU General Public License for more details.
18 //
19 //   You should have received a copy of the GNU General Public License
20 //   along with this program. If not, write to the Free Software Foundation,
21 //   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24 
25 #include "KviIrcView_tools.h"
26 #include "KviIrcView.h"
27 #include "KviIconManager.h"
28 #include "KviOptions.h"
29 #include "KviLocale.h"
30 #include "KviMemory.h"
31 #include "KviMessageBox.h"
32 #include "KviFileDialog.h"
33 #include "KviApplication.h"
34 #include "KviThemedLineEdit.h"
35 #include "KviShortcut.h"
36 #include "KviWindow.h"
37 
38 #include <QHBoxLayout>
39 #include <QLabel>
40 #include <QPushButton>
41 #include <QCursor>
42 #include <QEvent>
43 #include <QMouseEvent>
44 #include <QHeaderView>
45 #include <QScrollBar>
46 #include <QComboBox>
47 #include <QIcon>
48 #include <QMenu>
49 
50 //
51 // Tool widget implementation
52 //
53 
KviIrcMessageCheckListItem(QTreeWidget * par,KviIrcViewToolWidget * w,int id)54 KviIrcMessageCheckListItem::KviIrcMessageCheckListItem(QTreeWidget * par, KviIrcViewToolWidget * w, int id)
55     : QTreeWidgetItem(par)
56 {
57 	m_iId = id;
58 	setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
59 	setCheckState(0, Qt::Checked);
60 	setIcon(0, *(g_pIconManager->getSmallIcon(KVI_OPTION_MSGTYPE(id).pixId())));
61 	setText(0, __tr2qs_no_xgettext(KVI_OPTION_MSGTYPE(id).type()));
62 	m_pToolWidget = w;
63 }
64 
65 KviIrcMessageCheckListItem::~KviIrcMessageCheckListItem()
66     = default;
67 
KviIrcViewToolWidget(KviIrcView * pParent)68 KviIrcViewToolWidget::KviIrcViewToolWidget(KviIrcView * pParent)
69     : QWidget(pParent)
70 {
71 	m_pIrcView = pParent;
72 	setAutoFillBackground(true);
73 	setContentsMargins(0, 0, 0, 0);
74 
75 	QHBoxLayout * pLayout = new QHBoxLayout(this);
76 	pLayout->setMargin(2);
77 	pLayout->setSpacing(2);
78 
79 	QPushButton * pButton = new QPushButton(QIcon(*g_pIconManager->getSmallIcon(KviIconManager::Close)), QString(), this);
80 	pButton->setFixedSize(16, 16);
81 	pButton->setFlat(true);
82 	connect(pButton, SIGNAL(clicked()), m_pIrcView, SLOT(toggleToolWidget()));
83 	pLayout->addWidget(pButton);
84 
85 	m_pStringToFind = new KviThemedLineEdit(this, m_pIrcView->parentKviWindow(), "search_lineedit");
86 	pLayout->addWidget(m_pStringToFind);
87 	connect(m_pStringToFind, SIGNAL(returnPressed()), this, SLOT(findNext()));
88 	connect(m_pStringToFind, SIGNAL(textChanged(QString)), this, SLOT(findNextHelper(QString)));
89 
90 	pButton = new QPushButton(__tr2qs("&Next"), this);
91 	pButton->setDefault(true);
92 	connect(pButton, SIGNAL(clicked()), this, SLOT(findNext()));
93 	pLayout->addWidget(pButton);
94 
95 	pButton = new QPushButton(__tr2qs("&Previous"), this);
96 	connect(pButton, SIGNAL(clicked()), this, SLOT(findPrev()));
97 	pLayout->addWidget(pButton);
98 
99 	m_pOptionsButton = new QPushButton(this);
100 	m_pOptionsButton->setText(__tr2qs("&Options"));
101 	pLayout->addWidget(m_pOptionsButton);
102 
103 	m_pOptionsWidget = new QMenu(m_pOptionsButton);
104 	QGridLayout * pOptionsLayout = new QGridLayout(m_pOptionsWidget);
105 	pOptionsLayout->setSpacing(2);
106 
107 	connect(m_pOptionsButton, SIGNAL(clicked()), this, SLOT(toggleOptions()));
108 
109 	// Filter tab
110 
111 	QLabel * pLabel = new QLabel(__tr2qs("Message Types"), m_pOptionsWidget); //groupbox title
112 	pOptionsLayout->addWidget(pLabel, 0, 0, 1, 2);
113 
114 	m_pFilterView = new QTreeWidget(m_pOptionsWidget);
115 	m_pFilterView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
116 	m_pFilterView->setRootIsDecorated(false);
117 	//FIXME hardcoded size sucks
118 	m_pFilterView->setMinimumSize(QSize(200, 150));
119 	m_pFilterView->setColumnCount(1);
120 	m_pFilterView->header()->hide();
121 	pOptionsLayout->addWidget(m_pFilterView, 1, 0, 4, 2);
122 
123 	m_pFilterItems = (KviIrcMessageCheckListItem **)KviMemory::allocate(KVI_NUM_MSGTYPE_OPTIONS * sizeof(KviIrcMessageCheckListItem *));
124 
125 	for(int i = 0; i < KVI_NUM_MSGTYPE_OPTIONS; i++)
126 	{
127 		m_pFilterItems[i] = new KviIrcMessageCheckListItem(m_pFilterView, this, i);
128 	}
129 
130 	pButton = new QPushButton(__tr2qs("Set &All"), m_pOptionsWidget);
131 	connect(pButton, SIGNAL(clicked()), this, SLOT(filterEnableAll()));
132 	pOptionsLayout->addWidget(pButton, 6, 0);
133 
134 	pButton = new QPushButton(__tr2qs("Set &None"), m_pOptionsWidget);
135 	connect(pButton, SIGNAL(clicked()), this, SLOT(filterEnableNone()));
136 	pOptionsLayout->addWidget(pButton, 6, 1);
137 
138 	pButton = new QPushButton(__tr2qs("&Load from..."), m_pOptionsWidget);
139 	connect(pButton, SIGNAL(clicked()), this, SLOT(filterLoad()));
140 	pOptionsLayout->addWidget(pButton, 7, 0);
141 
142 	pButton = new QPushButton(__tr2qs("&Save As..."), m_pOptionsWidget);
143 	connect(pButton, SIGNAL(clicked()), this, SLOT(filterSave()));
144 	pOptionsLayout->addWidget(pButton, 7, 1);
145 
146 	pLabel = new QLabel(__tr2qs("Pattern:"), m_pOptionsWidget);
147 	pOptionsLayout->addWidget(pLabel, 8, 0);
148 	m_pSearchMode = new QComboBox(m_pOptionsWidget);
149 	m_pSearchMode->insertItem(PlainText, __tr2qs("Plain Text"));
150 	m_pSearchMode->insertItem(Wildcards, __tr2qs("Wildcards"));
151 	m_pSearchMode->insertItem(RegExp, __tr2qs("RegExp"));
152 	pOptionsLayout->addWidget(m_pSearchMode, 8, 1);
153 
154 	pLabel = new QLabel(__tr2qs("Match:"), m_pOptionsWidget);
155 	pOptionsLayout->addWidget(pLabel, 9, 0);
156 
157 	m_pCaseSensitive = new QCheckBox(__tr2qs("&Case sensitive"), m_pOptionsWidget);
158 	pOptionsLayout->addWidget(m_pCaseSensitive, 9, 1);
159 
160 	// Focusing the 'string to find' widget has been moved to the toggle function so that it happens whenever the widget is shown
161 
162 	KviShortcut::create(Qt::Key_Escape, m_pIrcView, SLOT(toggleToolWidget()), nullptr, Qt::WidgetWithChildrenShortcut);
163 	KviShortcut::create(KVI_SHORTCUTS_WIN_SEARCH, m_pIrcView, SLOT(toggleToolWidget()), nullptr, Qt::WidgetWithChildrenShortcut);
164 }
165 
~KviIrcViewToolWidget()166 KviIrcViewToolWidget::~KviIrcViewToolWidget()
167 {
168 	if(m_pIrcView)
169 		if(m_pIrcView->parentKviWindow())
170 			if(m_pIrcView->parentKviWindow()->input())
171 				m_pIrcView->parentKviWindow()->input()->setFocus();
172 }
173 
toggleOptions()174 void KviIrcViewToolWidget::toggleOptions()
175 {
176 	if(m_pOptionsWidget->isVisible())
177 	{
178 		m_pOptionsWidget->hide();
179 	}
180 	else
181 	{
182 		m_pOptionsWidget->adjustSize();
183 		QPoint p = QPoint(
184 		    m_pOptionsButton->pos().x() + m_pOptionsButton->width() - m_pOptionsWidget->width(),
185 		    m_pOptionsButton->pos().y() - m_pOptionsWidget->height());
186 		m_pOptionsWidget->popup(mapToGlobal(p));
187 	}
188 }
189 
filterEnableAll()190 void KviIrcViewToolWidget::filterEnableAll()
191 {
192 	for(int i = 0; i < KVI_NUM_MSGTYPE_OPTIONS; i++)
193 		m_pFilterItems[i]->setOn(true);
194 }
195 
filterEnableNone()196 void KviIrcViewToolWidget::filterEnableNone()
197 {
198 	for(int i = 0; i < KVI_NUM_MSGTYPE_OPTIONS; i++)
199 		m_pFilterItems[i]->setOn(false);
200 }
201 
filterLoad()202 void KviIrcViewToolWidget::filterLoad()
203 {
204 	QString szFile;
205 	QString szInit;
206 	g_pApp->getLocalKvircDirectory(szInit, KviApplication::Filters);
207 
208 	if(KviFileDialog::askForOpenFileName(szFile, __tr2qs("Select a File - KVIrc"), szInit, QString(), false, true, this)) // This is the window title
209 	{
210 		QFile f(szFile);
211 		if(f.open(QIODevice::ReadOnly))
212 		{
213 			char cBuffer[KVI_NUM_MSGTYPE_OPTIONS];
214 			KviMemory::set(cBuffer, 0, KVI_NUM_MSGTYPE_OPTIONS);
215 			f.read(cBuffer, KVI_NUM_MSGTYPE_OPTIONS);
216 			f.close();
217 			for(int i = 0; i < KVI_NUM_MSGTYPE_OPTIONS; i++)
218 			{
219 				m_pFilterItems[i]->setOn(cBuffer[i]);
220 			}
221 			forceRepaint();
222 		}
223 		else
224 		{
225 			KviMessageBox::warning(__tr2qs("Can't open the filter file %s for reading."), &szFile);
226 		}
227 	}
228 }
229 
filterSave()230 void KviIrcViewToolWidget::filterSave()
231 {
232 	QString szFile;
233 	QString szInit;
234 	g_pApp->getLocalKvircDirectory(szInit, KviApplication::Filters, "filter.kvf");
235 	if(KviFileDialog::askForSaveFileName(szFile, __tr2qs("Enter a Filename - KVIrc"), szInit, QString(), false, false, true, this)) // this is the window title
236 	{
237 		QFile f(szFile);
238 		if(f.open(QIODevice::WriteOnly))
239 		{
240 			char cBuffer[KVI_NUM_MSGTYPE_OPTIONS];
241 			for(int i = 0; i < KVI_NUM_MSGTYPE_OPTIONS; i++)
242 			{
243 				cBuffer[i] = messageEnabled(i) ? 1 : 0;
244 			}
245 			if(f.write(cBuffer, KVI_NUM_MSGTYPE_OPTIONS) < KVI_NUM_MSGTYPE_OPTIONS)
246 				KviMessageBox::warning(__tr2qs("Failed to write the filter file %Q (IO Error)"), &szFile);
247 			f.close();
248 		}
249 		else
250 			KviMessageBox::warning(__tr2qs("Can't open the filter file %Q for writing"), &szFile);
251 	}
252 }
253 
focusStringToFind()254 void KviIrcViewToolWidget::focusStringToFind()
255 {
256 #ifndef COMPILE_ON_MAC
257 	m_pStringToFind->setFocus(); // this makes MacOSX version of Qt go nuts and crash
258 #endif                           //!COMPILE_ON_MAC
259 }
260 
forceRepaint()261 void KviIrcViewToolWidget::forceRepaint()
262 {
263 #if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW)
264 	m_pIrcView->repaint();
265 #else
266 	m_pIrcView->paintEvent(nullptr);
267 #endif
268 }
269 
setFindResult(const QString &)270 void KviIrcViewToolWidget::setFindResult(const QString &)
271 {
272 	// 	m_pFindResult->setText(szText);
273 }
274 
findPrev()275 void KviIrcViewToolWidget::findPrev()
276 {
277 	SearchMode eMode = (SearchMode)m_pSearchMode->currentIndex();
278 	m_pIrcView->findPrev(m_pStringToFind->text(), m_pCaseSensitive->isChecked(), eMode != PlainText, eMode == RegExp);
279 }
280 
findNextHelper(QString)281 void KviIrcViewToolWidget::findNextHelper(QString)
282 {
283 	m_pIrcView->m_pCursorLine = m_pIrcView->m_pFirstLine;
284 	findNext();
285 }
286 
findNext()287 void KviIrcViewToolWidget::findNext()
288 {
289 	SearchMode eMode = (SearchMode)m_pSearchMode->currentIndex();
290 	m_pIrcView->findNext(m_pStringToFind->text(), m_pCaseSensitive->isChecked(), eMode != PlainText, eMode == RegExp);
291 }
292 
293 //
294 // Link tip label implementation
295 //
296 
KviIrcViewToolTip(KviIrcView * pView)297 KviIrcViewToolTip::KviIrcViewToolTip(KviIrcView * pView)
298     : KviTalToolTip(pView)
299 {
300 	m_pView = pView;
301 }
302 
303 KviIrcViewToolTip::~KviIrcViewToolTip()
304     = default;
305 
maybeTip(const QPoint & pnt)306 void KviIrcViewToolTip::maybeTip(const QPoint & pnt)
307 {
308 	m_pView->maybeTip(pnt);
309 }
310