aboutsummaryrefslogtreecommitdiffstats
//=============================================================================
//
//   File : HelpWindow.cpp
//   Creation date : Tue Aug 11 2000 18:08:22 by Szymon Stefanek
//
//   This file is part of the KVIrc IRC client distribution
//   Copyright (C) 2000-2010 Szymon Stefanek (pragma at kvirc dot net)
//
//   This program is FREE software. You can redistribute it and/or
//   modify it under the m_terms of the GNU General Public License
//   as published by the Free Software Foundation; either version 2
//   of the License, or (at your option) any later version.
//
//   This program is distributed in the HOPE that it will be USEFUL,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//   See the GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program. If not, write to the Free Software Foundation,
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================

#include "HelpWindow.h"
#include "HelpWidget.h"

#include "kvi_settings.h"
#include "KviApplication.h"
#include "KviIconManager.h"
#include "KviOptions.h"
#include "KviLocale.h"
#include "KviModule.h"
#include "KviRegExp.h"
#include "KviConfigurationFile.h"
#include "kvi_sourcesdate.h"

#include <QList>
#include <QFileInfo>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QToolTip>
#include <QTimer>

extern HelpIndex * g_pDocIndex;
extern KviPointerList<HelpWindow> * g_pHelpWindowList;
extern KviPointerList<HelpWidget> * g_pHelpWidgetList;

//bool g_bIndexingDone = false;
HelpWindow::HelpWindow(const char * name)
    : KviWindow(KviWindow::Help, name)
{
	g_pHelpWindowList->append(this);
	setMinimumSize(600, 500);
	m_pSplitter = new KviTalSplitter(Qt::Horizontal, this);
	m_pSplitter->setObjectName("main_splitter");
	m_pSplitter->setChildrenCollapsible(false);

	m_pHelpWidget = new HelpWidget(m_pSplitter);

	m_pToolBar = new KviTalVBox(m_pSplitter);
	m_pTabWidget = new QTabWidget(m_pToolBar);

	m_pBottomLayout = new KviTalHBox(m_pToolBar);
	m_pProgressBar = new QProgressBar(m_pBottomLayout);
	m_pCancelButton = new QPushButton(m_pBottomLayout);
	m_pCancelButton->setText(__tr2qs_ctx("Cancel", "logview"));
	connect(m_pCancelButton, SIGNAL(clicked()), g_pDocIndex, SLOT(setLastWinClosed()));
	m_pBottomLayout->setVisible(false);

	m_pIndexTab = new KviTalVBox(m_pTabWidget);
	m_pTabWidget->addTab(m_pIndexTab, __tr2qs("Help Index"));

	KviTalHBox * pSearchBox = new KviTalHBox(m_pIndexTab);
	m_pIndexSearch = new QLineEdit(pSearchBox);
	connect(m_pIndexSearch, SIGNAL(textChanged(const QString &)), this, SLOT(searchInIndex(const QString &)));
	connect(m_pIndexSearch, SIGNAL(returnPressed()), this, SLOT(showIndexTopic()));

	m_pBtnRefreshIndex = new QPushButton(pSearchBox);
	m_pBtnRefreshIndex->setIcon(*g_pIconManager->getBigIcon(KVI_REFRESH_IMAGE_NAME));
	connect(m_pBtnRefreshIndex, SIGNAL(clicked()), this, SLOT(refreshIndex()));
	m_pBtnRefreshIndex->setToolTip(__tr2qs("Refresh index"));

	m_pIndexListWidget = new KviTalListWidget(m_pIndexTab);
	connect(m_pIndexListWidget, SIGNAL(itemActivated(QListWidgetItem *)), this, SLOT(indexSelected(QListWidgetItem *)));

	m_pSearchTab = new KviTalVBox(m_pTabWidget);
	m_pTabWidget->addTab(m_pSearchTab, __tr2qs("Search"));

	m_pTermsEdit = new QLineEdit(m_pSearchTab);

	connect(m_pTermsEdit, SIGNAL(returnPressed()), this, SLOT(startSearch()));

	m_pResultBox = new KviTalListWidget(m_pSearchTab);
	connect(m_pResultBox, SIGNAL(itemActivated(QListWidgetItem *)), this, SLOT(searchSelected(QListWidgetItem *)));

	QList<int> li;
	li.append(width() - 80);
	li.append(80);
	m_pSplitter->setSizes(li);

	connect(g_pDocIndex, SIGNAL(indexingStart(int)), this, SLOT(indexingStart(int)));
	connect(g_pDocIndex, SIGNAL(indexingProgress(int)), this, SLOT(indexingProgress(int)));
	connect(g_pDocIndex, SIGNAL(indexingEnd()), this, SLOT(indexingEnd()));

	QTimer::singleShot(0, this, SLOT(initialSetup()));
}

