Sunday 28 April 2013

Developing with Qt on the MSVC Express IDE

You can use Qt Creator with the MSVC compiler. However, you may prefer to use the MSVC IDE, instead. This is harder than it sounds, because Qt's build process may have additional compile steps, such as invoking uic or moc; and, by default, MSVC isn't aware of these steps. There is a Qt plugin, but it doesn't work in MSVC Express. So, if you're using MSVC Express, you need a different solution.

Googling provides several answers for this. The one I found more often was using qmake -tp vc to generate a .vcxproj file out of a .pro file. Works like a charm, and you're guaranteed to get a flawless build on MSVC with no extra work. Before running this command, just make sure your PATH includes qmake, set your QMAKESPEC correctly (if you're in doubt about the correct value for your system, check the mkspecs folder in your Qt installation), and... well, you'll have some relative called Bob, I guess.

This will also set all the required include and lib folders automatically; however, it won't set the runtime path, so before you try debugging your app from the MSVC IDE, go to your project's Property Pages -> Configuration Properties -> Debugging -> Environment and set the PATH to include all the required DLLs.

Running qmake like this takes a snapshot of the .pro file and creates a similar .vcxproj file, which means that further changes to your .pro file will require running qmake again. This will generate a new .vcxproj file (amazing, hey?), so you'd better a) have a good merge tool; or b) don't plan on making any changes to the .vcxproj file.

