Qt Visual Studio Add-in



Getting Started

In this tutorial, we will create an address book application step-by-step using the Qt Visual Studio Add-in. We will also outline how to make a basic project using one of the project wizards and create a form with Qt Designer. In addition, we will also show you how to convert a Visual Studio project file into a qmake compatible .pro file.

Creating a Skeleton Qt Application

The first step is to create a trivial project. To do so, select the New Project dialog in Visual Studio and click the Qt Projects folder. Then select the Qt Application item and type "AddressBook" in the Name field.

When you click OK, a project wizard will appear. This wizard has a page listing Qt modules you can link your project against, followed by a page that enables you to specify the name of a skeleton class that will be generated by the wizard as a starting point. For this Address Book example, we will use the default values.

Now, we have a small working Qt application. Press F5 to try it out. The result is an empty window. You can close it by clicking the X button on the title bar.

Designing the Main Dialog

Next, we will design the application's main dialog using Qt Designer. See the Qt Designer Manual for more information.

We begin by adding the widgets and setting their properties. These widgets are then put into layouts. The result is shown below.

Screenshot of the AddressBook's main dialog

Adding the Widgets

We launch Qt Designer by double-clicking on the Form Files\addressbook.ui file in Visual Studio's Solution Explorer.

First, we add the QListWidget. Expand the Item-Based Widgets group in the Widget Box, then click on the List Widget subitem and drag it to the top-left corner of the form. The Property Editor will now display the properties for the QListWidget object. Using this editor, set the ObjectName property to "addressList".

Next, we insert the Add and Delete buttons. Expand the Buttons group in the Widget Box and drag two Push Buttons to the top-right corner of the form. Rename the buttons to "addButton" and "deleteButton", and their Text property to "Add" and "Delete".

Finally, we add two QLabel objects to display the selected item in the list by dragging the Label item from the Display Widgets group onto the form, once for each label.

Rename the first label to "nameLabel" and change its Text property to "<No item selected>"; rename the second label to "emailLabel" and leave its Text property empty.

Try to position the widgets as they appear in the screenshot above.

Adding the Layouts

In order to properly position the widgets and ensure that they resize accordingly when the form is resized, we need to add layouts to the form.

We require a vertical layout for the buttons as well as a spacer to push the buttons to the top of the layout. To add a spacer, drag the Vertical Spacer item from the Spacers group onto the form, located below the push buttons. Then, select the buttons and the spacer (click on each widget while holding Shift) and click Form|Layout Vertically.

The window also needs a layout to manage the positioning of other widgets as well as the button layout. So, we add another layout by selecting the list widget, the two labels and the button layout, and then clicking Form|Layout in a Grid.

Hint: Make sure that the labels are almost as wide as the form; otherwise the grid layout will make them only as wide as the address list.

To preview your form without compiling it, click Form|Preview.... To build and run the application save the form, leave the Qt Designer and press F5 in Visual Studio.

Adding an "Add Address" Dialog

Now that the main dialog is done, we move on to add functionality to our address book application. We would like to have an application that pops up a dialog when the user clicks the Add button. Hence, we require an "Add Address" dialog.

Designing the Dialog

We start by designing the dialog. This time, there is no ready-made .ui file available in the project. So, we select Project|Add Class...|Qt4 Classes|Qt4GuiClass. This will invoke a wizard requesting for a class name. Enter "AddDialog" as the name and "QDialog" as the base class. Then, check the "Multiple Inheritance" checkbox and click on the Finish button.

You will now have an adddialog.ui file in the project's Form Files folder.

Screenshot of the Add Address Dialog

To set the properties of the dialog, double-click on adddialog.ui to open the form in Qt Designer. Then, click on the form and set its WindowTitle property to "Add Address". Next, create the following widgets and set their ObjectName and Text properties according to values listed in the table below.

WidgetObjectNameText
QLabel"nameText""Name:"
QLabel"emailText""Email:"
QLineEdit"nameEdit"""
QLineEdit"emailEdit"""
QPushButton"okButton""OK"

Now you can layout your widgets. Hint: Use a grid layout for the labels and line edits.

Connecting to the Dialog's OK Button

We want the OK button to invoke the QDialog::accept() slot, and we do this by clicking on the Edit Signals/Slots toolbar button. You will then enter Qt Designer's Signals and Slots Editing Mode.

Click on the OK button and drag the mouse cursor to an empty area of the form and release the mouse button. The Configure Connection dialog will pop up, allowing you to establish a signal-slot connection between the OK button and the form. Connect the button's clicked() signal to the form's accept() slot.

