I finished a project in C++
. It is a console application, created with CodeBlocks. Although I consider it not so important in the scope of this question: The application manages data about bills and customers of a small company. The program is complete and could be very easily expanded by a console user interface (right now, I run it as a programmer).
Now I decided to learn GUI programming using Qt
and the QtCreator with its QtDesigner!
Not only because it is common practice to separate logic from GUI when creating a GUI application, I want to put my project into practice in two big parts, namely, of course, logic and GUI.
You already know that the logic part is complete; what I have is a project folder called project
containing another folder (CodeBlocks project) project_logic
which again contains several classes, thus header files and implementation files (and a main, which will of course be obsolete, eventually). It also contains files from/into which the program reads/writes. It is written in "pure" C++
and uses none of the means provided by Qt
and it is important to me that it stays that way!
Now I added a Qt
project project_gui
into the project
-folder and started to create the GUI, implementing only the most basic functionality, like changing between dialogues, closing the application, etc. So far it knows nothing about its future back-end (project_logic
).
As a third component I need some kind of controlling which links the application's logic with its GUI. Here comes my conceptual question: What is the best way to put them together in one application?
Since project_logic
could work alone as a console application, it already provides the most essential controlling components and functions. This will stay this way, because I want to keep its standalone functionality. Even more so because I am totally new to GUI programming and/or in two weeks I could happen to create another GUI for the same logic. The result would be that the classes of the logic part are included in the GUI source like any other header and used to create a program with full functionality. Validating user input would rest on the GUI part. The program's logic would in any case remain updatable.
To make the GUI as reusable as possible; should I implement a third component à la project_controlling
that provides interaction between GUI and logic (user input validation done by controlling) in that each of the two remain as independent as possible? GUI not including headers of logic, so to say, but including controlling headers?
The second point may sound a little bit weird, I admit; to put it short, my aims are:
project_logic
standard C++
and independent (in terms of patching, adding functionality, etc...) andQt
for GUI at maximum (at the same time reasonable) separation of GUI and logic.Should I include the project_logic
headers via #include "../project_logic/header1.h"
etc? (There may be a problem with using the classes, which I will post in a separate question.)
Should I include them as a subproject?
How would I connect the parts "in code"?
Do the logic functions still find the files I mentioned earlier (read/write)?
Please keep the following in mind: I'm new to GUI programming! And I gave my best to explain my thoughts/problems... However, I know C and C++ and write console applications which I use for e.g. simulations at university and can handle the standard stuff quite well, I reckon. Even if the potential answerer feels like suggesting a very different approach, I would appreciate a "solution" for the concept I proposed. The reason for that I explained in the introduction. Unnecessary to mention though that I am of course interested in hearing different suggestions.
I decided to post the question after I did some research and tried my best in "trial & error" fashion before. There is a lot of information about this topic out there on StackOverflow and other boards, so I wanted to present my idea and collect criticism and inputs, rather than adding another "how to?" to the hodgepodge of questions.
Since this question is about the general approach, I will maybe (quite sure... :-P ) ask more technical questions later, which I would like to edit into this question (hyperlinks) as soon as they arise. However, basic recipes in this matter, if available, are welcomed, of course.
After some comments and answers I feel like posting a little EDIT just to make things clear:
project_logic
is more or less finished and coded in CodeBlocks as a CodeBlocks project.main.cpp
which is now only used for debugging.)project_gui
is being set up as a Qt-Widget-Application project (using QtCreator/Designer).project_logic
in any way).... the workflow, I want to follow, since this is my first big project:
project_logic
and project_gui
won't leave their respective directories; they both are in a directory called project
. (Exception: Logic will be exported as a dll (or something similar) if necessary, which is then provided to the GUI.)project_logic
I want to do so in CodeBlocks (and repeat a possible export as described above).project_logic
(or any third layer like for instance project_controlling
) have to be made disposable for project_gui
in the most easiest fashion imaginable... (see Trains of thoughts number 1) :-PTo use Qt, you must have a C++ compiler. But it doesn't mean that your "application logic" can't be written in C, compiled with a C compiler and carefully linked to the C++ part (the GUI with Qt). This application logic can be generic, linkable into other executables (pure-C, mixed C/C++, etc.)
In a software product there are two distinct modules whose responsibilities are well-defined and should be clearly demarcated. The model is a software representation of a solution to a known problem whereas the view allows the user to interact with the model to solve a specific problem.
Qt is used for developing graphical user interfaces (GUIs) and multi-platform applications that run on all major desktop platforms and most mobile or embedded platforms. Most GUI programs created with Qt have a native-looking interface, in which case Qt is classified as a widget toolkit.
when you have developed different parts of your application in different projects, the easiest way is to just link your main project with the libraries and use them. So in your case you should provide the dll for the project logic which is developed and compiled in CodeBlocks to your Qt project, link to it and use the classes.
For example you can put the header files of your library in a folder named Logic
and the debug and release versions of the .lib
files in relevant folders and link your application :
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/Logic/release/ -lLogic
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/Logic/debug/ -lLogic
INCLUDEPATH += $$PWD/Logic
DEPENDPATH += $$PWD/Logic
In this case using Subdirs
is a good idea to separate code modules from each other. This way you can have independent software modules which are reusable and able to be changed easily. It also makes the project much cleaner and easier to read.
In this approach the modules can interact with each other through signals and slots which makes different components completely independent and changing one module does not require changing other parts.
Qt Creator provides good automation in liking the parts to each other. You can make a Subdirs project and add your subprojects to its .pro file :
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
Component1 \
Component2 \
Component3 \
MainApp \
You should bring the subprojects that others depend on, first in the list. Also notice that the name of the .pro file of the subproject should be the same as it's folder name. This way the subprojects are detected and listed in the Projects pane.
The subprojects Component1
, Component2
and Component3
could be libraries. Part of .pro file for Component1
:
TARGET = Component1
TEMPLATE = lib
DEFINES += COMPONENT1_LIBRARY
SOURCES += ...
HEADERS += ...
The subproject MainApp
can be app. Part of .pro file for MainApp
:
TARGET = MainApp
TEMPLATE = app
You can use the libraries in each subproject by linking it to the subproject. This can be done by right clicking on the subproject and choosing "Add Library" and then "Internal Library". When you select one library from the list of subprojects, the linking configurations are added to the .pro automatically. It will be like :
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../Component1/release/ -lComponent1
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../Component1/debug/ -lComponent1
else:unix: LIBS += -L$$OUT_PWD/../Component1/ -lComponent1
INCLUDEPATH += $$PWD/../Component1
DEPENDPATH += $$PWD/../Component1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With