Why is this a problem? Well, even though we're using MSVC, we'll still have to work in Qt Creator, because: 1) Working in Qt Designer is a lot easier than creating .ui files by hand; 2) adding new forms to a Qt Creator's project also sets up the corresponding C++ files; or 3) when using Designer's tools for setting up signals/slots, you must have Qt's project open, if you just double-click the .ui file in your MSVC project, it opens the corresponding form in Qt Designer, but there's some things you won't be able to do (like using the Go to slot... option) because your project isn't open in Qt Creator (i.e., Qt Creator is editing a form, but doesn't know where are the corresponding C++ files, where the code must go). So, using MSVC as your IDE doesn't mean you'll never need to fire Qt Creator again.

We could create our MSVC project like this and then, whenever we added something to our .pro file, we'd manually add it to our MSVC project (and set its Item Type to Custom Build Tool and fill all the other required fields, if necessary).

Well, we could, but this wouldn't be much of a post if there wasn't some sort of alternative, right?

And we do have an alternative. I've first come across it here. Just by using what you find there (.target files for MSBuild), you'll have automatic handling of .ui and .qrc files. MOC compilation is treated on an item-by-item basis. I've looked at this, and decided to make some changes that better fit my planned workflow.

Before we start - everything written below assumes none of your own source files follows these specs: moc_*.cpp, ui_*.h, and qrc_*.cpp. The only files that follow these specs should be the files generated by moc, uic, and rcc. If that's not the case, then do not to use anything that I present/suggest on this post; doing so can not only mess up your build process in MSVC, but can also delete your source files by erroneously assuming they were generated. You've been warned.

moc compiler

My first goal is automating moc.

Note: The post linked above states that "since usually not all headers in a Qt project use the Q_OBJECT macro moc.exe would run and fail for those headers". This might have been correct at the time it was written, but not anymore. If you run moc on a file without the Q_OBJECT macro, this is what you get

>moc sometestclass.h
sometestclass.h(0): Note: No relevant classes found. No output generated.

>echo %ERRORLEVEL%
0


Contrast that with running moc on a non-existent file

>moc mainrrr.cpp
moc: mainrrr.cpp: No such file

>echo %ERRORLEVEL%
1


So, while I could just run every .h and .cpp file through moc, I prefer running just those that actually require it. So, I created a batch script that runs a grep for Q_OBJECT and uses wc -l to count the matches.

for /f "usebackq" %%a in (`grep "Q_OBJECT" %1 ^| wc -l`) do @set ret=%%a
if not %ret% == 0 echo %1 >> %2


Yes, this is on Windows; you can either install these utilities or use another alternative. The two parameters (%1 and %2) are the source file to check for Q_OBJECT and the result file where we'll write the source file's path, if a match is found.

I've then used the .targets file for uic on the linked article and adapted it to work with my script and invoke moc. So, what does it do?
  • It runs on every .h and .cpp file on the project root and its sub-folders, except files that follow the moc_*.cpp spec.
  • For each of these files, it runs the batch script described above.
  • It reads the result file, and runs each source file on the list through moc. moc's output is placed on either the debug or the release folder.
  • It adds the moc-compiled files to ClCompile.
The last step means we don't have to manually add the moc-generated files to our project. Let's look at an example. Suppose we have a mainwindow.h that looks like this:

class MainWindow : public QMainWindow
{
    Q_OBJECT

    etc...
};

We need to run mainwindow.h through moc, which will then create moc_mainwindow.cpp. However, unless moc_mainwindow.cpp is already part of our project, it won't be included in the build. And the build will fail, obviously. This would mean that, for every x file that needed moc, we would have to manually add a moc_x.cpp to our project. Not that much work, yes, but not my cup of tea, either. Especially when we can just let the build sort it out and add it automatically.

There is just one thing I haven't yet figured out - even when this target is skipped, the moc_*.cpp files are still added to the build, which doesn't make sense to me.

uic & qrc compilers

For these, I've made almost no changes to the .targets file on the linked article.
  • I've placed the output files in the debug and release folders.
  • I've added the .h files to ClInclude and .cpp files to ClCompile.

Bringing it all together

So, this is my suggested approach:
  • Create your Qt project, and immediately run qmake -tp vc to create the MSVC project.
  • Open the MSVC IDE, and remove the following files from the project: *.ui files, moc_*.cpp files, ui_*.h files, *.qrc files, qrc_*.cpp files.
  • Check the remaining files properties for any Item Type that is set as Custom Build Tool - e.g., if you have a form, qmake -tp vc will turn your form's .h file (say, mainwindow.h) Item Type to Custom Build Tool and call moc on it (because your form has the Q_OBJECT macro). Change all Item Types to C/C++ header or C/C++ compiler.
At this point, you should have a project with only .h and .cpp files, and there should be no custom build steps. Naturally, if you try to build it in this state, the build will fail, because neither moc nor uic will be called. You'll need to add the rules to call those tools. Right-click the project on the Solution Explorer and select Build Customizations. Click Find Existing... and navigate to the folder where you have the 3 .targets files described above (I've called mine QtMOC.targets, QtUIC.targets, and QtRCC.targets). Add them, and enable them (i.e., check the check-boxes before their names).

If you build now, you should have a successful build.

So, how do I plan to use this setup, then?
  • Changes to the form should be made in Qt Designer, opening the Qt project with Qt Creator.
  • Any UI additions will require us to manually add the .h and .cpp files. There's no need to add the .ui file, it'll be picked up by our rule.
  • Any new C++ source file will have to be manually added.
  • Nothing else needs to be added to the MSVC project. Our rules will pick up all the necessary files and include them in the build.
This is a level of manual work I'm comfortable with, because all it entails is adding C++ files. I'm not worrying about adding any specific Qt files, those are handled automatically.

I'll be using the same folder as project root for both Qt Creator's and MSVC's projects. The generated files will go on different sub-folders, though - I'll use MSVC's default debug and release folders, and for Qt Creator, I'll call them something like QtC-<Kit>-debug and QtC-<Kit>-release.

The .targets files output messages to the build log. However, to see those messages, you have to go to Tools -> Options -> Projects and Solutions -> Build and Run and set both MSBuild project build output verbosity and MSBuild project build log file verbosity to Normal. Alternatively, you can tweak the Importance parameter of the Message tasks.

Clean