HelpWindow::~HelpWindow()
{
	g_pHelpWindowList->removeRef(this);
}

void HelpWindow::initialSetup()
{
	m_pIndexSearch->setFocus();

	QString szDoclist, szDict;

	g_pApp->getLocalKvircDirectory(szDoclist, KviApplication::Help, "help.doclist." KVI_SOURCES_DATE);
	g_pApp->getLocalKvircDirectory(szDict, KviApplication::Help, "help.dict." KVI_SOURCES_DATE);

	if(QFileInfo(szDoclist).exists() && QFileInfo(szDict).exists())
	{
		g_pDocIndex->readDict();
		m_pIndexListWidget->clear();
		QStringList docList = g_pDocIndex->titlesList();
		m_pIndexListWidget->addItems(docList);
		m_pIndexListWidget->sortItems();
		m_pBtnRefreshIndex->setEnabled(true);
	}
	else
		g_pDocIndex->makeIndex();
}

void HelpWindow::indexingStart(int iNum)
{
	m_pBtnRefreshIndex->setEnabled(false);
	m_pBottomLayout->setVisible(true);
	m_pProgressBar->setRange(0, iNum);
	m_pProgressBar->setValue(0);
}

void HelpWindow::indexingProgress(int iNum)
{
	m_pProgressBar->setValue(iNum);
}

void HelpWindow::indexingEnd()
{
	m_pProgressBar->setValue(0);
	m_pBottomLayout->setVisible(false);
	g_pDocIndex->writeDict();
	m_pIndexListWidget->clear();
	QStringList docList = g_pDocIndex->titlesList();
	m_pIndexListWidget->addItems(docList);
	m_pIndexListWidget->sortItems();
	m_pBtnRefreshIndex->setEnabled(true);
}

void HelpWindow::saveProperties(KviConfigurationFile * cfg)
{
	KviWindow::saveProperties(cfg);
	cfg->writeEntry("Splitter", m_pSplitter->sizes());
}

void HelpWindow::loadProperties(KviConfigurationFile * cfg)
{
	QList<int> def;
	int w = width();
	def.append((w * 82) / 100);
	def.append((w * 18) / 100);
	m_pSplitter->setSizes(cfg->readIntListEntry("Splitter", def));
	KviWindow::loadProperties(cfg);
}

void HelpWindow::refreshIndex()
{
	g_pDocIndex->makeIndex();
}

