Modifying GUI to use kchmviewer if available

Discussions related to using the OSE version of VirtualBox.
Post Reply
mYse|f
Posts: 13
Joined: 10. Sep 2015, 01:10
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: Mainly Trisquel GNU/Linux for compilation purposes
Location: Slovakia, Europe
Contact:

Modifying GUI to use kchmviewer if available

Post by mYse|f »

When accessing the documentation, the OSE version opens UserManual.pdf in whatever is the default PDF viewer in the system (e.g. Evince) while the official version opens VirtualBox.chm in an older (GPLv2) version of kchmviewer, that comes bundled in the package. Since my build contains documentation in both PDF and CHM formats (but no kchmviewer), I would like to adapt VirtualBox's code to check whether kchmviewer is installed (e.g. using "which kchmviewer"), and if not, fall back to UserManual.pdf. Currently I have no C++ skills and would be grateful if the developers would show me how to properly do this.

Here's the relevant code snippet from VirtualBox-5.0.6/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp:

Code: Select all

void UIMessageCenter::sltShowHelpHelpDialog()
{
#ifndef VBOX_OSE
    /* For non-OSE version we just open it: */
    sltShowUserManual(vboxGlobal().helpFile());
#else /* #ifndef VBOX_OSE */
    /* For OSE version we have to check if it present first: */
    QString strUserManualFileName1 = vboxGlobal().helpFile();
    QString strShortFileName = QFileInfo(strUserManualFileName1).fileName();
    QString strUserManualFileName2 = QDir(vboxGlobal().homeFolder()).absoluteFilePath(strShortFileName);
    /* Show if user manual already present: */
    if (QFile::exists(strUserManualFileName1))
        sltShowUserManual(strUserManualFileName1);
    else if (QFile::exists(strUserManualFileName2))
        sltShowUserManual(strUserManualFileName2);
    /* If downloader is running already: */
    else if (UIDownloaderUserManual::current())
    {
        /* Just show network access manager: */
        gNetworkManager->show();
    }
    /* Else propose to download user manual: */
    else if (cannotFindUserManual(strUserManualFileName1))
    {
        /* Create User Manual downloader: */
        UIDownloaderUserManual *pDl = UIDownloaderUserManual::create();
        /* After downloading finished => show User Manual: */
        connect(pDl, SIGNAL(sigDownloadFinished(const QString&)), this, SLOT(sltShowUserManual(const QString&)));
        /* Start downloading: */
        pDl->start();
    }
#endif /* #ifdef VBOX_OSE */
}
…
void UIMessageCenter::sltShowUserManual(const QString &strLocation)
{
#if defined (Q_WS_WIN32)
    HtmlHelp(GetDesktopWindow(), strLocation.utf16(), HH_DISPLAY_TOPIC, NULL);
#elif defined (Q_WS_X11)
# ifndef VBOX_OSE
    char szViewerPath[RTPATH_MAX];
    int rc;
    rc = RTPathAppPrivateArch(szViewerPath, sizeof(szViewerPath));
    AssertRC(rc);
    QProcess::startDetached(QString(szViewerPath) + "/kchmviewer", QStringList(strLocation));
# else /* #ifndef VBOX_OSE */
    vboxGlobal().openURL("file://" + strLocation);
# endif /* #ifdef VBOX_OSE */
#elif defined (Q_WS_MAC)
    vboxGlobal().openURL("file://" + strLocation);
#endif
}
…and also VBoxGlobal.cpp:

Code: Select all

QString VBoxGlobal::helpFile() const
{
#if defined (Q_WS_WIN32)
    const QString name = "VirtualBox";
    const QString suffix = "chm";
#elif defined (Q_WS_MAC)
    const QString name = "UserManual";
    const QString suffix = "pdf";
#elif defined (Q_WS_X11)
# if defined VBOX_OSE
    const QString name = "UserManual";
    const QString suffix = "pdf";
# else
    const QString name = "VirtualBox";
    const QString suffix = "chm";
# endif
#endif
    /* Where are the docs located? */
    char szDocsPath[RTPATH_MAX];
    int rc = RTPathAppDocs (szDocsPath, sizeof (szDocsPath));
    AssertRC (rc);
    /* Make sure that the language is in two letter code.
     * Note: if languageId() returns an empty string lang.name() will
     * return "C" which is an valid language code. */
    QLocale lang (VBoxGlobal::languageId());

    /* Construct the path and the filename */
    QString manual = QString ("%1/%2_%3.%4").arg (szDocsPath)
                                            .arg (name)
                                            .arg (lang.name())
                                            .arg (suffix);
    /* Check if a help file with that name exists */
    QFileInfo fi (manual);
    if (fi.exists())
        return manual;

    /* Fall back to the standard */
    manual = QString ("%1/%2.%4").arg (szDocsPath)
                                 .arg (name)
                                 .arg (suffix);
    return manual;
}
Thank you in advance.

