From 2e539044672d5a42b0d9e0bb0dd37d5b83ed4310 Mon Sep 17 00:00:00 2001 From: mjbudd77 Date: Mon, 16 Aug 2021 06:29:57 -0400 Subject: [PATCH] Added code to allow for an external chm viewer to be used for unix OS. --- src/drivers/Qt/ConsoleWindow.cpp | 21 ++-- src/drivers/Qt/ConsoleWindow.h | 11 ++ src/drivers/Qt/HelpPages.cpp | 188 +++++++++++++++++++++++++++++-- src/drivers/Qt/HelpPages.h | 1 - src/drivers/Qt/config.cpp | 6 + 5 files changed, 208 insertions(+), 19 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 424f56c7..149d7532 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -227,6 +227,7 @@ consoleWin_t::consoleWin_t(QWidget *parent) refreshRate = 0.0; updateCounter = 0; recentRomMenuReset = false; + helpWin = 0; // Viewport Cursor Type and Visibility loadCursor(); @@ -1890,22 +1891,24 @@ void consoleWin_t::createMainMenu(void) helpMenu->addAction(msgLogAct); // Help -> Documentation Online - act = new QAction(tr("&Docs (Online)"), this); + subMenu = helpMenu->addMenu( tr("&Documentation") ); + subMenu->setIcon( style()->standardIcon( QStyle::SP_DialogHelpButton ) ); + + // Help -> Documentation Online + act = new QAction(tr("&Online"), this); act->setStatusTip(tr("Documentation")); - act->setIcon( style()->standardIcon( QStyle::SP_DialogHelpButton ) ); + //act->setIcon( style()->standardIcon( QStyle::SP_DialogHelpButton ) ); connect(act, SIGNAL(triggered()), this, SLOT(openOnlineDocs(void)) ); - helpMenu->addAction(act); + subMenu->addAction(act); -#ifdef WIN32 // Help -> Documentation Offline - act = new QAction(tr("&Docs (Offline)"), this); + act = new QAction(tr("&Local"), this); act->setStatusTip(tr("Documentation")); - act->setIcon( style()->standardIcon( QStyle::SP_DialogHelpButton ) ); + //act->setIcon( style()->standardIcon( QStyle::SP_DialogHelpButton ) ); connect(act, SIGNAL(triggered()), this, SLOT(openOfflineDocs(void)) ); - helpMenu->addAction(act); -#endif + subMenu->addAction(act); }; //--------------------------------------------------------------------------- int consoleWin_t::loadVideoDriver( int driverId ) @@ -4172,6 +4175,8 @@ void consoleWin_t::updatePeriodic(void) recWavAct->setEnabled( FCEU_IsValidUI( FCEUI_RECORDMOVIE ) && !FCEUI_WaveRecordRunning() ); recAsWavAct->setEnabled( FCEU_IsValidUI( FCEUI_RECORDMOVIE ) && !FCEUI_WaveRecordRunning() ); stopWavAct->setEnabled( FCEUI_WaveRecordRunning() ); + + helpPageMaint(); } if ( errorMsgValid ) diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index 4a1e361d..accd8a25 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -171,6 +171,9 @@ class consoleWin_t : public QMainWindow void setMenuAccessPauseEnable(bool enable); void setContextMenuEnable(bool enable); void setSoundUseGlobalFocus(bool enable); + + void OpenHelpWindow(std::string subpage = ""); + protected: consoleMenuBar *menubar; @@ -266,6 +269,11 @@ class consoleWin_t : public QMainWindow double refreshRate; unsigned int updateCounter; +#ifdef WIN32 + HWND helpWin; +#else + int helpWin; +#endif protected: void resizeEvent(QResizeEvent *event) override; void closeEvent(QCloseEvent *event) override; @@ -291,6 +299,9 @@ class consoleWin_t : public QMainWindow void loadState(int slot); void transferVideoBuffer(void); void syncAutoFirePatternMenu(void); + void helpPageMaint(void); + + std::string find_chm(void); public slots: void openDebugWindow(void); diff --git a/src/drivers/Qt/HelpPages.cpp b/src/drivers/Qt/HelpPages.cpp index 5b85ff73..730e5e26 100644 --- a/src/drivers/Qt/HelpPages.cpp +++ b/src/drivers/Qt/HelpPages.cpp @@ -1,37 +1,205 @@ +/* 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 +#include +#include +#include #include "driver.h" #include "Qt/HelpPages.h" +#include "Qt/fceuWrapper.h" #include "Qt/ConsoleWindow.h" +#include "Qt/ConsoleUtilities.h" #ifdef WIN32 #include #include +#else // Linux or Unix or APPLE +#include +#include +#include +#endif -void OpenHelpWindow(std::string subpage) +#if defined(__linux__) || defined(__unix__) || defined(__APPLE__) +static int forkHelpFileViewer( const char *chmViewer, const char *filepath ); +#endif + +void consoleWin_t::OpenHelpWindow(std::string subpage) { - HWND helpWin; - std::string helpFileName = FCEUI_GetBaseDirectory(); - helpFileName += "\\..\\doc\\fceux.chm"; + std::string helpFileName; + + g_config->getOption ("SDL.HelpFilePath", &helpFileName ); + + if ( helpFileName.length() == 0 ) + { + std::string helpFileName = FCEUI_GetBaseDirectory(); + helpFileName += "\\..\\doc\\fceux.chm"; + } + + if ( !QFile( QString::fromStdString(helpFileName) ).exists() ) + { + helpFileName = find_chm(); + } + + 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() ); - helpWin = HtmlHelp( HWND(consoleWindow->winId()), helpFileName.c_str(), HH_DISPLAY_TOPIC, (DWORD)NULL); + +#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; + } + std::string helpFileViewer; + g_config->getOption ("SDL.HelpFileViewer", &helpFileViewer ); -void OpenHelpWindow(std::string subpage) -{ - printf("Local CHM Help File Reference is only supported on Windows OS\n"); + helpWin = forkHelpFileViewer( helpFileViewer.c_str(), helpFileName.c_str() ); +#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::find_chm(void) +{ + int ret, useNativeFileDialogVal; + QString filename; + std::string last; + char dir[512]; + QFileDialog dialog(this, tr("Open Help File") ); + QList 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); + + dialog.setNameFilter(tr("Compiled HTML Files (*.chm *.CHM) ;; All files (*)")); + + 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 diff --git a/src/drivers/Qt/HelpPages.h b/src/drivers/Qt/HelpPages.h index b986da0d..531f6750 100644 --- a/src/drivers/Qt/HelpPages.h +++ b/src/drivers/Qt/HelpPages.h @@ -1,3 +1,2 @@ // HelpPages.h -void OpenHelpWindow(std::string subpage = ""); diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp index 90883a91..3b90e81a 100644 --- a/src/drivers/Qt/config.cpp +++ b/src/drivers/Qt/config.cpp @@ -707,6 +707,12 @@ InitConfig() config->addOption("_lastsavestateas", "SDL.LastSaveStateAs", savPath ); config->addOption("_lastopenmovie", "SDL.LastOpenMovie", movPath); config->addOption("_lastloadlua", "SDL.LastLoadLua", ""); + config->addOption("SDL.HelpFilePath", ""); +#ifdef WIN32 + config->addOption("SDL.HelpFileViewer", ""); +#else + config->addOption("SDL.HelpFileViewer", "/usr/bin/xchm"); +#endif for (unsigned int i=0; i<10; i++) {