PDA

View Full Version : QTextBrowser setSearchPaths doesn't work



poporacer
31st March 2012, 07:28
I am trying to set up a user manual and followed the method in C++ Gui Programming with Qt. It worked exactly as planned on Qt Creator version 2.0 using Qt 4.7. I then transferred the code to Creator Version 2.4.1 using Qt 4.7.4 and it didn't work. At first the browser window would not load anything. I modified the code and now the manual shows, but it does not show the pictures. Here is what I have:
Original code

DlgHelpBrowser::DlgHelpBrowser(const QString &path, const QString &page,
QWidget *parent) :
QDialog(parent),
ui(new Ui::DlgHelpBrowser)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setAttribute(Qt::WA_GroupLeader);

connect (ui->btnHome, SIGNAL(clicked()),
ui->textBrowser, SLOT (home()));
connect (ui->btnBack, SIGNAL(clicked()),
ui->textBrowser, SLOT (backward()));
connect (ui->btnClose, SIGNAL(clicked()),
this, SLOT (close()));
ui->textBrowser->setSearchPaths(QStringList() << path <<"/graphics");
ui->textBrowser->setSource(page);
}

void DlgHelpBrowser::showPage(const QString &page)
{
QString path= directoryOf("manual").absolutePath();
DlgHelpBrowser *browser = new DlgHelpBrowser ( path, page);
browser->resize(1000, 800);
browser->show();
}

QDir DlgHelpBrowser::directoryOf(const QString &subdir)
{
QDir dir(QApplication::applicationDirPath());
if (dir.dirName().toLower()== "debug" || dir.dirName().toLower()=="release")
dir.cdUp();

dir.cd(subdir);
return dir;
}
The code to run on Creator 2.4.1

DlgHelpBrowser::DlgHelpBrowser(const QString &path, const QString &page,
QWidget *parent) :
QDialog(parent),
ui(new Ui::DlgHelpBrowser)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setAttribute(Qt::WA_GroupLeader);

connect (ui->btnHome, SIGNAL(clicked()),
ui->textBrowser, SLOT (home()));
connect (ui->btnBack, SIGNAL(clicked()),
ui->textBrowser, SLOT (backward()));
connect (ui->btnClose, SIGNAL(clicked()),
this, SLOT (close()));
QUrl loadPage =QUrl::fromLocalFile(page);//New line here
ui->textBrowser->setSearchPaths(QStringList() << path <<"/graphics"); //I also tried path + "/graphics"
ui->textBrowser->setSource(loadPage);
ui->textBrowser->zoomIn(2);
}

This shows the HTML file but the pictures are not there, just a picture icon. Any ideas?

ChrisW67
1st April 2012, 00:32
Did you really need another thread for the same problem?

Does a path "/graphics" exist on your machine? Which drive would that be on Windows machines? This is not a path relative to the current working directory or relative to any other path in the search path.

poporacer
1st April 2012, 05:28
Sorry for posting again. The problem is a little different from the original one. I got the html file to show, now I keed the images to show. I haven't gotten a response in over a week. I do have a /graphics folder it is in the manual folder.How do I give it a path relative to the working directory? I tried path+"/graphics" and it didn't work. My file structure is "workingDirectory"/manual/graphics. The html code is in the manual folder and the images for the html is in the graphics folder. What am I missing?

ChrisW67
1st April 2012, 09:58
You are missing correct paths either in your search path or in the actual HTML of your pages.

If your HTML page in the manual directory refers to:

<img src="graphics/diagram.png" />
the diagram.png exists in the graphics folder, and the HTML is loading then it should just work.

poporacer
1st April 2012, 17:00
The code for the HTML files is

<img style="width: 682px; height: 364px;" src="graphics/mainMenu.jpg">
I tried adding the trailing foward slash like you had but it still didn't work. And I have tried several variations of setting the search paths, and none of them worked. I even tried hardcoding the path and it didn't work. If I move the graphics folder to the current working folder, it all works. For some reason I cannot get the setSearchPaths to work correctly. And everything worked perfectly with Qt 4.7 but not 4.7.4?? Any ideas where I am going wrong?

The code for the HTML files is

<img style="width: 682px; height: 364px;" src="graphics/mainMenu.jpg">
I tried adding the trailing foward slash like you had but it still didn't work. And I have tried several variations of setting the search paths, and none of them worked. I even tried hardcoding the path and it didn't work. If I move the graphics folder to the current working folder, it all works. For some reason I cannot get the setSearchPaths to work correctly. And everything worked perfectly with Qt 4.7 but not 4.7.4?? Any ideas where I am going wrong?

Added after 35 minutes:

Here is an example:
7551

ChrisW67
2nd April 2012, 05:18
Your code as posted works just fine here on Linux/Qt 4.7.4/GCC, Windows XP/Qt 4.7.4/MingW, and Windows XP/Qt 4.8.0/MingW. It even works without the erroneous "/graphics" folder in the search path. Does it fail when the image is a PNG? Do you have the Qt JPEG plugin?

poporacer
3rd April 2012, 06:55
I tried with a .png file and same thing. I am running Windows 7, 64 bit, Qt 4.8 (32 bit), mingw. (If I go to about Qt, it says based on Qt 4.7.4, but in my project setting it says version 4.8.0) I have the qjpeg4.dll in my release version in a folder imageformats. Any ideas why it won't work on my machine? Maybe a Windows 7 bug?

ChrisW67
3rd April 2012, 08:22
This is curious. I just grabbed the source again, built it on the same machine with the intention of running it on Win 7 64, and it does not behave even on the XP machine. It's possible that yesterday I was accidentally getting 4.7.3 libraries.

