//=============================================================================
//
// File : libkvihelp.cpp
// Creation date : Sun Aug 13 2000 03:00:00 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 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 "HelpWidget.h"
#include "HelpWindow.h"
#include "HelpIndex.h"
#include "KviLocale.h"
#include "KviModule.h"
#include "KviFileUtils.h"
#include "KviRegExp.h"
#include "kvi_sourcesdate.h"
#include "KviApplication.h"
#include "KviMainWindow.h"
#include <QDir>
#include <QFileInfo>
#include <QSplitter>
HelpIndex * g_pDocIndex = nullptr;
KviPointerList<HelpWidget> * g_pHelpWidgetList = nullptr;
KviPointerList<HelpWindow> * g_pHelpWindowList = nullptr;
/*
@doc: help.open
@type:
command
@title:
help.open
@short:
Shows a help document
@syntax:
help.open [-n] [-m] [document: string]
@description:
Finds the first available help browser in the current frame
then opens the specified [document].
If no [document] is specified it the documentation index is shown.
If no help browser is available, a new one is created.
[document] can be an absolute path or a relative one: in this case
the document is searched in the KVIrc documentation directory.[br]
If no document has been found using absolute and relative paths,
the first document matching [document] in the help search database
is shown. Otherwise, an error page is displayed.
The help browser has limited HTML browsing capabilities: you can
use it to view simple HTML files on your filesystem.[br]
This command is exported by the "help" module.
@switches:
!sw: -m | --mdi
The created browser is a MDI window,
otherwise it is a static window.
!sw: -n | --new
The window creation is forced even
if there are other help browsers already open.[br]
@examples:
[example]
help.open /home/pragma/myfile.html //absolute path
help.open cmd_snd.play.html //relative path
help.open "Binding operator" //keyword search, remember quoting
help.open OnNickServAuth //keyword search for an event
help.open \$my.user //keyword search, $ needs to be escaped
[/example]
*/
static bool help_kvs_cmd_open(KviKvsModuleCommandCall * c)
{
QString szDoc, szHelpDir, szParam;
QDir dirHelp;
KVSM_PARAMETERS_BEGIN(c)
KVSM_PARAMETER("document", KVS_PT_STRING, KVS_PF_OPTIONAL | KVS_PF_APPENDREMAINING, szParam)
KVSM_PARAMETERS_END(c)
// no document => index
if(szParam.isEmpty())
{
szParam = QString("index.html");
qDebug("No file, use default at path %s", szParam.toUtf8().data());
}
/*
* Path checking order:
* 1) absolute path
* 2) local help (in user directory)
* 3) global help (in kvirc directory)
*/
// try absolute path
QFileInfo f(szParam);
if(!f.exists() || !f.isAbsolute())
{
// try relative path (to local help)
g_pApp->getLocalKvircDirectory(szHelpDir, KviApplication::Help);
dirHelp = QDir(szHelpDir);
szDoc = dirHelp.absoluteFilePath(szParam);
qDebug("No abs path, trying local relative path: %s", szDoc.toUtf8().data());
f.setFile(szDoc);
if(!f.exists())
{
//try relative path (to global help)
g_pApp->getGlobalKvircDirectory(szHelpDir, KviApplication::Help);
dirHelp = QDir(szHelpDir);
szDoc = dirHelp.absoluteFilePath(szParam);
qDebug("No local relative, trying global relative path: %s", szDoc.toUtf8().data());
f.setFile(szDoc);
}
}
// Search in help
if(!f.exists())
{
qDebug("No path, trying search..");
if(g_pDocIndex)
{
if(!g_pDocIndex->documentList().count())
{
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(KviFileUtils::fileExists(szDoclist) && KviFileUtils::fileExists(szDict))
{
g_pDocIndex->readDict();
}
else
{
g_pDocIndex->makeIndex();
g_pDocIndex->writeDict();
}
}
int i = g_pDocIndex->titlesList().indexOf((QRegularExpression) KviRegExp(KviRegExp::escape(szParam), KviRegExp::CaseInsensitive));
if(i != -1)
{
szDoc = QUrl(g_pDocIndex->documentList()[i]).toLocalFile();
f.setFile(szDoc);
}
else
{
QString szTmpDocName(".*/doc_");
szTmpDocName.append(KviRegExp::escape(szParam));
szTmpDocName.append("\\.html");
i = g_pDocIndex->documentList().indexOf((QRegularExpression) KviRegExp(szTmpDocName, KviRegExp::CaseInsensitive));
if(i != -1)
{
szDoc = QUrl(g_pDocIndex->documentList()[i]).toLocalFile();
f.setFile(szDoc);
}
}
}
}
// Everything failed => error
if(!f.exists())
{
szDoc = dirHelp.absoluteFilePath("nohelpavailable.html");
qDebug("Document not found, defaulting to error page: %s", szDoc.toUtf8().data());
f.setFile(szDoc);
}
if(!c->switches()->find('n', "new"))
{
HelpWidget * w = (HelpWidget *)g_pMainWindow->findChild<HelpWidget *>("help_widget");
if(w)
{
w->textBrowser()->setSource(QUrl::fromLocalFile(f.absoluteFilePath()));
HelpWindow * pHelpWindow = g_pHelpWindowList->first();
if (pHelpWindow)
pHelpWindow->delayedAutoRaise();
return true;
}
}
if(c->switches()->find('m', "mdi"))
{
HelpWindow * w = new HelpWindow("Help browser");
w->textBrowser()->setSource(QUrl::fromLocalFile(f.absoluteFilePath()));
g_pMainWindow->addWindow(w);
}
else
{
HelpWidget * w = new HelpWidget(g_pMainWindow->splitter(), true);
w->textBrowser()->setSource(QUrl::fromLocalFile(f.absoluteFilePath()));
w->show();
}
return true;
}
static bool help_module_init(KviModule * m)
{
QString szHelpDir, szDocList;
g_pApp->getLocalKvircDirectory(szDocList, KviApplication::Help, "help.doclist." KVI_SOURCES_DATE);
g_pApp->getGlobalKvircDirectory(szHelpDir, KviApplication::Help);
g_pDocIndex = new HelpIndex(szHelpDir, szDocList);
g_pDocIndex->setDocListFile(szDocList);
g_pApp->getLocalKvircDirectory(szHelpDir, KviApplication::Help, "help.dict." KVI_SOURCES_DATE);
g_pDocIndex->setDictionaryFile(szHelpDir);
g_pHelpWidgetList = new KviPointerList<HelpWidget>;
g_pHelpWidgetList->setAutoDelete(false);
g_pHelpWindowList = new KviPointerList<HelpWindow>;
g_pHelpWindowList->setAutoDelete(false);
KVSM_REGISTER_SIMPLE_COMMAND(m, "open", help_kvs_cmd_open);
return true;
}
static bool help_module_cleanup(KviModule *)
{
if(g_pDocIndex)
delete g_pDocIndex;
while(g_pHelpWidgetList->first())
delete g_pHelpWidgetList->first();
delete g_pHelpWidgetList;
g_pHelpWidgetList = nullptr;
while(g_pHelpWindowList->first())
g_pHelpWindowList->first()->close();
delete g_pHelpWindowList;
g_pHelpWindowList = nullptr;
return true;
}
static bool help_module_can_unload(KviModule *)
{
return (g_pHelpWidgetList->isEmpty() && g_pHelpWindowList->isEmpty());
}
KVIRC_MODULE(
"Help", // module name
"4.0.0", // module version
"Copyright (C) 2000 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
"Help browser extension",
help_module_init,
help_module_can_unload,
0,
help_module_cleanup,
0)