fceux/src/drivers/Qt/HelpPages.cpp

395 lines
11 KiB
C++

/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2020 mjbudd77
*
* 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
*/
// HelpPages.cpp
#include <string>
#include <QFile>
#include <QFileDialog>
#include <QStandardPaths>
#include <QMenuBar>
#include <QToolBar>
#include <QMenu>
#include <QAction>
#include <QSettings>
#include <QHelpEngine>
#include <QHelpIndexModel>
#include <QHelpContentWidget>
#include "driver.h"
#include "Qt/HelpPages.h"
#include "Qt/fceuWrapper.h"
#include "Qt/ConsoleWindow.h"
#include "Qt/ConsoleUtilities.h"
#ifdef WIN32
#include <Windows.h>
#include <htmlhelp.h>
//#else // Linux or Unix or APPLE
//#include <unistd.h>
//#include <sys/types.h>
//#include <sys/wait.h>
#endif
//#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
//static int forkHelpFileViewer( const char *chmViewer, const char *filepath );
//#endif
void consoleWin_t::OpenHelpWindow(std::string subpage)
{
std::string helpFileName;
g_config->getOption ("SDL.HelpFilePath", &helpFileName );
if ( helpFileName.length() == 0 )
{
#ifdef WIN32
helpFileName = FCEUI_GetBaseDirectory();
helpFileName += "\\..\\doc\\fceux.chm";
#else
helpFileName = "/usr/share/fceux/fceux.qhc";
#endif
#ifdef __APPLE__
if ( !QFile( QString::fromStdString(helpFileName) ).exists() )
{
// Search for MacOSX DragNDrop Resources
helpFileName = QApplication::applicationDirPath().toStdString() + "/../Resources/fceux.qhc";
}
#endif
}
if ( !QFile( QString::fromStdString(helpFileName) ).exists() )
{
helpFileName = findHelpFile();
}
if ( helpFileName.length() == 0 )
{
return;
}
#ifdef WIN32
if (subpage.length() > 0)
{
helpFileName = helpFileName + "::/" + subpage + ".htm";
}
#else
// Subpage indexing is not supported by linux chm viewer
#endif
//printf("Looking for HelpFile '%s'\n", helpFileName.c_str() );
#ifdef WIN32
// Windows specific HtmlHelp library function
helpWin = HtmlHelp( HWND(winId()), helpFileName.c_str(), HH_DISPLAY_TOPIC, (DWORD)NULL);
if ( helpWin == NULL )
{
printf("Error: Failed to open help file '%s'\n", helpFileName.c_str() );
}
#else
if ( helpWin > 0 )
{
printf("There is already a CHM Viewer open somewhere...\n");
return;
}
//helpWin = forkHelpFileViewer( helpFileViewer.c_str(), helpFileName.c_str() );
HelpDialog *win = new HelpDialog( helpFileName.c_str(), this);
win->show();
#endif
}
//void consoleWin_t::helpPageMaint(void)
//{
//#ifdef WIN32
// // Does any help page cleanup need to be done in windows?
//#else
// if ( helpWin > 0 )
// { // Calling waitpid is important to ensure that CHM viewer process is cleaned up
// // in the event that it exits. Otherwise zombie processes will be left.
// int pid, wstat=0;
//
// pid = waitpid( -1, &wstat, WNOHANG );
//
// if ( pid == helpWin )
// {
// //printf("Help CHM Viewer Closed\n");
// helpWin = 0;
// }
// }
//
//#endif
//}
std::string consoleWin_t::findHelpFile(void)
{
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
char dir[512];
QFileDialog dialog(this, tr("Open Help File") );
QList<QUrl> urls;
//QDir d;
urls << QUrl::fromLocalFile( QDir::rootPath() );
urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first());
urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DownloadLocation).first());
urls << QUrl::fromLocalFile( QDir( FCEUI_GetBaseDirectory() ).absolutePath() );
dialog.setFileMode(QFileDialog::ExistingFile);
#ifdef WIN32
dialog.setNameFilter(tr("Compiled HTML Files (*.chm *.CHM) ;; All files (*)"));
#else
dialog.setNameFilter(tr("QHelp Files (*.qhc *.QHC) ;; All files (*)"));
#endif
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::AllDirs | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Open") );
g_config->getOption ("SDL.HelpFilePath", &last );
if ( last.size() > 0 )
{
getDirFromFile( last.c_str(), dir );
dialog.setDirectory( tr(dir) );
}
else
{
dialog.setDirectory( QDir( FCEUI_GetBaseDirectory() ).absolutePath() );
}
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.setSidebarUrls(urls);
ret = dialog.exec();
if ( ret )
{
QStringList fileList;
fileList = dialog.selectedFiles();
if ( fileList.size() > 0 )
{
filename = fileList[0];
}
}
if ( filename.isNull() )
{
return last;
}
//qDebug() << "selected file path : " << filename.toUtf8();
g_config->setOption ("SDL.HelpFilePath", filename.toStdString().c_str() );
return filename.toStdString();
}
//#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
//static int forkHelpFileViewer( const char *chmViewer, const char *filepath )
//{
// int pid = 0;
//
// if ( chmViewer[0] == 0 )
// {
// return -1;
// }
//
// pid = fork();
//
// if ( pid == 0 )
// { // Child process
// execl( chmViewer, chmViewer, filepath, NULL );
// exit(0);
// }
// return pid;
//}
//#endif
//-----------------------------------------------------------------------------------------------
//--- Help Page Dialog
//-----------------------------------------------------------------------------------------------
HelpDialog::HelpDialog( const char *helpFileName, QWidget *parent)
: QDialog(parent, Qt::Window)
{
int useNativeMenuBar;
QMenu *fileMenu;
QMenuBar *menuBar;
QToolBar *toolBar;
QAction *act;
QVBoxLayout *mainLayoutv;
QSettings settings;
mainLayoutv = new QVBoxLayout();
setLayout( mainLayoutv );
toolBar = new QToolBar(this);
menuBar = new QMenuBar(this);
mainLayoutv->setMenuBar( menuBar );
// This is needed for menu bar to show up on MacOS
g_config->getOption( "SDL.UseNativeMenuBar", &useNativeMenuBar );
menuBar->setNativeMenuBar( useNativeMenuBar ? true : false );
helpEngine = new QHelpEngine( helpFileName, this );
helpEngine->setupData();
hsplitter = new QSplitter( Qt::Horizontal );
tabWgt = new QTabWidget();
textViewer = new HelpBrowser( helpEngine );
textViewer->setSource(
QUrl("qthelp://TasVideos.fceux/doc/help/fceux.html"));
//-----------------------------------------------------------------------
// Menu Start
//-----------------------------------------------------------------------
// File
fileMenu = menuBar->addMenu(tr("&File"));
// File -> Close
act = new QAction(tr("&Close"), this);
act->setShortcut(QKeySequence::Close);
act->setStatusTip(tr("Close Window"));
connect(act, SIGNAL(triggered()), this, SLOT(closeWindow(void)) );
fileMenu->addAction(act);
//-----------------------------------------------------------------------
// Menu End
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// Tool Bar Setup Start
//-----------------------------------------------------------------------
backButton = act = new QAction(tr("&Backward"), this);
//act->setShortcut( QKeySequence(tr("Ctrl+A") ));
act->setToolTip(tr("Navigate Backward"));
act->setIcon( style()->standardIcon(QStyle::SP_ArrowBack) );
connect(act, SIGNAL(triggered(void)), textViewer, SLOT(backward(void)) );
toolBar->addAction(act);
forwardButton = act = new QAction(tr("&Forward"), this);
//act->setShortcut( QKeySequence(tr("Ctrl+A") ));
act->setToolTip(tr("Navigate Forward"));
act->setIcon( style()->standardIcon(QStyle::SP_ArrowForward) );
connect(act, SIGNAL(triggered(void)), textViewer, SLOT(forward(void)) );
toolBar->addAction(act);
//-----------------------------------------------------------------------
// Tool Bar Setup End
//-----------------------------------------------------------------------
backButton->setEnabled(false);
forwardButton->setEnabled(false);
tabWgt->addTab( helpEngine->contentWidget(), tr("Contents") );
tabWgt->addTab( helpEngine->indexWidget() , tr("Index") );
hsplitter->addWidget( tabWgt );
hsplitter->addWidget( textViewer );
mainLayoutv->addWidget( toolBar );
mainLayoutv->addWidget( hsplitter );
connect(helpEngine->contentWidget(),
SIGNAL(linkActivated(QUrl)),
textViewer, SLOT(setSource(QUrl)));
connect(helpEngine->indexWidget(),
SIGNAL(linkActivated(QUrl, QString)),
textViewer, SLOT(setSource(QUrl)));
connect( textViewer, SIGNAL(backwardAvailable(bool)), this, SLOT(navBackwardAvailable(bool)) );
connect( textViewer, SIGNAL(forwardAvailable(bool)) , this, SLOT(navForwardAvailable(bool)) );
// Restore Window Geometry
restoreGeometry(settings.value("HelpPage/geometry").toByteArray());
// Restore Horizontal Panel State
hsplitter->restoreState( settings.value("HelpPage/hPanelState").toByteArray() );
}
//-----------------------------------------------------------------------------------------------
HelpDialog::~HelpDialog(void)
{
QSettings settings;
// Save Horizontal Panel State
settings.setValue("HelpPage/hPanelState", hsplitter->saveState());
// Save Window Geometry
settings.setValue("HelpPage/geometry", saveGeometry());
}
//-----------------------------------------------------------------------------------------------
void HelpDialog::closeEvent(QCloseEvent *event)
{
//printf("Help Dialog Close Window Event\n");
done(0);
deleteLater();
event->accept();
}
//-----------------------------------------------------------------------------------------------
void HelpDialog::closeWindow(void)
{
//printf("Close Window\n");
done(0);
deleteLater();
}
//-----------------------------------------------------------------------------------------------
void HelpDialog::navBackwardAvailable(bool avail)
{
backButton->setEnabled( avail );
}
//-----------------------------------------------------------------------------------------------
void HelpDialog::navForwardAvailable(bool avail)
{
forwardButton->setEnabled( avail );
}
//-----------------------------------------------------------------------------------------------
//---- Help Browser Class
//-----------------------------------------------------------------------------------------------
HelpBrowser::HelpBrowser(QHelpEngine* helpEngine,
QWidget* parent):QTextBrowser(parent),
helpEngine(helpEngine)
{
}
//-----------------------------------------------------------------------------------------------
QVariant HelpBrowser::loadResource(int type, const QUrl &name)
{
if (name.scheme() == "qthelp")
return QVariant(helpEngine->fileData(name));
else
return QTextBrowser::loadResource(type, name);
}
//-----------------------------------------------------------------------------------------------