You'll notice when you run Build -> Clean Solution, the generated files remain. If you don't want that, there's a simple way to take care of it. Open your project's Property Pages, go to Configuration Properties -> General -> Extensions to Delete on Clean, and select Edit from the combo box. Add the following lines:
moc_*.cpp
ui_*.h
qrc_*.cpp

Yep, even though it says extensions, it actually uses the whole file spec, which is the intelligent thing to do, actually. I'll say it again, obvious though it may be: If any of your own files follow these specs, then you can't use this.

You don't need to worry about dealing with the debug or release folders, because MSVC runs Clean on those folders, depending on which configuration you have active - if you copy a moc_*.cpp file and put it on your project's root folder, or on any other sub-folder, it won't be deleted.

There's an alternative to this, which is to place all the generated files in one folder (e.g., generated_files), and adding something like this:
generated_files\moc_*.cpp
generated_files\ui_*.h
generated_files\qrc_*.cpp

This means you'd have to create this folder in both debug and release folders. If you wanted a single generated_files folder, under your project's root folder, you'd have to add "..\" to each of the 3 lines above.

A final note

I'm just learning this, and none of the above has been thoroughly tested. Hence, the disclaimers on the .targets files. Use this at your own risk.

You can get the files here.

Thursday 25 April 2013

Qt Layout Tutorial - Part III

And here we are, in the third - and last - part of our Qt layout tutorial.