Displaying the "Add Address" Dialog from the Application

Once we have completed designing the dialog, we have to invoke it when the user clicks the main dialog's Add button. To achieve this behavior, we add a slot to the AddressBook class and invoke the AddDialog from this slot.

Forms created using Qt Designer call QMetaObject::connectSlotsByName() to establish connections between signals emitted by the form's child widgets and slots that follow the naming convention on_<sender>_<signal>(). To react on clicking the add button you must implement a slot called on_addButton_clicked(). Type in the following lines of code in the slot's body:

 AddDialog dialog(this);
dialog.exec();

If we want to connect to another signal, instead of clicked(), we have to add another signal to the AddressBook class. This requires editing both the header file (addressbook.h) and the implementation file (addressbook.cpp).

Next, we include adddialog.h to addressbook.cpp:

 #include "adddialog.h"

Build and run the program now. If you click on the Add button, the Add Address dialog will pop up. If you click on OK, the dialog will disappear.

Adding Items to the List Widget

When the user clicks OK, we would like to add an item to the QListWidget. To do so, modify the code in the on_addButton_clicked() slot to the following:

 AddDialog dialog(this);

if (dialog.exec()) {
QString name = dialog.nameEdit->text();
QString email = dialog.emailEdit->text();

if (!name.isEmpty() && !email.isEmpty()) {
QListWidgetItem *item = new QListWidgetItem(name, ui.addressList);
item->setData(Qt::UserRole, email);
ui.addressList->setCurrentItem(item);
}
}

We execute the dialog. If the dialog is accepted, e.g., OK is clicked, we extract the Name an Email fields and create a QListWidgetItem with the given information.

Try out the application. Click Add, enter "John Doe" for the name and "john@johndoe.de" for the email. Click OK. The list widget should now contain the new item.

Displaying the Selected Item

When the user selects an item in the list widget, we would like to update the nameLabel and emailLabel at the bottom of the form. This behavior requires another slot to be added to the AddressBook class.

In the addressbook.h file, add the following code in the private slots section of the class:

 void on_addressList_currentItemChanged();

Then, add the block of code below to addressbook.cpp:

 void AddressBook::on_addressList_currentItemChanged()
{
QListWidgetItem *curItem = ui.addressList->currentItem();

if (curItem) {
ui.nameLabel->setText("Name: " + curItem->text());
ui.emailLabel->setText("Email: " +
curItem->data(Qt::UserRole).toString());
} else {
ui.nameLabel->setText("<No item selected>");
ui.emailLabel->clear();
}
}

Thanks to the naming convention, this slot will automatically be connected to addressList's currentItemChanged() signal, and will be invoked whenever the selected item in the list changes.

Adding Functionality for the Delete Button

Similar to the Add button, we implement a slot for the Delete button. Open the addressbook.h file and add a new slot declaration on_deleteButton_clicked(). Then open addressbook.cpp and add the slot definition for on_deleteButton_clicked(). Type the following code in the slot's boy:

 QListWidgetItem *curItem = ui.addressList->currentItem();

if (curItem) {
int row = ui.addressList->row(curItem);
ui.addressList->takeItem(row);
delete curItem;

if (ui.addressList->count() > 0)
ui.addressList->setCurrentRow(0);
else
on_addressList_currentItemChanged();
}

Your application is now complete!

Creating Qt Project File

If you want to build this application on other platforms, you need to create a .pro file for the project. A simple way to do this is to let the Visual Studio Add-in create a basic .pro file for you by clicking Qt|Create Basic .pro File. When the Export Project dialog shows up, ensure that the Create .pri File option is checked, then click OK. Visual Studio will then ask you where to save the .pri file. The default location and name is usually sufficient, so just click Save. For more information about .pro files and their associated .pri files, see Managing Projects.

That's it! You should now have a working .pro file and .pri file for your project. For more complex projects, manually editing the .pro file is required to make it work on all plaforms; however, for our simple project the generated .pro file is sufficient.



Managing Projects

Creating New Qt Projects

Once you have installed the add-in, Visual Studio's New Project dialog will contain a Qt Projects folder with the following project templates:

  1. Qt Application: A simple Qt GUI Application with one form.
  2. Qt Console Application: A basic Qt console application.
  3. Qt Library: A basic Qt-based dynamic library.
  4. Qt4 Designer Plugin: A Qt Designer custom widget plugin.
  5. ActiveQt Server: A simple ActiveX server.

If you have a Qt for Windows CE license, two additional project types are available:

  1. Qt WindowsCE Application: A simple Qt GUI Application for Windows CE with one form.
  2. Qt WindowsCE Library: A basic Qt-based dynamic library for Windows CE.

