1 
2 /*
3  * CodeQuery
4  * Copyright (C) 2013-2017 ruben2020 https://github.com/ruben2020/
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  */
11 
12 
13 #include <stdlib.h>
14 #include <string.h>
15 #include <QProcess>
16 #include <QInputDialog>
17 #include <QFontDatabase>
18 
19 #include "ScintillaEdit.h"
20 #include "SciLexer.h"
21 
22 #include "fileviewer.h"
23 #include "mainwindow.h"
24 #include "fileviewsettingsdialog.h"
25 #include "themes.h"
26 
27 #ifdef _WIN32
28 #define EXT_EDITOR_DEFAULT_PATH "notepad %f"
29 #else
30 #define EXT_EDITOR_DEFAULT_PATH "gedit %f +%n"
31 #endif
32 
filedata()33 filedata::filedata()
34 {
35 	linenum = "1";
36 	fileid = -99;
37 }
filedata(const QString & fn,const QString & ln,const int & fi)38 filedata::filedata(const QString& fn, const QString& ln, const int& fi)
39 {
40 	linenum = ln;
41 	filename = fn;
42 	fileid = fi;
43 }
44 
compare(const filedata & fd)45 bool filedata::compare(const filedata& fd)
46 {
47 	bool cmp;
48 	if ((fileid < 0)||(fd.fileid < 0))
49 	{
50 		cmp = ((linenum.compare(fd.linenum) == 0)&&
51 			(filename.compare(fd.filename) == 0));
52 	}
53 	else
54 	{
55 		cmp = ((linenum.compare(fd.linenum) == 0)&&
56 			(fileid == fd.fileid));
57 	}
58 	return cmp;
59 }
60 
compareFilePathOnly(const filedata & fd)61 bool filedata::compareFilePathOnly(const filedata& fd)
62 {
63 	bool cmp;
64 	if ((fileid < 0)||(fd.fileid < 0))
65 	{
66 		cmp = (filename.compare(fd.filename) == 0);
67 	}
68 	else
69 	{
70 		cmp = (fileid == fd.fileid);
71 	}
72 	return cmp;
73 }
74 
compareFileNameOnly(const filedata & fd)75 bool filedata::compareFileNameOnly(const filedata& fd)
76 {
77 	bool cmp;
78 	if ((fileid < 0)||(fd.fileid < 0))
79 	{
80 		cmp =(strcmp(
81 		extract_filename(filename.C_STR()),
82 		extract_filename(fd.filename.C_STR())) == 0);
83 	}
84 	else
85 	{
86 		cmp = (fileid == fd.fileid);
87 	}
88 	return cmp;
89 }
90 
filedata(const filedata & fd)91 filedata::filedata(const filedata& fd)
92 {
93 	linenum = fd.linenum;
94 	filename = fd.filename;
95 	fileid = fd.fileid;
96 }
97 
operator =(const filedata & fd)98 filedata& filedata::operator=(const filedata& fd)
99 {
100 	if (&fd != this)
101 	{
102 		linenum = fd.linenum;
103 		filename = fd.filename;
104 		fileid = fd.fileid;
105 	}
106 	return *this;
107 }
108 
fileviewer(mainwindow * pmw)109 fileviewer::fileviewer(mainwindow* pmw)
110 :mw(pmw)
111 ,m_pushButtonPrev(NULL)
112 ,m_pushButtonNext(NULL)
113 ,m_pushButtonOpenInEditor(NULL)
114 ,m_pushButtonPaste(NULL)
115 ,m_pushButtonGoToLine(NULL)
116 ,m_labelFilePath(NULL)
117 ,m_textEditSource(NULL)
118 ,m_textEditSourceFont("Courier New", 12)
119 ,m_externalEditorPath(EXT_EDITOR_DEFAULT_PATH)
120 ,m_timestampMismatchWarned(false)
121 ,m_lexer(SCLEX_NULL)
122 ,m_fontsize(0)
123 ,m_currentlang(enHighlightCPP)
124 ,m_currentline(1)
125 ,m_annotline(1)
126 ,m_pushButtonTextShrink(NULL)
127 ,m_pushButtonTextEnlarge(NULL)
128 ,m_checkBoxSymbolOnly(NULL)
129 ,m_listWidgetFunc(NULL)
130 ,m_comboBoxFuncListSort(NULL)
131 ,m_fontwidthtemp(1)
132 ,m_markerhandle(1)
133 ,m_markerhandle2(2)
134 {
135 	m_iter = m_fileDataList.begin();
136 	m_textEditSourceFont.setStyleHint(QFont::TypeWriter);
137 }
138 
~fileviewer()139 fileviewer::~fileviewer()
140 {
141 	disconnect();
142 }
143 
createFontList(void)144 void fileviewer::createFontList(void)
145 {
146 	QFontDatabase fontdb;
147 	QStringList fontlst = fontdb.families(QFontDatabase::Latin);
148 	QStringList fixedpitch;
149 	QStringList::iterator it;
150 	for(it = fontlst.begin(); it != fontlst.end(); it++)
151 	{
152 		if (fontdb.isFixedPitch(*it))
153 		{
154 			fixedpitch << (*it);
155 		}
156 	}
157 	fixedpitch.sort();
158 	m_fontlist = fixedpitch;
159 }
160 
checkFontFamily(QString fontname)161 QString fileviewer::checkFontFamily(QString fontname)
162 {
163 	QString newfont;
164 #ifdef _WIN32
165 	QString tryfont1 = "Consolas";
166 	QString tryfont2 = "Courier New";
167 #else
168 	QString tryfont1 = "Monospace";
169 	QString tryfont2 = "Ubuntu Mono";
170 #endif
171 	if (m_fontlist.isEmpty()) createFontList();
172 	if (m_fontlist.contains(fontname))
173 	{
174 		newfont = fontname;
175 	}
176 	else
177 	{
178 #if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
179 		newfont = QFontDatabase::systemFont(QFontDatabase::FixedFont).family();
180 #else
181 		if      (m_fontlist.contains(tryfont1)) newfont = tryfont1;
182 		else if (m_fontlist.contains(tryfont2)) newfont = tryfont2;
183 		else newfont = m_fontlist[0];
184 #endif
185 	}
186 	return newfont;
187 }
188 
init(void)189 void fileviewer::init(void)
190 {
191 	Scintilla_LinkLexers();
192 	m_pushButtonPaste->setEnabled(false);
193 	m_pushButtonPrev->setEnabled(false);
194 	m_pushButtonNext->setEnabled(false);
195 	m_pushButtonTextShrink->setEnabled(false);
196 	m_pushButtonTextEnlarge->setEnabled(false);
197 	m_pushButtonGoToLine->setEnabled(false);
198 	m_pushButtonOpenInEditor->setEnabled(false);
199 	m_labelFilePath->clear();
200 	m_textEditSource->setWrapMode(SC_WRAP_NONE);
201 	m_textEditSource->setReadOnly(true);
202 	m_markerhandle = 0;
203 	m_markerhandle2 = 1;
204 	m_textEditSource->markerDefine(m_markerhandle, SC_MARK_BACKGROUND);
205 	m_textEditSource->markerDefine(m_markerhandle2, SC_MARK_ARROW);
206 	m_textEditSource->setMarginTypeN(0, SC_MARGIN_NUMBER);
207 	m_textEditSource->setMarginTypeN(1, SC_MARGIN_SYMBOL);
208 	m_textEditSource->annotationSetVisible(ANNOTATION_BOXED);
209 	m_textEditSource->setCodePage(SC_CP_UTF8);
210 	m_textEditSource->setCaretPeriod(0);
211 	createFontList();
212 	ScintillaEditBase *textEditSourceBase = m_textEditSource;
213 	connect(textEditSourceBase, SIGNAL(selectionChanged(bool)),
214 			this, SLOT(AbleToCopy(bool)));
215 	connect(m_pushButtonGoToLine, SIGNAL(clicked(bool)),
216 			this, SLOT(GoToLine_ButtonClick(bool)));
217 	connect(m_pushButtonPaste, SIGNAL(clicked(bool)),
218 			this, SLOT(Paste_ButtonClick(bool)));
219 	connect(m_pushButtonPrev, SIGNAL(clicked(bool)),
220 			this, SLOT(Prev_ButtonClick(bool)));
221 	connect(m_pushButtonNext, SIGNAL(clicked(bool)),
222 			this, SLOT(Next_ButtonClick(bool)));
223 	connect(m_pushButtonOpenInEditor, SIGNAL(clicked(bool)),
224 			this, SLOT(OpenInEditor_ButtonClick(bool)));
225 	connect(m_pushButtonTextShrink, SIGNAL(clicked(bool)),
226 			this, SLOT(TextShrink_ButtonClick(bool)));
227 	connect(m_pushButtonTextEnlarge, SIGNAL(clicked(bool)),
228 			this, SLOT(TextEnlarge_ButtonClick(bool)));
229 	connect(m_listWidgetFunc, SIGNAL(itemPressed(QListWidgetItem *)),
230 			this, SLOT(funcItemSelected(QListWidgetItem *)));
231 	connect(m_comboBoxFuncListSort, SIGNAL(currentIndexChanged(int)),
232 			this, SLOT(FuncListSort_indexChanged(int)));
233 	m_fileDataList.clear();
234 	clearTextEdit();
235 	setLexer();
236 }
237 
clearList()238 void fileviewer::clearList()
239 {
240 	//printf("Fileview clearlist\n");
241 	m_pushButtonPaste->setEnabled(false);
242 	m_pushButtonPrev->setEnabled(false);
243 	m_pushButtonNext->setEnabled(false);
244 	m_pushButtonTextShrink->setEnabled(false);
245 	m_pushButtonTextEnlarge->setEnabled(false);
246 	m_pushButtonGoToLine->setEnabled(false);
247 	m_pushButtonOpenInEditor->setEnabled(false);
248 	m_labelFilePath->clear();
249 	clearTextEdit();
250 	m_fileDataList.clear();
251 	m_iter = m_fileDataList.begin();
252 	m_timestampMismatchWarned = false;
253 	m_listWidgetFunc->clear();
254 }
255 
recvDBtimestamp(QDateTime dt)256 void fileviewer::recvDBtimestamp(QDateTime dt)
257 {
258 	m_DBtimestamp = dt;
259 }
260 
fileToBeOpened(QString filename,QString linenum,int fileid)261 void fileviewer::fileToBeOpened(QString filename, QString linenum, int fileid)
262 {
263 	filename.replace(QString("$HOME"), QDir::homePath());
264 #ifdef _WIN32
265 	filename.replace("/", "\\");
266 #endif
267 	if (!(QFile::exists(filename)))
268 	{
269 		m_labelFilePath->setText(tr("File not found"));
270 		handleFileCannotBeOpenedCase();
271 		return;
272 	}
273 	QFile file(filename);
274 	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
275 	{
276 		m_labelFilePath->setText(tr("File could not be opened"));
277 		handleFileCannotBeOpenedCase();
278 		return;
279 	}
280 	file.close();
281 
282 	QFileInfo fi(filename);
283 	if ((m_DBtimestamp < fi.lastModified())&&(m_timestampMismatchWarned == false))
284 	{
285 
286 		m_timestampMismatchWarned = true;
287 		QMessageBox msgBox((QWidget*)mw);
288 		msgBox.setIcon(QMessageBox::Warning);
289 		msgBox.setStandardButtons(QMessageBox::Ok);
290 		msgBox.setText(tr("The source file to be viewed is newer than the CodeQuery database file. You are recommended to manually regenerate the CodeQuery database file."));
291 		msgBox.exec();
292 	}
293 	filedata fd(filename, linenum, fileid);
294 	if (m_fileDataList.isEmpty())
295 	{
296 		//printf("Fileviewer: empty list\n");
297 		m_fileDataList.push_back(fd);
298 		m_iter = m_fileDataList.end() - 1;
299 		m_pushButtonPrev->setEnabled(false);
300 		m_pushButtonNext->setEnabled(false);
301 		updateTextEdit();
302 		return;
303 	}
304 	else if (m_iter == m_fileDataList.end())
305 	{
306 		// previous file not found
307 		//printf("Fileviewer: previous file not found %d, %d\n", m_fileDataList.end(), m_fileDataList.end() - 1);
308 		m_fileDataList.push_back(fd);
309 		m_iter = m_fileDataList.end() - 1;
310 		m_pushButtonPrev->setEnabled(m_iter != m_fileDataList.begin());
311 		m_pushButtonNext->setEnabled(false);
312 		updateTextEdit();
313 	}
314 	else if (m_iter->compare(fd))
315 	{
316 		// the same filename and line number
317 		//printf("Fileviewer: same filename and line number\n");
318 		updateFilePathLabel();
319 		return;
320 	}
321 	else if (m_iter->compareFilePathOnly(fd))
322 	{
323 		// same file, different line number
324 		//printf("Fileviewer: same file, different line number\n");
325 		m_fileDataList.push_back(fd);
326 		m_iter = m_fileDataList.end() - 1;
327 		m_pushButtonPrev->setEnabled(true);
328 		m_pushButtonNext->setEnabled(false);
329 		highlightLine(fd.linenum.toInt());
330 		updateFilePathLabel();
331 	}
332 	else
333 	{
334 		// different file
335 		//printf("Fileviewer: different file\n");
336 		m_fileDataList.push_back(fd);
337 		m_iter = m_fileDataList.end() - 1;
338 		m_pushButtonPrev->setEnabled(true);
339 		m_pushButtonNext->setEnabled(false);
340 		updateTextEdit();
341 	}
342 	if ((m_fileDataList.isEmpty())||(m_iter == m_fileDataList.end())) return;
343 	QVector<filedata>::iterator it = m_fileDataList.begin();
344 	while ((it != m_fileDataList.end() - 1)&&(it != m_fileDataList.end()))
345 	{
346 		if (it->compare(fd)) it = m_fileDataList.erase(it);
347 		else it++;
348 	}
349 	if (m_fileDataList.size() > 20) m_fileDataList.erase(m_fileDataList.begin());
350 	m_iter = m_fileDataList.end() - 1;
351 }
352 
clearTextEdit(void)353 void fileviewer::clearTextEdit(void)
354 {
355 	m_textEditSource->setReadOnly(false);
356 	m_textEditSource->clearAll();
357 	m_textEditSource->setReadOnly(true);
358 }
359 
updateTextEdit(void)360 void fileviewer::updateTextEdit(void)
361 {
362 	if (m_iter == m_fileDataList.end()) return;
363 	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
364 	clearTextEdit();
365 
366 	QFile file(m_iter->filename);
367 	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
368 	{
369 		QApplication::restoreOverrideCursor();
370 		return;
371 	}
372 	QTextStream in(&file);
373 
374 	int lang = enHighlightCPP; // default
375 
376 	QRegExp rx1("\\.py$", Qt::CaseInsensitive);
377 	int pos = rx1.indexIn(m_iter->filename);
378 	if (pos != -1) lang = enHighlightPython;
379 
380 	QRegExp rx2("\\.java$", Qt::CaseInsensitive);
381 	pos = rx2.indexIn(m_iter->filename);
382 	if (pos != -1) lang = enHighlightJava;
383 
384 	QRegExp rx3("\\.rb$", Qt::CaseInsensitive);
385 	pos = rx3.indexIn(m_iter->filename);
386 	if (pos != -1) lang = enHighlightRuby;
387 
388 	QRegExp rx4("\\.js$", Qt::CaseInsensitive);
389 	pos = rx4.indexIn(m_iter->filename);
390 	if (pos != -1) lang = enHighlightJavascript;
391 
392 	QRegExp rx5("\\.go$", Qt::CaseInsensitive);
393 	pos = rx5.indexIn(m_iter->filename);
394 	if (pos != -1) lang = enHighlightGo;
395 
396 	m_currentlang = lang;
397 
398 	QString alltext;
399 	while (!in.atEnd())
400 	{
401 		alltext = in.readAll();
402 	}
403 	m_textEditSource->setReadOnly(false);
404 	m_textEditSource->setText(alltext.toUtf8().data());
405 	m_textEditSource->setReadOnly(true);
406 	m_textEditSource->setMarginWidthN(0,  m_textEditSource->textWidth(STYLE_LINENUMBER, QString::number(m_textEditSource->lineCount() * 10).C_STR()));
407 	highlightLine(m_iter->linenum.toInt());
408 	updateFilePathLabel();
409 	m_pushButtonGoToLine->setEnabled(true);
410 	m_pushButtonOpenInEditor->setEnabled(true);
411 	m_pushButtonTextShrink->setEnabled(true);
412 	m_pushButtonTextEnlarge->setEnabled(true);
413 	m_listWidgetFunc->clear();
414 	if (m_iter->fileid < 0)	{emit requestFuncList_filename(m_iter->filename);}
415 	else {emit requestFuncList_fileid(m_iter->fileid);}
416 	setLexer(lang);
417 	QApplication::restoreOverrideCursor();
418 }
419 
updateFilePathLabel(void)420 void fileviewer::updateFilePathLabel(void)
421 {
422 	QString labeltext = m_iter->filename;
423 	labeltext += ":";
424 	labeltext += m_iter->linenum;
425 	m_labelFilePath->setText(labeltext);
426 	m_pushButtonGoToLine->setEnabled(true);
427 }
428 
braceMatchCheck(void)429 void fileviewer::braceMatchCheck(void)
430 {
431 	long cpos, matchpos;
432 	cpos     = m_textEditSource->currentPos();
433 	matchpos = m_textEditSource->braceMatch(cpos, 0);
434 	if (matchpos == -1)
435 	{
436 		cpos--;
437 		matchpos = m_textEditSource->braceMatch(cpos, 0);
438 	}
439 	if (matchpos != -1) m_textEditSource->braceHighlight(cpos, matchpos);
440 	else m_textEditSource->braceHighlight(-1, -1);
441 }
442 
updateFuncList(void)443 void fileviewer::updateFuncList(void)
444 {
445 	if (m_funclist.resultlist.empty()) return;
446 	long line = m_textEditSource->lineFromPosition(m_textEditSource->currentPos()) + 1;
447 	tStr selectedfunc = "";
448 	unsigned int selectedline, line1;
449 	auto previt = m_funclist.resultlist.begin();
450 	for (auto it = m_funclist.resultlist.begin(); it != m_funclist.resultlist.end(); it++)
451 	{
452 		if ( (line < it->intLinenum) && (line >= previt->intLinenum) )
453 		{
454 			selectedfunc = previt->symname;
455 			selectedline = previt->intLinenum;
456 			break;
457 		}
458 		previt = it;
459 	}
460 	if (selectedfunc.isEmpty() == false)
461 	{
462 		auto itemlist = m_listWidgetFunc->findItems(selectedfunc, Qt::MatchExactly);
463 		for (auto it = itemlist.begin(); it != itemlist.end(); it++)
464 		{
465 			line1 = (*it)->data(Qt::UserRole).toUInt();
466 			if (selectedline == line1)
467 			{
468 				m_listWidgetFunc->setCurrentItem(*it);
469 				break;
470 			}
471 		}
472 	}
473 }
474 
AbleToCopy(bool copy)475 void fileviewer::AbleToCopy(bool copy)
476 {
477 	m_pushButtonPaste->setEnabled(copy);
478 	m_textEditSource->annotationClearAll();
479 	braceMatchCheck();
480 	updateFuncList();
481 	if (copy)
482 	{
483 		m_textEditSource->copy();
484 		m_annotline = m_textEditSource->lineFromPosition(m_textEditSource->selectionEnd());
485 		QString str = (QApplication::clipboard())->text();
486 		if (str.length() > 0)
487 		{
488 			emit requestAnnotation(str);
489 		}
490 	}
491 }
492 
GoToLine_ButtonClick(bool checked)493 void fileviewer::GoToLine_ButtonClick(bool checked)
494 {
495 	if (!checked) highlightLine(m_iter->linenum.toInt());
496 }
497 
Prev_ButtonClick(bool checked)498 void fileviewer::Prev_ButtonClick(bool checked)
499 {
500 	if (m_fileDataList.isEmpty())
501 	{
502 		m_pushButtonPrev->setEnabled(false);
503 		m_pushButtonNext->setEnabled(false);
504 		return;
505 	}
506 	if(m_iter == m_fileDataList.begin())
507 	{
508 		m_pushButtonPrev->setEnabled(false);
509 		return;
510 	}
511 	if (!checked)
512 	{
513 		QVector<filedata>::iterator it = m_iter;
514 		m_iter--;
515 		if ((it != m_fileDataList.end())&&(m_iter->compareFilePathOnly(*it)))
516 		{
517 			highlightLine(m_iter->linenum.toInt());
518 			updateFilePathLabel();
519 		}
520 		else
521 		{
522 			updateTextEdit();
523 		}
524 		m_pushButtonPrev->setEnabled(m_iter != m_fileDataList.begin());
525 		m_pushButtonNext->setEnabled(m_iter != m_fileDataList.end() - 1);
526 	}
527 }
528 
Next_ButtonClick(bool checked)529 void fileviewer::Next_ButtonClick(bool checked)
530 {
531 	if (m_fileDataList.isEmpty())
532 	{
533 		m_pushButtonPrev->setEnabled(false);
534 		m_pushButtonNext->setEnabled(false);
535 		return;
536 	}
537 	if((m_iter == m_fileDataList.end() - 1)||
538 		(m_iter == m_fileDataList.end()))
539 	{
540 		m_pushButtonNext->setEnabled(false);
541 		return;
542 	}
543 	if (!checked)
544 	{
545 		QVector<filedata>::iterator it = m_iter;
546 		m_iter++;
547 		if (m_iter->compareFilePathOnly(*it))
548 		{
549 			highlightLine(m_iter->linenum.toInt());
550 			updateFilePathLabel();
551 		}
552 		else
553 		{
554 			updateTextEdit();
555 		}
556 		m_pushButtonPrev->setEnabled(m_iter != m_fileDataList.begin());
557 		m_pushButtonNext->setEnabled(m_iter != m_fileDataList.end() - 1);
558 	}
559 }
560 
handleFileCannotBeOpenedCase(void)561 void fileviewer::handleFileCannotBeOpenedCase(void)
562 {
563 	//printf("handleFileCannotBeOpenedCase\n");
564 	clearTextEdit();
565 	m_pushButtonTextShrink->setEnabled(false);
566 	m_pushButtonTextEnlarge->setEnabled(false);
567 	m_pushButtonGoToLine->setEnabled(false);
568 	m_pushButtonNext->setEnabled(false);
569 	m_pushButtonPrev->setEnabled(m_fileDataList.isEmpty() == false);
570 	m_iter = m_fileDataList.end();
571 }
572 
573 
Paste_ButtonClick(bool checked)574 void fileviewer::Paste_ButtonClick(bool checked)
575 {
576 	if (!checked)
577 	{
578 		m_textEditSource->copy();
579 		if (m_checkBoxSymbolOnly->isChecked())
580 			emit searchCopiedTextSymbolOnly();
581 		else emit searchCopiedText();
582 	}
583 }
584 
fileViewSettings_Triggered(bool checked)585 void fileviewer::fileViewSettings_Triggered(bool checked)
586 {
587 	cqDialogFileViewSettings cqdg((QWidget*)mw, this,
588 		m_fontlist, themes::getThemesList());
589 	m_fonttemp = m_textEditSourceFont.family();
590 	m_fontwidthtemp = (m_textEditSource->tabWidth());
591 	m_themetemp = m_theme;
592 	cqdg.setCurrentFontType(m_fonttemp);
593 	cqdg.setTabWidth(m_fontwidthtemp);
594 	cqdg.setCurrentTheme(m_themetemp);
595 	cqdg.setModal(true);
596 	cqdg.exec();
597 	if (cqdg.result() == QDialog::Accepted)
598 	{
599 		m_textEditSourceFont.setFamily(m_fonttemp);
600 		//m_lexer->setFont(m_textEditSourceFont);
601 		m_textEditSource->setTabWidth(m_fontwidthtemp);
602 		m_textEditSource->setZoom(m_fontsize);
603 		m_theme = m_themetemp;
604 		m_themelast = "1234";
605 		setLexer();
606 	}
607 }
608 
OptionsExtEditor_Triggered(bool checked)609 void fileviewer::OptionsExtEditor_Triggered(bool checked)
610 {
611 	bool ok;
612 	QString inptext;
613 	QInputDialog qinp(mw);
614 	qinp.setCancelButtonText(tr("Cancel"));
615 	qinp.setOkButtonText(tr("OK"));
616 	qinp.setInputMode(QInputDialog::TextInput);
617 	qinp.setWindowTitle(tr("External Editor Configuration"));
618 	QString exted = tr("Please enter the path and arguments for the external editor. Replace as follows:");
619 	exted += "\n%f - ";
620 	exted += tr("for file path");
621 	exted += "\n%n - ";
622 	exted += tr("for line number");
623 	exted += "\n";
624 	exted += tr("For example:");
625 #ifdef _WIN32
626 	exted += "\n\"C:\\Program Files\\Notepad++\\notepad++.exe\" -n%n %f";
627 #else
628 	exted += "\ngedit %f +%n";
629 #endif
630 	qinp.setLabelText(exted);
631 	qinp.setTextEchoMode(QLineEdit::Normal);
632 	qinp.setTextValue(m_externalEditorPath);
633 	qinp.exec();
634 	ok = (qinp.result() == QDialog::Accepted);
635 	inptext = qinp.textValue();
636 	if (ok && (inptext.isEmpty() == false)) m_externalEditorPath = inptext.trimmed();
637 }
638 
OpenInEditor_ButtonClick(bool checked)639 void fileviewer::OpenInEditor_ButtonClick(bool checked)
640 {
641 	QMessageBox msgBox(mw);
642 	msgBox.setIcon(QMessageBox::Warning);
643 	msgBox.setStandardButtons(QMessageBox::Ok);
644 	if (!checked)
645 	{
646 		QFile file(m_iter->filename);
647 		if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
648 		{
649 			msgBox.setText(tr("File could not be opened!"));
650 			msgBox.exec();
651 			return;
652 		}
653 		file.close();
654 
655 		QStringList arguments;
656 		QString program;
657 		QRegExp rx("^\"([^\"]+)\" (.*)");
658 		int pos = rx.indexIn(m_externalEditorPath);
659 		if (pos != -1)
660 		{
661 			program = rx.cap(1);
662 			arguments = (rx.cap(2)).split(QRegExp("[ ]+"));
663 		}
664 		else
665 		{
666 			arguments = m_externalEditorPath.split(QRegExp("[ ]+"));
667 			program = arguments.takeFirst();
668 		}
669 		arguments.replaceInStrings(QRegExp("%f"), m_iter->filename);
670 		arguments.replaceInStrings(QRegExp("%n"), m_iter->linenum);
671 
672 		if (QProcess::startDetached(program, arguments) == false)
673 		{
674 			msgBox.setText(tr("External editor could not be started. Please check Options!"));
675 			msgBox.exec();
676 			return;
677 		}
678 	}
679 }
680 
TextShrink_ButtonClick(bool checked)681 void fileviewer::TextShrink_ButtonClick(bool checked)
682 {
683 	if (!checked)
684 	{
685 		textSizeChange(0-1);
686 		//m_textEditSource->zoomOut();
687 	}
688 }
689 
TextEnlarge_ButtonClick(bool checked)690 void fileviewer::TextEnlarge_ButtonClick(bool checked)
691 {
692 	if (!checked)
693 	{
694 		textSizeChange(1);
695 		//m_textEditSource->zoomIn();
696 	}
697 }
698 
textSizeChange(int n)699 void fileviewer::textSizeChange(int n)
700 {
701 	//m_fontwidthtemp = (m_textEditSource->tabWidth());
702 	//m_lexer->setFont(m_textEditSourceFont);
703 	m_fontsize += n;
704 	m_textEditSource->setZoom(m_fontsize);
705 	m_textEditSource->setMarginWidthN(0,  m_textEditSource->textWidth(STYLE_LINENUMBER, QString::number(m_textEditSource->lineCount() * 10).C_STR()));
706 	//m_textEditSource->setTabWidth(m_fontwidthtemp);
707 }
708 
fontSelectionTemporary(const QString & fonttxt)709 void fileviewer::fontSelectionTemporary(const QString &fonttxt)
710 {
711 	m_fonttemp = fonttxt;
712 }
713 
themeSelectionTemporary(const QString & themetxt)714 void fileviewer::themeSelectionTemporary(const QString &themetxt)
715 {
716 	m_themetemp = themetxt;
717 }
718 
tabWidthSelectionTemporary(const QString & width)719 void fileviewer::tabWidthSelectionTemporary(const QString &width)
720 {
721 	m_fontwidthtemp = width.toInt();
722 }
723 
highlightLine(unsigned int num)724 void fileviewer::highlightLine(unsigned int num)
725 {
726 	m_textEditSource->markerDeleteAll(-1);
727 	if (num <= 0)
728 	{
729 		num = 1;
730 	}
731 	else
732 	{
733 		num = num - 1; // not sure why it's one off
734 		m_textEditSource->markerAdd(num, m_markerhandle);
735 		m_textEditSource->markerAdd(num, m_markerhandle2);
736 	}
737 	m_textEditSource->setFirstVisibleLine(num);
738 	m_currentline = num;
739 }
740 
setLexer(int lang)741 void fileviewer::setLexer(int lang)
742 {
743 	if (lang == -1) lang = m_currentlang;
744 
745 	switch(lang)
746 	{
747 
748 		case enHighlightCPP:
749 			replaceLexer(SCLEX_CPP, lang);
750 			break;
751 
752 		case enHighlightPython:
753 			replaceLexer(SCLEX_PYTHON, lang);
754 			break;
755 
756 		case enHighlightJava:
757 			replaceLexer(SCLEX_CPP, lang);
758 			break;
759 
760 		case enHighlightRuby:
761 			replaceLexer(SCLEX_RUBY, lang);
762 			break;
763 
764 		case enHighlightJavascript:
765 			replaceLexer(SCLEX_CPP, lang);
766 			break;
767 
768 		default:
769 			replaceLexer(SCLEX_CPP, lang);
770 			break;
771 
772 	}
773 }
774 
replaceLexer(int sclang,int lang)775 void fileviewer::replaceLexer(int sclang, int lang)
776 {
777 	QColor markerlinebgcolor;
778 	QColor linenumfgcolor;
779 	//if (m_lexer != sclang)
780 	{
781 		switch (lang)
782 		{
783 			case enHighlightCPP:
784 				m_lexer = SCLEX_CPP;
785 				break;
786 
787 			case enHighlightPython:
788 				m_lexer = SCLEX_PYTHON;
789 				break;
790 
791 			case enHighlightJava:
792 				m_lexer = SCLEX_CPP;
793 				break;
794 
795 			case enHighlightRuby:
796 				m_lexer = SCLEX_RUBY;
797 				break;
798 
799 			case enHighlightJavascript:
800 				m_lexer = SCLEX_CPP;
801 				break;
802 
803 			default:
804 				m_lexer = SCLEX_CPP;
805 				break;
806 		}
807 		m_textEditSource->setLexer(m_lexer);
808 		m_textEditSource->clearDocumentStyle();
809 		m_textEditSource->setZoom(m_fontsize);
810 		m_themelast = "1234";
811 	}
812 	//if (m_themelast.compare(m_theme) != 0)
813 	{
814 		m_themelast = m_theme;
815 		themes::setTheme(m_theme, lang, m_textEditSource, m_textEditSourceFont, markerlinebgcolor, linenumfgcolor);
816 		m_textEditSource->markerSetBack(m_markerhandle, themes::QC2SC(markerlinebgcolor));
817 		m_textEditSource->markerSetBack(m_markerhandle2, themes::QC2SC(linenumfgcolor));
818 		m_textEditSource->markerSetAlpha(m_markerhandle, SC_ALPHA_NOALPHA);
819 		m_textEditSource->markerSetAlpha(m_markerhandle2, SC_ALPHA_NOALPHA);
820 		m_textEditSource->styleSetFont(STYLE_LINENUMBER, m_textEditSourceFont.family().C_STR());
821 		m_textEditSource->setZoom(m_fontsize);
822 		m_textEditSource->setMarginWidthN(0, m_textEditSource->textWidth(STYLE_LINENUMBER, QString::number(m_textEditSource->lineCount() * 10).C_STR()));
823 		themes::setKeywords(lang, m_textEditSource);
824 		m_textEditSource->colourise(0, -1);
825 	}
826 }
827 
annotate(QStringList annotstrLst)828 void fileviewer::annotate(QStringList annotstrLst)
829 {
830 	m_textEditSource->copy();
831 	QString str = (QApplication::clipboard())->text();
832 	m_annotline = m_textEditSource->lineFromPosition(m_textEditSource->selectionEnd());
833 	if ((annotstrLst.length() >= 2)&&(annotstrLst[0] == str))
834 	{
835 		m_textEditSource->annotationClearAll();
836 		m_textEditSource->annotationSetText(m_annotline, annotstrLst[1].toUtf8().data());
837 		m_textEditSource->annotationSetStyle(m_annotline, 29);
838 	}
839 	else if (str.length() > 0)
840 	{
841 		emit requestAnnotation(str);
842 	}
843 }
844 
recvFuncList(sqlqueryresultlist * reslist)845 void fileviewer::recvFuncList(sqlqueryresultlist* reslist)
846 {
847 	m_listWidgetFunc->clear();
848 	if ((m_fileDataList.isEmpty())||(m_iter == m_fileDataList.end())) return;
849 	m_funclist = *reslist;
850 	m_funclist.sort_by_linenum();
851 	for (auto it = m_funclist.resultlist.begin(); it != m_funclist.resultlist.end(); it++)
852 	{
853 		it->intLinenum = atoi(it->linenum.C_STR());
854 	}
855 	filedata fd(m_funclist.resultlist[0].filename, "1", -99);
856 	if (m_iter->compareFileNameOnly(fd) == false)
857 	{
858 		if (m_iter->fileid < 0)	{emit requestFuncList_filename(m_iter->filename);}
859 		else {emit requestFuncList_fileid(m_iter->fileid);}
860 		return;
861 	}
862 	sqlqueryresultlist templist = m_funclist;
863 	if (m_comboBoxFuncListSort->currentIndex() != 0) templist.sort_by_name();
864 	QListWidgetItem* item;
865 	for (auto it = templist.resultlist.begin(); it != templist.resultlist.end(); it++)
866 	{
867 		item = new QListWidgetItem(it->symname);
868 		item->setData(Qt::UserRole, QVariant(it->intLinenum));
869 		m_listWidgetFunc->addItem(item);
870 	}
871 }
872 
funcItemSelected(QListWidgetItem * curitem)873 void fileviewer::funcItemSelected(QListWidgetItem * curitem)
874 {
875 	if (curitem == nullptr) return;
876 	unsigned int num = curitem->data(Qt::UserRole).toUInt();
877 	m_textEditSource->setFirstVisibleLine(num - 1);
878 }
879 
FuncListSort_indexChanged(const int & idx)880 void fileviewer::FuncListSort_indexChanged(const int& idx)
881 {
882 	recvFuncList(&m_funclist);
883 }
884 
885