As I was preparing this post, I realized one of the group boxes we added in part I, namely the group box corresponding to area B, is not actually necessary. So, we're going to remove it (you may want to refer to part I of this tutorial, since I'll be using the names I defined there):
  • Drag group box B1 to area A. The group box corresponding to area A should "light up" its entire area, to show it has the focus and that's where you'll drop the dragged widgets.
  • Do the same with group box B2 and the vertical spacer (assuming it didn't disappear, see part II).
  • Delete the now empty group box on the right. If you did this before performing the previous steps, you'd delete the group box and everything it contains.
  • Place the group boxes and spacer back where they were.
A very important note: Before you start applying layouts, make sure area B is the exact size you want it to be. When you apply layouts in area B, it should cause a minimum amount of resizing.

So, let's finish this.

As we apply layouts, all the already existing layouts should become perfectly aligned and identically sized, and the widgets' size and position should keep their expected values. If that's not the case, then you need to review the properties on the widgets.

1. Select group box B1 and apply a vertical layout. Do the same with group box B2.

You may have to do some tweaking at this point - e.g., I've had to tweak the spacer in the 2nd row of B1, in order to get the 3 push buttons to the same size as the buttons in B2.

Notice that the push button in row 6 of B2 fills one whole row. If you don't like it, you have several options:
  • If you want the button aligned to the left of the group box, change its sizePolicy.HorizontalPolicy to "Fixed" or "Maximum". You can then set the button's minimumSize.Width to set its width.
  • If you want the button in the center of the row, you'll have to add 1 horizontal spacer to each side of the button. However, you'll have to do this BEFORE you apply the vertical layout to group box B2, because once the button is in a vertical layout, anything you add can only go above or below the button. So, just press "undo", add the 2 spacers, select all 3 widgets, and apply a horizontal layout.
  • If you want the button aligned to the right, follow the procedure in the previous point, but add only 1 spacer, to the left of the button.
If you add spacers, remember to set their sizeType to "Minimum", or area B will expand later.

2. Select the two groupboxes (B1 and B2) and the vertical spacer on the right side of the form and apply a vertical layout. This should give you both group boxes perfectly aligned, one below the other, and all the layouts within each group box (and, consequently, the widgets within each layout) should also be perfectly sized/aligned. If it doesn't - e.g., if some push buttons become larger than others, then... you've guessed it, it's time for some more tweaking.

I needed some tweaking on 4 of the push buttons that were aligned at the right side, and I've decided to change the maximumSize.Width on these buttons, instead of fine-tuning the spacers.

Area B is done, now let's turn to area A. My original idea was that it would contain a single widget, e.g., a label, that would grow and shrink as we resized the form. However, I've decided to complicate matters a bit. Instead, it will contain two widgets, a list widget on top of a text edit widget. The list will resize horizontally, but not vertically; and the text edit will resize both vertically and horizontally.

3. Add a list widget and a text edit to group box A.

4. Select the list. Its sizePolicy.HorizontalPolicy should be "Expanding". We'll set its sizePolicy.VerticalPolicy to "Minimum".

5. Now, select the text edit. Both sizePolicy.HorizontalPolicy and sizePolicy.VerticalPolicy should be "Expanding".

6. Select group box A and apply a vertical layout.

When you resize group box A, this is what should happen:
  • When the group box resizes horizontally, both widgets should resize accordingly.
  • When the group box expands vertically, the list may expand, but should stop doing so at some point, and only the text edit should keep expanding.
  • When the group box shrinks vertically, the edit box should shrink and, after some point, the list should begin shrinking, too.
When we apply all layouts, the list will stop resizing vertically.

Area A is done. It was a lot simpler because we didn't want to fine-tune our control of the widgets in this area. Keep this in mind when designing your UIs - the less control you want over size, position, and resizing, the better.

7. Before we turn to area C, let's select areas A and B and apply a horizontal layout. When you resize this layout, area B should move, but always keep the same size, and area A should maintain the resize rules outlined above.

Also notice that as you shrink this layout, either vertically or horizontally, all the widgets eventually get shrunk to oblivion. Don't worry, this will be solved soon.

Now, area C. Since I don't know very well what I could place here, I'll keep it simple - just a text edit that will resize horizontally, but not vertically.

8. Add a text edit to area C. Set its sizePolicy.VerticalPolicy to "Minimum".

9. Select the group box C and apply a horizontal layout.

10. Finally, select the form or its top widget (e.g., if it's a QMainWindow, you can select the main window or the central widget) and apply a vertical layout.

Build and run! You may need some additional touches. I did, had to tweak the sizeHint.Width on spacers to get all the buttons properly aligned.

Anyway, it's ready! Get a liquid beverage (as opposed to a "solid beverage", obviously) of your choice and indulge in as much rejoicing as legally permitted. And, while indulging in said rejoicing, notice that if you try to shrink the form it eventually stops - e.g., area B acts as a vertical break, it will stop shrinking when the vertical spacer on bottom reaches 0.

I hope you've found it useful, and not overly boring.

I'll end by saying, once again, that this tutorial is based mostly on trial and error. While I've advised certain values for widget properties, the same effect can be achieved using different values. And, naturally, there may even be a faster/better way of achieving this. And, if you happen to know of such a faster/better, you're welcome to drop me a line on the comments.

You can find the files here.

Sunday 21 April 2013

Qt Layout Tutorial - Part II

Note: Now that the tutorial is finished, here are links to part I, part III, and the files.

Before we proceed with our tutorial, a few notes about maximumSize:
  • Qt Designer won't let you resize a widget beyond its maximumSize. So, when you want to experiment with it, make sure its value is someHugeValueDefinitelyLargerThan42 (don't ask, just read part I), so you can resize it to your heart's content.
  • If you want your widget to expand with the layout, you'll have to take that into account when you change maximumSize. In this example, since I don't want area B to expand, I'm setting maximumSize equal to the current size.
  • Even though I said you don't need to change anything on push buttons, setting their maximumSize is always an option if you're having trouble getting them to keep your desired size.
Also, if you're having trouble with widget sizes in different layouts, the first thing to do is resize the layouts so they have similar dimensions. This is especially helpful with the push buttons in this tutorial, if you don't want to change any of their properties.

One final note: For some reason I didn't figure out (but I admit I didn't do much research on it), the vertical spacer I placed on step 3 of part I went missing when I reopened the project for this post. I added it back, closed and re-opened Qt Creator, opened the project and... gone again. I know once we apply a layout (which we'll do in part III) it stays put, so I've just accepted it as another little quirk I'll have to live with.

Now, let's continue our Qt layout tutorial.

In part I we've divided the form in 3 areas, and filled area B1 (you may want to refer to part I, since I've defined these names there). Now, let's take care of area B2.

