Currently I am writing a C++ Qt GUI standard (i.e. via Qt Creator) application.
Basically, what I am trying to do is an application, which operates the following singleton classes:
a MainWindow class, which is responsible for the core logic;
a ServerWindow class, which is responsible for the server connection;
a User class, which is returned (in form of a pointer) by the ServerWindow class after successfull authentication;
a Data class, which is initialized with the data, recieved via ServerWindow upon user authentication.
The algorithm is:
Construct a MainWindow and create a Data class; it also holds a pointer (nullptr at this step) at the current user.
When the constructor has finished, the ServerWindow (derived from QDialog) is executed (via Qt delayed connection). At this step the MainWindow is frozen and set invisible, untill the ServerWindow emits one of the signals (logged, fail). The ServerWindow has a modal mode flag set.
When the ServerWindow is done, a pointer to the current user is passed to the MainWindow. The ServerWindow also knows about the Data class and initializes it.
The main problem is that at step 2 the application icon in the taskbar (I use Windows OS) is not shown. When the MainWindow is "offline" (i.e., not shown, invisible via setVisibility(false)), there is no icon. It is highly annoying, especially if there is a bunch of other applications open. So that, my question is: what can I do to make ServerWindow create an application icon in the taskbar without MainWindow being shown?
The additional, by-the-way question is about possible application architecture remastering. I cannot find any books in my small library about similar applications designing. Frankly, I cannot even figure out, which words I should pass to the Google search line. Any advice?
Preliminary, thanks for any answers!
Related
I am developing an application to feed a database. My main window is basically a menu that opens forms for different utilities.
Not sure if it's the best practice but let me explain what I'm trying to do:
my class mainwindow has a private QString that will store the current project name. In the menu, "Load" opens the form (another class) that lists all the existing projects in a combobox. The user chooses the project he wants and clicks OK.
I would like to return the combobox.currentText() into the dedicated private variable. After some research I still cannot figure out how to make it, wether I should use SIGNAL from the form to trigger a SLOT of the mainform or if there is a simple way to just return a value after pressing OK (such as an input dialog). If i am not clear enough, maybe the following sketch could help.
I definitively have a lack of knowledge on the subject but would be grateful for some help.
Indeed if your form for loading a project would emit a signal currentProjectChanged as soon as the user accepts the form (presses the OK button), this signal could be connected to a slot of the main window. For simple things this may be fine and elegant.
On the other hand reacting on actions sometimes needs more logic. If your action triggers a slot that cares for action execution, this slot probably should implement the logic. It should open the form and check whether the user has accepted the project change (pressed OK). In this case the action execution slot could get the new project name from the form and call a main window method to pass the new project name.
I am creating a dialog based application, I found there are two components, which are dlg and app.
My question is, what is their different and if I want to write back end logic for the application, which file I should write to for better practice ?
My back end logic means:
e.g: creating an application receives input from two text boxes and sum them up
my back end logic means the function to sum up two variables.
The application (CWinApp) is the outer container, that contains all application specific stuff. The application object is a singleton.
The CMyDialog class carries out the UI and all actions belonging to one dialog.
Because an application may have more than one dialog class, you are not restricted to have only one dialog. But you always have only one application object.
So your logic should all be located in the dialog class.
The dialog and the application may exchange results and data. The normal logic is to copy the data from the application into member objects in the dialog. Launch the dialog. After the dialog is successfully executed the values are copied back.
I have Application A which is a third party Windows application (with GUI) that uses the Qt library.
I want to write Application B which will be responsible for starting Application A. I want Application B to also find buttons on Application B (QWidgets) and send them mouse inputs (click, double click etc).
I can run Application A through using the start function on a QProcess.
How do I do the following from my instance of the QProcess:
Get the top level window(s) for the process
Get a widget by name or (other identifiable attribute)
Get the widgets caption, colour and coordinates (and maybe some other data)
Send mouse move and click events to specific coordinates
Give a widget keyboard focus
Send keyboard key presses
Note - I know how to do this with the Windows API, but asking for a way via Qt. The specific Application A in question does not use the native windowing system, therefore window handles will not show up in Spy++ or Windows API functions.
Update 1 - Cannot seem to get any meaningful objects through the process's children
My attempt at getting child widgets for the process:
QProcess* process = new QProcess();
QString program = "\"C:\\Program Files (x86)\\foo\\bar.exe\"";
process->start(program);
auto widgets = process->findChildren<QWidget*>("", Qt::FindChildrenRecursively);
auto i = widgets.count();
// i = 0
If I find children of type <QObject*> I get 4 results. I used metaObject()->className() to see that I have two pairs of QWindowsPipeReader and QWinOverlappedIoNotifier objects.
Update 2 - Cannot create/inject window from another process
I noticed that when I run the QProcess I can use Windows API functions to get the top level window (top level only). I read in the Qt documentation that you can create a QWindow from the handle of a window in another process using QWindow::fromWinId.
Using this function will throw an 0xC0000005: Access violation reading location 0x00000000. error. I am not passing in a null handle. I am using reinterpret_cast to get the HWND to a WId type. It creates a QWindow only when I create a QApplication beforehand.
The new QWindow will have no children (using window->findChildren<QObject*>("", Qt::FindChildrenRecursively); I assume that the creation of the QWindow does not bring across associated child widgets.
Update 3 - I am currently reading into whether inter-process communication can be used
I have come across various threads, questions and code snippets regarding ICP in Qt. I don't see anything so far that specifically shows that ICP is possible when one of the processes is third party.
I have seen that the Squish Gui test tool lets you interrogate QWidget properties.
This will never work the way you intend it to.
If you really wish to take direct control over the other application, you must inject your code into that application. Let's assume that the application uses a dynamically linked Qt. Then:
Build a binary-compatible version of Qt, using the same compiler that was used to build the application you intend to tweak.
Replace the application's Qt with yours. Everything should still work fine, given that yours should be binary compatible. If not, the binary compatibility isn't there, and you must tweak things until they work.
Edit your Qt to add a hook to initialize your code at the end of QApplication constructor. This makes the Qt module that provides QApplication dependent on your code.
Put your code into a dll that the widgets (for Qt 5) or gui (for Qt 4) module is now dependent on.
Again replace the app's Qt with yours, with hooks that start your code.
Your code will of course need to be asynchronous, and will be monitoring the application's progress by inspecting the qApp->activeWindow(), qApp->allWidgets(), etc.
That's pretty much the only way to do it. You can of course inject your code in any other way you desire, but you will need to work with a binary-compatible version of Qt just to compile your code. Note that binary compatibility encompasses more than merely using the same compiler version and Qt version. Many of the configure switches must be the same, too.
I'm working on a tool, on the main window of the tool there are few Qt widgets added on it.
When we used to RMB click on the Qt widget, a context menu pops up (and via eventFilter few functions have been called) to do the required work- say, doTask() slot gets called up with the receiver object.
Now I have to add a banner menu on the window, which has to copy all the features of RMB context menu.
Since this banner menu is not of Qt, but written in some internal functions (say, LISP) I have problems in calling that slot function - doTask(), as I don't know what is the receiver object.
How can I communicate with a Qt widget through some external command/language?
Please add comment if anything is not clear in this.
Can you not expose a simple C style method from a QT aware object that acts as a proxy for the slot calls. ie Your banner calls method, method then calls appropriate slots?
Your basic problem is just knowing the receiver object. Once you do, you can call its slot directly (doesn't need to go through a signal).
The menu knows this, because it keeps a pointer to the receiver object. Your own banner menu must do the same. "It doesn't know the receiver object" must therefore be fixed.
I am creating a GUI to manipulate a robot arm. The location of the arm can be described by 6 floats (describing the positions of the various arm joints.
The interface consists of a QGraphicsView with a diagram of the arm (which can be clicked to change the arm position - adjusting the 6 floats). The interface also has 6 lineEdit boxes, to also adjust those values separately.
When the graphics view is clicked, and when the line edit boxes are changed, I'd like the line edit boxes / graphics view to stay in synchronisation.
This brings me to confusion about how to store the 6 floats, and trigger events when they're updated. My current idea is this:
The robot arm's location should be represented by a class, RobotArmLocation. Objects of this class then have methods such as obj.ShoulderRotation() and obj.SetShoulderRotation().
The MainWindow has a single instance of RobotArmLocation.
Next is the bit I'm more confused about, how to join everything up. I am thinking:
The MainWindow has a ArmLocationChanged slot. This is signalled whenever the location object is changed.
The diagram class will have a SetRobotArmLocation(RobotArmLocation &loc). When the diagram is changed, it's free to change the location object, and fire a signal to the ArmLocationChanged slot.
Likewise, changing any of the text boxes will fire a signal to that ArmLocationChanged slot. The slot then has code to synchronise all the elements.
This kind of seems like a mess to me, does anyone have any other suggestions? I've also thought of the following, does it have any merrit?
The RobotArmLocation class has a ValueChanged slot, the diagram and textboxes can use that directly, and bypass the MainWindow directly (seems cleaner?)
thanks for any wisdom!
Except for really simple cases (e.g. a label that shows the value of a slider) my experience has been to stay away from inter-component signal/slot connections inside Qt Designer. Rather, have the component firing the signal of interest connect to a slog defined in the top level QWidget class you're subclassing (i.e. QMainWidow, etc... let's just call it the Form class). You can also go the other way: if you have a custom signal in the Form class, you can connect it with Qt Designer to one of the public widget slots.
To be specific using your example:
I'm going to assume that you have subclassed QMainWindow and QGraphicsView. Let's call the subclasses RobotMainWindow and RobotView.
RobotMainWindow contains the QLineEdit fields and RobotView. The way you specify RobotView in Qt Designer is to insert a QWidget and use the Promote to... feature to tell Qt that the QWidget should be replaced at compile time with your custom RobotView.
Name the QLineEdit fields edit1, edit2...edit6.
In the Qt Designer signal/slot editor define slots in RobotMainWindow to be called when the value in a QLineEdit changes. There are some more elegant ways of doing this, but for simplicity let's say you define 6 slots named setValue1(float), setValue2(float), etc.
In the source code for RobotMainWindow, go declare and define these slots, such that they update your arm, shoulder, whatever.
Also in the source code, define a signal valueChanged() (or multiple for each field, your choice). Have the slots you defined emit valueChanged().
Back in Qt Designer you can now link the appropriate signal from each QLineEdit to the corresponding slot in RobotMainWindow.
Back in the signal/slot editor add the valueChanged() signal to the RobotMainWindow (so Qt Designer knows about it). Connect this signal to a new slot in RobotView, using the procedure above, so it can update the rendering.
Repeat all of this for handling changes from RobotView to the editing fields (via RobotMainWindow.
In short, I think you'll find everything more straight-forward if your route the signals through your Form subclass (which I think of as the Controller in MVC parlance).