EDIT: I added the missing piece of code that I previously overlooked.
EDIT 2: Also added code from VBoxGlobal.cpp that defines the filename. I guess this is the part that I have to change.
Last edited by mYse|f on 17. Oct 2015, 18:12, edited 2 times in total.
mYse|f
Posts: 13
Joined: 10. Sep 2015, 01:10
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: Mainly Trisquel GNU/Linux for compilation purposes
Location: Slovakia, Europe
Contact:

Re: Modifying GUI to use kchmviewer if available

Post by mYse|f »

I've tried to replace the line
# ifndef VBOX_OSE
with
# if (system("which kchmviewer") != 0)
as pointed out here, but I'm getting the following error message (screenshot):

Code: Select all

/media/trisquel/NewVirtualDisk1/VirtualBox-5.0.6/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp:2678:13: error: missing binary operator before token "("
 # if (system("which kchmviewer") != 0)
             ^
kmk: *** [/media/trisquel/NewVirtualDisk1/VirtualBox-5.0.6/out/debian/builddir/obj/VirtualBox/src/globals/UIMessageCenter.o] Error 1
Can anyone help me out?
Perryg
Site Moderator
Posts: 34369
Joined: 6. Sep 2008, 22:55
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: *NIX

Re: Modifying GUI to use kchmviewer if available

Post by Perryg »

OSE builds typically disable the build of the kchmviewer. Add the following to your LocalConfig.kmk

Code: Select all

VBOX_WITH_KCHMVIEWER = 1
Also when I built with the viewer enabled I needed to have wine installed to do so. There is the real problem. Newer versions of wine don't work. It had to be a really old one that you just can not find any more.
mYse|f
Posts: 13
Joined: 10. Sep 2015, 01:10
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: Mainly Trisquel GNU/Linux for compilation purposes
Location: Slovakia, Europe
Contact:

Re: Modifying GUI to use kchmviewer if available

Post by mYse|f »

Thanks, but this isn't what I'm trying to do. I'm not trying to include kchmviewer in the package, instead, I want VirtualBox to make use of it if it's available in the system. Also, I'm building the documentation separately before VirtualBox using a different CHM compiler so the Wine issue doesn't affect me.
Perryg
Site Moderator
Posts: 34369
Joined: 6. Sep 2008, 22:55
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: *NIX

Re: Modifying GUI to use kchmviewer if available

Post by Perryg »

Very well. Do let us know how it turns out.
mYse|f
Posts: 13
Joined: 10. Sep 2015, 01:10
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: Mainly Trisquel GNU/Linux for compilation purposes
Location: Slovakia, Europe
Contact:

Re: Modifying GUI to use kchmviewer if available

Post by mYse|f »

I will since I'm asking here :). Just out of curiosity, how did you managed to build kchmviewer along with VirtualBox when the sources are not included in the tarball?
mYse|f
Posts: 13
Joined: 10. Sep 2015, 01:10
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: Mainly Trisquel GNU/Linux for compilation purposes
Location: Slovakia, Europe
Contact:

Re: Modifying GUI to use kchmviewer if available

Post by mYse|f »

I updated my initial post to reflect my findings. I also tried to ask for help on the #vbox and #vbox-dev IRC channels respectively, but haven't received any.

According to the explanation on Stack Overflow, the problem I'm encountering is a preprocessor error which "occur when the preprocessor encounters invalid syntax while trying to evaluate an expression in a #if or #endif directive." I guess this means that I cannot place system calls after #if. But then how am I supposed to do this? :?
mYse|f
Posts: 13
Joined: 10. Sep 2015, 01:10
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: Mainly Trisquel GNU/Linux for compilation purposes
Location: Slovakia, Europe
Contact:

Re: Modifying GUI to use kchmviewer if available

Post by mYse|f »

I have solved the preprocessor problem by removing the hashtags from the directives and adding brackets:

Code: Select all

if (system("which kchmviewer") != 0)
{
    const QString name = "UserManual";
    const QString suffix = "pdf";
}
else
{
    const QString name = "VirtualBox";
    const QString suffix = "chm";
}
However, the compiler now complains that the specific constants haven't been declared (screenshot):

Code: Select all

/media/trisquel/NewVirtualDisk1/VirtualBox-5.0.6/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp: In member function ‘QString VBoxGlobal::helpFile() const’:
/media/trisquel/NewVirtualDisk1/VirtualBox-5.0.6/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp:2491:51: error: ‘name’ was not declared in this scope
                                             .arg (name)
                                                   ^
/media/trisquel/NewVirtualDisk1/VirtualBox-5.0.6/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp:2493:51: error: ‘suffix’ was not declared in this scope
                                             .arg (suffix);
                                                   ^
kmk: *** [/media/trisquel/NewVirtualDisk1/VirtualBox-5.0.6/out/debian/builddir/obj/VirtualBox/src/globals/VBoxGlobal.o] Error 1
Guess I'm giving up.
mYse|f
Posts: 13
Joined: 10. Sep 2015, 01:10
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: Mainly Trisquel GNU/Linux for compilation purposes
Location: Slovakia, Europe
Contact:

Re: Modifying GUI to use kchmviewer if available

Post by mYse|f »

UPDATE: http://stackoverflow.com/questions/3322 ... -available.

Any help on solving this problem is welcome.
Post Reply