Each Qt project provides a wizard that allows you to specify the Qt modules required for your project. For some projects, the wizard will also generate a skeleton class that you can use to get started.

If you have used the installer for the binary version of Qt, you are now ready to write Qt code and build your projects. Alternatively, if you have built Qt from source, then you must tell Visual Studio where to find Qt. This step is further explained in the Basic Qt Version Management section.

Modifying Project Properties

Qt related project properties can be modified by opening the Qt Project Settings dialog. To display this dialog, select the respective Qt project in the solution explorer and select Qt|Qt Project Settings.

Screenshot of the property browser when selecting a Qt project

The following Qt project settings can be changed:

PropertyDescription
VersionThe Qt version to use for this project (see Basic Qt Version Management).
MocDirectoryThe directory (relative to the project) where the generated moc files are put. This directory must include the $(ConfigurationName) variable, to ensure that the moc files for different configurations (e.g., debug or release) do not collide.
MocOptionsAdditional command line options for the moc build step.
UicDirectoryThe directory (relative to the project) where the uic generated header files are put.
RccDirectoryThe directory (relative to the project) where the rcc generated source files are put.

When a Qt project is created, these properties are initialized to default values based on the last entered information found in the the Qt|Qt Project Settings dialog.

Basic Qt Version Management

The Visual Studio Add-in offers its own simple Qt version management, enabling you to use multiple versions of Qt 4 in parallel, e.g., Qt 4.5.0 and 4.5.1. When you install the add-in, the information about Qt versions is added to the user registry hive. So, another user will have to add a new Qt version since no default version will be set.

To add or remove Qt versions, click Qt|Configure Qt Versions and select the Qt Versions page. Click Add, then enter a name for the Qt version and the path to Qt's root directory, for example, C:\\Qt\\4.5.0". The first added Qt version is automatically the default version which will be used when creating new projects or importing a project from a .pro file. The default versions for Qt Windows or Windows CE projects can be changed using the combo boxes located under the Qt Builds list.

Screenshot of Qt versions configuration dialog

To specify which Qt version a project should use, select the project node of a Qt project (e.g., "Project1") in the Solution Explorer, and set its Version property using the Qt Project Settings.

Changing the Qt version for all projects in the solution can be done by invoking the context menu of the solution and activating the Change Solutions' Qt Version item. You can then select your desired Qt version in the dialog listing all available Qt versions.

Note: When you set a Qt version for the solution, this version becomes the default version if you add new projects to the solution.

Using the Qt Visual Studio Add-in does not require a globally set Qt environment variable. The Add-in will always overwrite the existing global Qt environment variable.

Note: If the build of your Qt projects fails with the error message The following environment variables were not found: $(QTDIR), then the project is probably referencing an invalid Qt build. This can happen after uninstalling an old Qt version. To correct this, change the Qt version of your project to a valid one.

Changing The Target Platform of Your Project

If you are developing on the Windows CE platform, Visual Studio Add-in enables you to switch between Windows and Windows CE easily. It is possible to create a standard Windows project, develop and test your application on your desktop PC, then later convert it into a Qt on Windows CE version.

To switch between platforms choose the appropriate Qt version in the Version property using the property browser, as described above.

Importing and Exporting Projects

Qt and Visual Studio use different file formats to save projects. If you build your application on multiple platforms, you probably already use Qt .pro files with qmake; otherwise, you might use .vcproj files and Visual Studio to build your project, usually convenient for Windows- only development.

Qt's Visual Studio add-in provides a way to combine both approaches - you do not have to manually maintain .pro files and .vcproj files in parallel. You start by creating a .vcproj file as usual. When you want a qmake .pro file, select Qt|Create Basic .pro File to generate a .pro file where you can store Unix and/or Mac OS X specific settings.

Screenshot of export dialog

If you have multiple Qt projects in one Visual Studio solution, the basic .pro file generator can create a master .pro file of type subdirs that includes all of the projects.

The generated .pro file is not meant to be a complete file, but a simple starting point for porting to other platforms. Having said, these files should be sufficient for compiling the skeleton projects created by the predefined Qt project wizards. The .pro file includes a .pri file.

The .pri file contains the list of source files, header files, .ui files, and .qrc files in the project. To generate the .pri file, select Qt|Export Project to .pri File. Whenever you add or remove a file from the Visual Studio project file, you must regenerate the .pri file to ensure that the application can still be build on other platforms.

Also, ensure that the included .pri file in the .pro file points to the right file. If you saved the .pri file in the suggested path and name, this should be correct.