void HelpWindow::startSearch()
{
	QString str = m_pTermsEdit->text();
	str = str.replace("\'", "\"");
	str = str.replace("`", "\"");
	QString buf = str;
	str = str.replace("-", " ");
	str = str.replace(KviRegExp(R"(\s[\S]?\s)"), " ");
	m_terms = str.split(" ", Qt::SkipEmptyParts);
	QStringList termSeq;
	QStringList seqWords;
	QStringList::iterator it = m_terms.begin();
	for(; it != m_terms.end(); ++it)
	{
		(*it) = (*it).simplified();
		(*it) = (*it).toLower();
		(*it) = (*it).replace("\"", "");
	}
	if(str.contains('\"'))
	{
		if((str.count('\"')) % 2 == 0)
		{
			int beg = 0;
			int end = 0;
			QString s;
			beg = str.indexOf('\"', beg);
			while(beg != -1)
			{
				beg++;
				end = str.indexOf('\"', beg);
				s = str.mid(beg, end - beg);
				s = s.toLower();
				s = s.simplified();
				if(s.contains('*'))
				{
					QMessageBox::warning(this, __tr2qs("Full Text Search - KVIrc"),
					    __tr2qs("Using a wildcard within phrases is not allowed."));
					return;
				}
				seqWords += s.split(' ', Qt::SkipEmptyParts);
				termSeq << s;
				beg = str.indexOf('\"', end + 1);
			}
		}
		else
		{
			QMessageBox::warning(this, __tr2qs("Full Text Search - KVIrc"),
			    __tr2qs("The closing quotation mark is missing."));
			return;
		}
	}
	setCursor(Qt::WaitCursor);
	m_foundDocs.clear();
	m_foundDocs = g_pDocIndex->query(m_terms, termSeq, seqWords);

	m_pResultBox->clear();
	for(it = m_foundDocs.begin(); it != m_foundDocs.end(); ++it)
		m_pResultBox->addItem(g_pDocIndex->getDocumentTitle(*it));

	m_terms.clear();
	bool isPhrase = false;
	QString s = "";
	for(const auto & i : buf)
	{
		if(i == '\"')
		{
			isPhrase = !isPhrase;
			s = s.simplified();
			if(!s.isEmpty())
				m_terms << s;
			s = "";
		}
		else if(i == ' ' && !isPhrase)
		{
			s = s.simplified();
			if(!s.isEmpty())
				m_terms << s;
			s = "";
		}
		else
			s += i;
	}
	if(!s.isEmpty())
		m_terms << s;

	setCursor(Qt::ArrowCursor);
}

QTextBrowser * HelpWindow::textBrowser()
{
	return m_pHelpWidget->textBrowser();
}

void HelpWindow::showIndexTopic()
{
	if(m_pIndexSearch->text().isEmpty() || !m_pIndexListWidget->selectedItems().count())
		return;
	int i = g_pDocIndex->titlesList().indexOf(m_pIndexListWidget->selectedItems().at(0)->text());
	textBrowser()->setSource(QUrl(g_pDocIndex->documentList()[i]));
}

void HelpWindow::searchInIndex(const QString & s)
{
	QListWidgetItem * item;
	QString sl = s.toLower();
	for(int i = 0; i < m_pIndexListWidget->count(); i++)
	{
		item = m_pIndexListWidget->item(i);
		QString t = item->text();
		if(t.length() >= sl.length() && item->text().left(s.length()).toLower() == sl)
		{
			m_pIndexListWidget->setCurrentItem(item);
			m_pIndexListWidget->scrollToItem(item, QAbstractItemView::PositionAtTop);
			break;
		}
	}
}

void HelpWindow::indexSelected(QListWidgetItem * item)
{
	if(!item)
		return;
	int i = g_pDocIndex->titlesList().indexOf(item->text());
	textBrowser()->setSource(QUrl(g_pDocIndex->documentList()[i]));
}

void HelpWindow::searchSelected(QListWidgetItem * item)
{
	if(!item)
		return;
	int i = g_pDocIndex->titlesList().indexOf(item->text());
	textBrowser()->setSource(QUrl(g_pDocIndex->documentList()[i]));
}

QPixmap * HelpWindow::myIconPtr()
{
	return g_pIconManager->getSmallIcon(KviIconManager::QuestionMark);
}

void HelpWindow::resizeEvent(QResizeEvent *)
{
	m_pSplitter->setGeometry(0, 0, width(), height());
}

void HelpWindow::fillCaptionBuffers()
{
	m_szPlainTextCaption = __tr2qs("Help Browser");
}