Area B2 will contain 6 rows of widgets (don't add them yet, just keep reading):
  • label + line edit + label + line edit + label + line edit + horizontal spacer + push button.
  • label + line edit + horizontal spacer + push button.
  • label + line edit + label + line edit + label + line edit + horizontal spacer + push button.
  • label + line edit + horizontal spacer + label + line edit + horizontal spacer.
  • label + combo box.
  • push button.
These widgets will need the same changes as we applied to the widgets we added to B1, otherwise B2 would cause area B to expand. So, instead of adding the widgets and changing all the properties again, I'll copy/paste as much as I can. Naturally, you're encouraged to change the widgets text and size, and play around with it; if a widget doesn't behave as expected when you apply a layout, take a look at its maximumSize and sizePolicy.

Also, don't worry if the layouts aren't perfectly aligned or have small differences in size. When we apply the final layouts in part III, everything will fall into place.

1. B2 - Row 1
1.1. Select a label and a line edit in B1, and copy/paste. Then, drag the copies to B2. Adjust the text and size of both widgets according to what you want. Repeat until you have 3 labels and 3 line edits in B2. Notice that you won't have to change sizePolicy, because the original widgets already had the correct value for our goal.

1.2. Select the horizontal spacer in B1, copy/paste, and drag it to B2. Once again, you won't have to change anything else.

1.3. You can add a new push button, instead of using copy/paste, since we didn't change anything on the push buttons.

2. B2 - Rows 2-6
For row 2, select a label, a line edit, a horizontal spacer and a push button from row 1. Copy/paste, and drag. Row 3 happens to have the exact same widgets as row 1, so you can just copy/paste row 1. For row 4, you can copy/paste a label + edit + spacer twice. And for rows 5 & 6, just add the widgets, setting the combo box's sizePolicy.HorizontalPolicy to "Minimum".

3. Next, we apply a horizontal layout to row 1. Everything should become neatly spaced, within the layout. Then, we apply a horizontal layout to row 2.

Now, since row 2 also has a push button at the right end, I'd like those buttons aligned. In order to achieve that, I aligned both layouts at the left border and fiddled with the sizeHint.Width on row 2's spacer. This is the best process I've discovered to align widgets on a layout - change their size in the property sheet. I did the same with the edit widget on row 2 to align it on the right with the 2nd edit widget on row 1.

4. Row 3 should be easy, since it's identical to row 1, so we just apply a horizontal layout. Row 4, however, may require some tweaking to get a widget alignment that looks good with the other rows. Some options are - change the dimension of the edits in rows 1-3 to align them with the second edit on row 4, or remove the second spacer in row 4 and let the 2nd edit align to the right.

I went with the first option. And that was good, because it showed me again that, while I can get around designing this UI, that doesn't mean I know exactly what's going on. I increased the size on the 3 edits in row 1. Instead of "compressing" the spacer, this sent the push button off the edge of group box. I resized the layout to fit within the group box, and, again, the spacer remained constant and the push button shrank. I only got the spacer to shrink and the push button to return to its "normal" (read "desired") size by manually reducing the spacer's sizeHint.Width on the property inspector.

However, when I did the same thing in row 2, everything went smoothly. Even though the push button was also pushed off, when I resized the layout, it went back into place and the spacer shrank automatically. I even increased the spacer's sizeHint.Width, which pushed the button off again, but when I resized the layout, back into place it went, with no need for manual resizing.

I checked the properties on all the widgets in rows 1 and 2, matching each identical widget - label to label, edit to edit, etc. All size policies were identical, all the mix/max sizes were set in the same fashion. So, why the different behaviour? No idea. At least row 3 behaved like row 1, so whatever's happening, it's consistent.

Then, I set the first spacer on row 4 with sizeType "Maximum" and adjusted the maximumSize.Width on the second edit, until it aligned on the right with the first edit on row 3.

5. Row 5 is easy, we just select both widgets and apply a horizontal layout. Then, we resize the layout, and the combo box will expand. Row 6 is just the push button, so we'll leave it be, there's no need to apply any layout.

That's it for now, we'll wrap it up next time.

Tuesday 16 April 2013

Qt Layout Tutorial - Part I

Note: Now that the tutorial is finished, here are links to part II, part III, and the files.

Laying out a roadmap

Over the next few posts, I'll show how to get Qt's layouts to do what you want, instead of totally ignoring you and just "doing their thing".

I'll start by saying what this is not:
  • It's not a reference of Qt's widgets/layouts.
  • It's not an introduction to Qt's layouts.
In fact, it may not even be the best/cleanest way to achieve the result I present here. It's just the way I figured out. It's also the tutorial I wish I had found when I had to deal with layouts in Qt, namely, something that explained step-by-step how to create a non-trivial UI in Qt Designer.

We'll be creating an UI similar to this (riveting, heh?):

+-------++----+
|       ||    |
|   A   ||  B |
|       ||    |
+-------++----+
+-------------+
|      C      |
+-------------+

A - Visualization area. When we resize the form, this area expands/shrinks both horizontally and vertically. In this tutorial, it'll probably contain a QLabel (e.g., for image viewing).
B - Input area. This will contain two group boxes, each with several widgets. When we resize the form, this area will move, but won't grow/shrink. This area will anchor on the form's left side.
C - Feedback area. I have nothing defined for this area, and will improvise a bit once we get to it. This area will grow/shrink horizontally, will move vertically, and it will anchor on the form's bottom.

By the way, when I use the word "form", I'm referring to any of the options we can use for a .ui file in Qt - main window, dialog, page, widget, etc.

Let's get started

1. We'll start by creating a new GUI project in Qt Creator. As I said, this is not an introduction, so I expect you know how to create a GUI project in Qt Creator.

2. Add 3 group boxes to the form, with positions roughly similar to areas A, B, and C, above.

3. Add 2 more group boxes to area B, one on top of the other; we'll call them B1 (top) and B2 (bottom). Add a vertical spacer below B2. Since area A will grow vertically and area B won't, we'll use this spacer to fill the remaining space.

4. Add the following to B1, in 2 rows:
  • Top row: label + line edit + label + line edit + horizontal spacer.
  • Bottom row: 3 push buttons.

5. Edit the labels and input your description. You can then resize the labels by selecting them and pressing Ctrl+J. Or right-click and select "Lay out -> Adjust Size". Notice that the labels will adjust to the text you've entered.

6. Next, resize the line edits to a sensible width for what you expect to input. E.g., in my case, I'll be inputting numbers in the range 0-255.

7. Now, we'll apply our first layout. Select the top row (label + line edit + label + line edit + spacer) and apply a horizontal layout. What happens next depends on the width of the form and the widgets; in my case, the labels kept their width, but the edits increased in width and threw the spacer off the form, to the right.

So, what's going on? If you take a look at the labels, their sizePolicy is "Preferred, Preferred". However, for the edits, sizePolicy.HorizontalPolicy is "Expanding". And maximumSize.Width is someHugeValueDefinitelyLargerThan42 (16777215, in my case). We need to put some sane values here.

First, press Ctrl+Z to undo the layout.

We'll start with the labels. Even though they kept their size, I believe it's cleaner to change them to state our intent - change their maximumSize.Width to match their current size, i.e., geometry.Width.

Next, we'll change the edits, setting sizePolicy.HorizontalPolicy to "Minimum", and maximumSize.Width to each edit's geometry.Width.

Now, we reapply the horizontal layout. Et voilĂ . The madness is gone, everything's sane. Well, for now. There's still one change missing, and we'd better do it now. Why? Because if we don't do it now, when we have just a few widgets, we'll have to go through a most-certainly-not-boring-no-no-not-at-all cycle of trial and error later, when we have, say, some 20+ widgets on our form.

So, select the spacer and change its sizeType from "Expanding" to "Minimum". And why are we changing this? Because if we don't, when we apply a layout to the form, area B will expand, and that's not what we want.

So, to recap: After setting the labels and edits to your desired width, set their maximumSize.Width to that value, and set sizePolicy.HorizontalPolicy to "Minimum" for both edits and the spacer.

8. Now, we'll apply our second layout, on the 3 push buttons in the bottom row of B1.

Here, we won't have to do anything else. Even though each button's maximumSize.Width is someHugeValueDefinitelyLargerThan42, their sizePolicy.HorizontalPolicy is "Minimum"; this ensures that these buttons won't cause B1 to expand, which is our goal.

If you want to keep the buttons smaller, add 2 spacers between them. If you want to keep 2 buttons together and separated from the third one, add a spacer between them. Just remember that the spacers on B can't have sizeType "Expanding", as that'll cause B to expand later on. I'm using "Minimum" since it's what worked best for me.

A dose of reality

Even though the steps presented above are nice, clean, and simple, the process to get there was anything but. It involved generous amounts of trial and error, experimenting and fiddling.

I now have a better understanding of how to get the layouts to do what I want, but I still think this is not practical. We shouldn't have to fiddle with each control to get the results we want, there should be overriding policies at both the layout level and the container level. And Qt Designer should allow us to resize the widgets after a layout has been applied and should have options to automatically change the necessary values to keep the appearance we want within the layout.

Yes, I know. This is Open Source, if you don't like it, contribute. The thing is, my sentence above, "I now have a better understanding of how to get the layouts to do what I want", is only half the story; the other half is "but I still don't actually understand how layouts work, I still can't visualize all the parts that contribute to it and grok their interactions". And this is definitely not high on my list of priorities, nor should it be.

Nor should it be, and that is actually my main complaint about the layout managers I've had to deal with, both in Qt and in Java - for something that should be simple and transparent, they sure require a lot of investment just to get it working, once you move away from Trivialville.

Anyway, that's it for now. We'll continue this tutorial on my next post, when we'll add a boatload of widgets to area B2.

Sunday 14 April 2013

Tidbits

Another quick post, along the lines of "what have I been up to"?
  • Investigating the debugging issues with gdb + Qt Creator (see here). Basically, a debugging session in Qt Creator will start a second thread on my app to load the executable's image and the required DLLs. However, sometimes, this thread doesn't exit, and the debugging session will inevitably switch to it, due to a SIGTRAP signal, and it will all eventually die with a SIGSEV.
  • Installing Sysinternal tools, Windows Performance Toolkit and VerySleepy. I've performed some captures with xperf, and took a look at the results with WPA. MS's documentation for this is less than stellar, and I recommend Bruce Dawson's blog for some high-quality info about WPF. My next step will be getting a better understanding of how these tools get the debug symbols, especially VerySleepy and gcc (mingw) symbols.
  • Fooling around with an algorithm for the Game of Life. I'm not expecting to come up with anything that competes with Hashlife, just something that I can compare with a brute-force implementation and see how it fares.
  • I've also been experimenting with Qt Designer. I won't get started on layout managers, otherwise I might just "never stop, never stop, never stop, never stop". I'll just say that I really miss C++ Builder. Hell, even good old WinForms was more intuitive. Still, this is what I have right now, and I'll be damned if I won't make it do what I want, instead of what it seems to think it should be doing based on the value of a few properties and the interaction those properties create, when spread out over a couple dozen widgets, and a few nested layout managers. Ugh!
Anyway, I've put testing the builds and my libsh2/boost::asio experience on hold for a bit, since both will get some mileage out of what I learn about Qt GUIs from these experiences with Qt Designer.