PDA

View Full Version : (1) Sub- and superscripts Windows & (2) deploying programs



julietbravo
10th August 2011, 20:31
Over the last year we have been working on a user interface for a simple meteorological model, to be used in some courses here at the Wageningen University. One of our wishes was to create a cross-platform program but although we have succeeded in this, there are still a few open problems:

1) Sub- and superscripts, mainly on Windows (XP/7):
In the interface we are using a lot of sub- and superscripts (and special characters), both in simple QLabels as in a QTreeWidget (see image below). Initially we used Unicode symbols which worked well in our development environment (both Linux and OS X), but unfortunately a lot of unicode symbols seem to be missing on Windows (e.g. a superscript minus). For the QLabels we were able to bypass this problem by formatting the labels in html (the ugly solution?), unfortunately in the QTreeWidget this is a bit difficult. We 'solved' this by using a normal minus instead of a superscript minus, but this is off course an ugly and temporary fix.
Does anyone know a good method to work with special characters in Qt, suitable for using in QLabels, QTreeWidgets, etc on OS X, Linux and Windows?

2) Deploying programs for Windows:
To create a stand-alone package for distribution I statically compiled QtCreator as described in many online tutorials. This is working, I only have to attach a few .dll files and thats it. However it took me quite some time to statically compile QtCreator, basically trial-and-error with disabling ever more options in the compile flags until it was working. Now I have to do this again, this time on Windows 7, and so far I haven't succeeded in compiling QtCreator :( To me this method of using a static compilation seems unnecessarily difficult; the compilation takes half a (working) day and (at least here) it often fails.
Am I missing something? Can this be done easier? Or does everybody who wants to make even the most simple program have to go through this 'hell'? For OS X there is a nice "Mac Deployment Tool", is there something similar for Windows?

Any answers will be greatly appreciated!
Cheers, Bart vS

http://files.vanstratum.com/CLASS_qt.png

Lykurg
10th August 2011, 22:07
1) Is it possible that the windows font (or the font you are using on windows) does not support that unicode chars? Have you test it with the same font? If so, I have no clue why, but as a work around you can use html (which in my opinion isn't so ugly) and you can also use it for the items ... but you have to create your own item delegate. To render the strings with html use QTextDocument and set the html there, then render it to the QPainter via QTextDocument::drawContents(). Some work but not so much for pure string items.

2) Why you have to link static. Isn't a dynamic linked application possible. For that you could provide an (single) install.exe. See NSIS Installer or BitRock etc.

julietbravo
10th August 2011, 22:37
Thanks for your fast reply Lykurg!

1) Most fonts used in Windows seem to have a limited character set where some characters indeed simply don't exist. I'll have to look into your proposed solution; all the data in the QTreeWidget is loaded from an object (not 'hard-coded' in the QTreeWidget) so perhaps I can put everything (or at least where needed) in html and load it through the sequence you suggested.

2) I tried making a stand-alone package before using a non-static compiled version of QtCreator but then I ended up with a huge nested list of dependencies (a.dll which depends on b.dll which depends on c.dll,d.dll.e.dll, etc.). I checked this with a tool called "Dependency Walker". How can I best solve this dependency problem? For me the list of dependencies (based on the output of the Dependency Walker) seemed endless...

*EDIT* Disregard my last question, I just found a quite extensive explanation about these things in the wiki of this website, I'll look through this before bothering you people with newbie questions ;)

Again, thanks in advance :)
Bart

Lykurg
11th August 2011, 07:23
Hi,

some further notes/ideas:

1) Before changing all to html, take a font, which supports the unicode symbols you use, and try it on windows. If that works you can deploy the font alongside your application without the need to actually install the font. Put the font in the qrc file and load it at runtime via QFontDatabase::addApplicationFontFromData().

2) Most of the dependencies you see are covered by Windows 7. If you don't use any further libraries you only have to bundle Qt(core|gui|sql).dll and the one of your compiler. That's all. (Possible some image plugins.) I guess you already have seen that: http://doc.qt.nokia.com/latest/deployment-windows.html.

And :confused: why do you want to deploy Qt Creator? It is only the editor and your application don't need it.

julietbravo
11th August 2011, 10:10
Hi,

1) We deliberately chose to work with the default fonts under Windows/OSX/Linux; for instance, by default I use the Ubuntu font under OpenSUSE and I always hate it when a program forces me to use, lets say, Comic Sans :p. I'll try the solution with html; if it is working we can use this on Windows/OSX/Linux (in the latter two we were also missing e.g. a superscript "3", so using html will sove some additional problems).