Seems to be a known issue:
https://bugreports.qt-project.org/browse/QTBUG-24077
The comments on this commit (http://qt.gitorious.org/qt/qt/commit/5f161591b6ae25524b129bf4a41d6438f0a4d402) imply that this occurred to fix a security bug in QUrl.

I can confirm that n absolute file path works but is impractical. I can also confirm that:


<img style="width: 1280px; height: 703px;" alt="" src="file:graphics/test.jpg">

also worked and preserves the relative path.

poporacer
4th April 2012, 04:23
Thanks,
I searched the bug reports but I guess I missed that. I really appreciate the time you spent to help me. I was going crazy when things worked fine with the older libraries. I think I will install the older libraries and use them.

Thanks a million!

ChrisW67
4th April 2012, 04:55
Or just adjust the local URLs in your HTML and future proof them: "graphics/test.jpg" ==> "file:graphics/test.jpg"

poporacer
4th April 2012, 04:57
One other problem I have with the QTextBrowser. It looks like you can't load an html file to an anchor. I have the manual open to the relative anchor point to the part of the manual where they are in the program.
I call this with:

DlgHelpBrowser::showPage("UserManual.html#6.3")

I will search to see if there is a fix to this.

ChrisW67
4th April 2012, 06:34
That's correct behaviour. You are passing a bare string to a function expecting a QUrl, which results in the string being treated literally as a file name by the conversion constructor (because there's no URI scheme). Use QUrl:


QUrl url("file:UserManual.html#anchor");
ui->textBrowser(url);

// or perhaps
QString fileName = "UserManual.html";
...
QUrl url = QUrl::fromLocalFile(fileName);
url.setEncodedFragment("anchor");
ui->textBrowser(url);

poporacer
5th April 2012, 05:22
I haven't had a chance to check your second suggestion, but I think I am following your first suggestion already. Here is the relevant code:

DlgHelpBrowser::showPage("UserManual.html#6.3")//passes anchor

void DlgHelpBrowser::showPage(const QString &page)
{
QString path= directoryOf("manual").absolutePath();
DlgHelpBrowser *browser = new DlgHelpBrowser ( path, page);//creates new QTextbrowser
browser->resize(1000, 800);
browser->show();
}

DlgHelpBrowser::DlgHelpBrowser(const QString &path, const QString &page,
QWidget *parent) :
QDialog(parent),
ui(new Ui::DlgHelpBrowser)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setAttribute(Qt::WA_GroupLeader);

connect (ui->btnHome, SIGNAL(clicked()),
ui->textBrowser, SLOT (home()));
connect (ui->btnBack, SIGNAL(clicked()),
ui->textBrowser, SLOT (backward()));
connect (ui->btnClose, SIGNAL(clicked()),
this, SLOT (close()));
QUrl loadPage =QUrl::fromLocalFile(page);//here page is converted to QUrl...shouldn't this work?
ui->textBrowser->setSearchPaths(QStringList() << path);
ui->textBrowser->setSource(loadPage);// I will try ui->textBrowser(loadPage) and see if it works

}
Am I doing this correctly? It is strange that in 4.7 you didn't need to convert to QUrl, it handled QStrings
I will try your second method as well and see if it works.
Again, many thanks for all your help!

ChrisW67
5th April 2012, 05:42
At line 16 of your last listing you are telling QUrl that path is a local file name, i.e. there exists a file literally called "UserManual.html#6.3". QUrl will encode the '#' so that it is not interpreted as the fragment separator.

Contrast these:


QUrl url1 = QUrl::fromLocalFile("UserManual.html#6.3");
qDebug() << url1.path() << url1.fragment() << url1.toEncoded();
// "UserManual.html#6.3" "" "file:UserManual.html%236.3"

QUrl url2("UserManual.html#6.3");
qDebug() << url2.path() << url2.fragment() << url2.toEncoded();
// "UserManual.html" "6.3" "UserManual.html#6.3"

poporacer
6th April 2012, 06:19
I see what you are saying but I can't get it to work. I tried several things but I can't figure out which function to pass the path and fragment to QTextBrowser.

ChrisW67
6th April 2012, 10:34
You use QTextBrowser::setSource() but you pass it a correctly constructed QUrl. I have already given you several ways to construct a QUrl from the file path and anchor (fragment).

poporacer
7th April 2012, 17:19
It took me a while to figure it out and here is what I did to get it to work. Originally I was testing to see what part of the program the user was at and then pass the relevant file name (for example: UserManual.html#sec1)to the showPage function. I had problems with the showPage function because of the constraints of the requirement to use QUrl::fromLocalFile to show the html file properly. I couldn't figure out how to get the path and fragment AND use the QUrl::fromLocalFile. Because I am always using the same file to open (UserManual.html), I hard coded the file name and then in the the test function I passed only the fragment. If I need to have a dynamic document and fragment, I think I will pass the document name and fragment as seperate items to the function. I am not sure if this is the best method, but in case someone else runs across the same problem here is the code I used:


//test function
void MainWindow::on_btnHelp_clicked()
{
switch (ui->MainStackWidget->currentIndex())//what stacked widget the user is looking at
{
case 0:
DlgHelpBrowser::showPage("");//no fragment
break;
case 1:
DlgHelpBrowser::showPage("sec1");
break;
case 2:
DlgHelpBrowser::showPage("sec2");
break;
case 3:
DlgHelpBrowser::showPage("sec3");
break;
}

//part of showPage function
QUrl loadPage =QUrl::fromLocalFile("UserManual.html");
loadPage.setFragment(page);//fragment passed from test function
ui->textBrowser->setSearchPaths(QStringList() << path);//path is generated from QApplication::applicationDirPath()
ui->textBrowser->setSource(loadPage);
If there is a better way, let me know. ChrisW67, Thanks for all your help!!!