is it better to create / add tab form in QtDesigner instead ?
My preference is to use QtDesigner for simple widgets - a QDialog or a QWidget with display or edit controls only. Anything more complicated (like tabs, stack widgets, etc.) I build in C++ code. I do not use QtDesigner to add slot connections; I make them in code using connect() statements. I also do not use the "automatic" slot connection feature of the MOC compiler: If you declare a slot for a QPushButton's clicked() signal as "on_buttonName_clicked()", MOC will add code to automatically connect the button's "clicked" signal to that slot. If you later add a connect() manually, then the slot will be called twice for every click, giving you no end of headaches as you try to figure out why.

So if I add another connection using Edit signal / slot - which takes precedence ?
Every signal / slot connection is unique. When a QObject-based class instance "emits" the signal, all slots that are connected to it will be called in the order in which they were connected. More than one slot can be connected to the same object instance's signal. The same slot may be connected to different signals from the same or different objects. The same signal / slot pair can be connected more than once, which means the slot will be called that many times for the same signal (not something you usually want to happen).

If I copy device.ui to deviceWidget.ui how do I associate that with DeviceDiscoveryWidget ?
The UIC (UI compiler) compiles the filename.ui file into ui_filenamei.h . This file declares a class with the same name as the class defined in the UI file, with "Ui_" prefixed to it. Look in the device.ui file, you will see an element "<class>DeviceDiscovery</class>". The UIC takes this name and creates a class named "Ui_DeviceDiscovery" in the ui_device.h file. This class has a setupUi() method.

For the DeviceDiscoverDialog class, you can see that "ui_device.h" is #included at the top of "device.h" and you can see a pointer variable Ui_DeviceDiscovery * ui" declared in the dialog class. In the DeviceDiscoveryDialog constructor, this variable is initialized with "ui( new Ui_DeviceDiscovery )" and later in the body of the constructor, this variable is used to execute the Ui class' "setupUi()" method. This builds the user interface that is shown at runtime.

So this is the association you asked about. The UIC compiles the *.ui files and generates ui*.h files containing class definitions named after whatever class was declared in the ui file. This ui_filename.h file is #included in the header file for the QWidget-based class that uses that user interface, and a variable of the Ui_class type is declared in the QWidget class. Usually this is done by your development environment (eg. QtCreator) when you execute an "Add new Qt GUI class" operation.

By convention, the user interface files are all named the same "device.h", device.cpp", "device.ui" just to eliminate confusion. But you can actually name them anything you want, as long as you #include the right files in the right places.

One more wrinkle:

There is also a MOC compiler (Meta Object Compiler). Any class that is derived from QObject (in other words, any class that implements signals and slots) must contain the Q_OBJECT macro at the top of the class definition. When you add a new QObject-based class using QtCreator (or Visual Studio with the Qt plugin) it automatically adds build instructions to run the MOC on your filename.h file. When you build your project, MOC runs on filename.h creating a moc_filename.cpp file, and adds that cpp file to the build also. The moc_filename.cpp class contains boilerplate code that implements any custom signals you have declared, as well as code to implement any automatic signal / slot connections. This .cpp file if compiled along with your own cpp files and linked together to form the entire executable.

So, in the case of the DeviceDiscoveryDialog class, there are ultimately 5 files:

- three files you create (device.h, device.cpp, and device.ui)
- one file generated by UIC (ui_device.h)
- one file generated by MOC (moc_device.cpp)

If you poke around in your build directories, you should see all of these files. If you are curious, you can open these generated files in your source code editor to see what the boilerplate code looks like, but if you change it your changes will be erased the next time the file is generated.

You use your C++ IDE to edit the ,cpp and .h files, QtDesigner to edit the .ui file, and the last two are created automatically each time the project is rebuilt.