Developers on platforms other than Windows can add or remove files to the project by editing the .pri file. When this happens, Windows developers must select Qt|Import .pri File to Project to bring the Visual Studio project file in sync with the .pri file.

If your project contains platform-specific source files, these files should be listed in the .pro file so that they are not overwritten by the Visual Studio Add-in.

In summary, a cross-platform Qt project consists of the following files:

  • A .vcproj file containing Windows-specific settings and listing the files in the project.
  • A .pro file containing Unix and/or Mac OS X specific settings.
  • A .pri file (a qmake include file) listing the files in the project.

If you already have a .pro file but not a .vcproj file, select Qt|Open Qt Project File (.pro)... to convert your .pro file to a .vcproj file. Be aware that the generated .vcproj only contains Windows-specific settings. Also, there is no way to convert a .vcproj file back to a .pro file format, apart from the basic .pro mechanism described above.



Adding Form Files to the Project

The Visual Studio Add-in lets you launch Qt Designer simply by double-clicking on a .ui file. See the Qt Designer manual} for more information.

To add a new .ui file to the project, select Project|Add New Item and then select the Qt Widget Form or the Qt Dialog Form template from the Qt Project Items folder.

Normally, you will need to wrap the code generated for the form file into a QWidget subclass to add signals or slots to it. A convenient way to do this is to select Project|Add Class and then select Qt4GuiClass from the Qt4Classes folder. This will create a .ui file, a .h file, and a .cpp file for you.

Creating Form Templates

You can add customized form templates by following these steps:

  • Create a form in the Qt Designer and save the .ui file (e.g. mydialog.ui).
  • Copy mydialog.ui to the uiItems\ directory within the Qt Visual Studio Add-in installation directory.
  • Create an icon file named mydialog.ico. It should have a size of 32x32 pixels.

After the next start of Visual Studio you can add new forms using your custom template.



Managing Resources

Adding new resources to a Qt project is similar to adding resources to a normal C++ project, the main difference being that .qrc files (Qt resource files) are used instead of Windows .rc files. Unlike .rc files, .qrc files work on all platforms supported by Qt and are trivial to load from Qt code.

Screenshot of the .qrc editor

To add new resources, you must first create a new .qrc file. To do this, open the Add New Item dialog, select Qt Resource File from the Qt Project Items folder, and click Open. The newly created .qrc file will be displayed in the Qrc Editor, which is part of the Add-in installation.

At this point, the .qrc file only contains a prefix named after the project. You can add resources under that prefix by selecting it and clicking on the Add button on the right hand side. Then click Add File in the context menu. Now the Resource Editor will display a dialog that allows you to add an existing file.

When referring to the resources later on from Qt code, you must prepend the prefix, the file name, and a colon. For example, :/MyProject/print.bmp. Using the context menu, you can rename the predefined prefix or add other prefixes to the .qrc file.

See the Qt Resource System document for more information.


Creating Qt Translation Files for the Project

To add a new translation file to the project, select Qt|Create New Translation File. In the Add Translation dialog, you can choose the language to create a translation file. A suggested file name is provided, and will be created when you click OK. The translation file is placed in the Translation Files folder in Visual Studio's Solution Explorer. Right-clicking on a translation file displays a menu that allows you to invoke lupdate, lrelease, and Qt Linguist.

See the Qt Linguist manual for more information on Qt's translation tools.



Frequently Asked Questions

Why is code completion not working?

You're implementing a slot...

Visual Studio can only provide code completion as long as it understands the code. Unfortunately, it does not know how to handle the Qt keyword slots in the header file. This means that the respective function body is foreign to the code model and no code completion will be provided. You can workaround the problem be placing a ';' after the colon of the slots keyword in the class declaration.

Note: Remember to remove the ';' when exporting the project as the code might not with older Unix compilers.

 class MyClass {
Q_OBJECT

public slots:;
void doSomething();

...
};

You are referencing objects from a .ui file...

The Visual Studio code model parser only parses C++ sources, meaning that widgets or objects defined in .ui files will not be accessible. To workaround the problem, the Qt Visual Studio Add-in automatically generates C++ code from the .ui file by saving the file and running uic on it. This step is done everytime the project is built. If the code completion does not work, try to rebuild the project. It is possible that you have to wait some time, before code completion fully works after updating an .ui file. For more information, you can refer to the Modifying Project Properties section.

It still does not work...

You should refresh the code model, Intellisense. This is done by opening the solution explorer, invoking the context menu of the project and activating the item Update Intellisense.


Comments