2) My apologies if I was unclear, we don't want to deploy QtCreator, only our little application :). I just did a fresh install of QtCreator (under Windows 7) and compiled (release) the program again. Moved the application to a new directory, included QtCore4.dll, mingwm10.dll, QtGui4.dll and next tried to fix the dependencies, needing the additional files: IEShims.dll (which was located in the Program files/internet explorer directory, I guess this is needed for the html that I use?), libgcc_s_dw2-1.dll and msvcr90.dll.

If I pull this combination through the dependency walker it gives me a warning ("error: at lest one module has an unresolved import due to a missing export function in an implicitly dependent module") and get a lot of missing functions (_Z4endlR11QtTextStream, _Z5qFreePv and about 100 more of these) from QtCore4.dll as QtGui4.dll depends on this file..

This is basically the problem I had before, after which I switched to a statically compiled version of QtCreator. Then I only needed to include Ieshims.dll, libgcc_s_dw2-1.dll and mingwm10.dll to get our little program working on a different (Qt-clean) system.


If you need additional information, let me know.
Thanks, Bart

julietbravo
11th August 2011, 15:08
As for problem 1); at the moment I'm filling the QtreeWidget like this:



for (int n=0; n<advancedtreegroups.size(); n++)
{
QTreeWidgetItem *treegroup = new QTreeWidgetItem;
treegroup->setText(0,advancedtreegroups.value(n));
ui->advancedplottree->addTopLevelItem(treegroup);
if (n == 0)
ui->advancedplottree->expandItem(treegroup);

for (int i=0; i<allvariables.value(n).size(); i++)
{
QTreeWidgetItem *treeitem = new QTreeWidgetItem;
outputvar item = allvariables.value(n).value(i);
treeitem->setCheckState(1,Qt::Unchecked);

if (advancedtreegroups.value(n) != "Vertical profiles")
treeitem->setCheckState(2,Qt::Unchecked);

QString variable = QString::fromUtf8(item.name.c_str()) + " [" + QString::fromUtf8(item.unit.c_str()) + "]";
QString description = QString::fromUtf8(item.description.c_str());
QString id = QString::fromUtf8(item.id.c_str());

treeitem->setText(0, variable);
treeitem->setText(3, description);
treeitem->setText(4, id);

treegroup->addChild(treeitem);
}
}

What should be the way to go? Given this structure, what would be the simplest solution to render some html in a QTreeWidgetItem at a given position/column?

I can create a QTextDocument and put some html in it:

QTextDocument abc;
abc.setHtml("<html>m s<sup>-1</sup></html>");


But then I'm completely stuck at how to continue :confused:

~Bart

Lykurg
11th August 2011, 20:00
Ok, that's my last present before I go on vacation tomorrow. It is not perfect, one can do a lot of optimizations, but that's all homework for you;)
#include <QtGui>


class MyDelegate : public QStyledItemDelegate
{
public:
MyDelegate(QObject* parent = 0)
: QStyledItemDelegate(parent) {};

void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
// you could also do a quick reg exp to check for
// HTML tags.
if (true == index.data(Qt::UserRole + 1234).toBool())
{
QTextDocument td;
td.setPageSize(option.rect.size());
td.setTextWidth(option.rect.width());
td.setDefaultFont(option.font);
td.setDocumentMargin(0);
td.setHtml(index.data().toString());
painter->translate(option.rect.topLeft());
td.drawContents(painter, QRect(QPoint(0,0), option.rect.size()));
painter->translate(-option.rect.topLeft());
}
else
QStyledItemDelegate::paint(painter, option, index);
}

};

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QTreeWidget tw;
tw.setColumnCount(1);
tw.setItemDelegate(new MyDelegate(&tw));

QList<QTreeWidgetItem *> items;
QTreeWidgetItem *it;

it = new QTreeWidgetItem;
it->setText(0, "plain Text");
items << it;

it = new QTreeWidgetItem;
it->setText(0, "m s<sup>-1</sup>");
it->setData(0, Qt::UserRole + 1234, true);
// you can choose any value for 1234
// this just tells if the item should
// rendered as HTML
items << it;

it = new QTreeWidgetItem;
it->setText(0, "m s<sup>-3</sup>");
it->setData(0, Qt::UserRole + 1234, true);
items << it;

it = new QTreeWidgetItem;
it->setText(0, "m s<sup>-1</sup>");
it->setData(0, Qt::UserRole + 1234, false);
items << it;

tw.insertTopLevelItems(0, items);

tw.show();

return a.exec();
}

julietbravo
11th August 2011, 20:14
Looks like I have some studying to do ;) Great, thanks a lot and have a nice vacation!!