How to disable minimizing by taskbar icon click - c++

I've stumbled across very strange behaviour during work on my program.
I've written custom changeEvent class, which allows me to hide program to SysTray on minimizing.
But when i double click on taskbar app icon, the function goes crazy. It creates 2 to 4 systray icons and on requesting window show again, it just shows main window borders without any content inside.
Here's my changeEvent code:
void MainWindow::changeEvent(QEvent *e) {
QMainWindow::changeEvent(e);
if(e->type()==QEvent::WindowStateChange)
if(isMinimized()) {
trayIcon=new QSystemTrayIcon(QIcon(":/icon/itime.ico"));
connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(on_show(QSystemTrayIcon::ActivationReason)));
QAction *showAction=new QAction("Pokaż",trayIcon);
connect(showAction,SIGNAL(triggered()),this,SLOT(on_show()));
QMenu *trayIconMenu=new QMenu;
trayIconMenu->addAction(showAction);
trayIcon->setContextMenu(trayIconMenu);
trayIcon->show();
this->hide();
}
}
on_show(QSystemTrayIcon::ActivatioReason) SLOT:
void MainWindow::on_show(QSystemTrayIcon::ActivationReason reason) {
if(reason) {
if(reason!=QSystemTrayIcon::DoubleClick)
return;
}
if(this->isMinimized()) {
this->raise();
this->showNormal();
this->setWindowState(Qt::WindowActive);
trayIcon->hide();
}
}
on_show() SLOT is just the same besides that first if.
Soo, I would like to know whether there is any way to disable minimizing of window by taskbar icon click.
If there's none, then maybe you have any ideas what can go wrong in here when doubleclicking on icon in taskbar?
Thanks for help!

I've managed to work around that problem by overloading closeEvent function and leaving alone changeEvent function.
So, I'm using boolean flag to distinct between closing of program by menu item and by clicking "X" button and the rest stays just the same, as posted in my earlier post with one change.
I've moved this whole block of code to window constructor in order to prevent multiple creation of trayIcon, as pointed out by Nicolas.
trayIcon=new QSystemTrayIcon(QIcon(":/icon/itime.ico"));
connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(on_show(QSystemTrayIcon::ActivationReason)));
QAction *showAction=new QAction("Pokaż",trayIcon);
connect(showAction,SIGNAL(triggered()),this,SLOT(on_show()));
QMenu *trayIconMenu=new QMenu;
trayIconMenu->addAction(showAction);
trayIcon->setContextMenu(trayIconMenu);
Thanks for your help!

Related

Call button click function from grandchild

I'm creating my first C++ wxWidgets application. I'm trying to create some kind of split button where the options are displayed in a grid. I have a custom button class which, when right-clicked on, opens a custom wxPopupTransientWindow that contains other buttons.
When I click on the buttons in the popup, I want to simulate a left click on the main button. I'm trying to achieve this through events, but I'm kinda confused.
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxWindow* mBtn = this->GetGrandParent();
mBtn->SetLabel(this->GetLabel());
mBtn->Refresh();
wxCommandEvent event(wxEVT_BUTTON);
event.SetId(GetId());
event.SetEventObject(mBtn);
mBtn-> //make it process the event somehow?
wxPopupTransientWindow* popup = wxDynamicCast(this->GetParent(), wxPopupTransientWindow);
popup->Dismiss();
}
}
What is the best way to do this?
You should do mBtn->ProcessWindowEvent() which is a shorter synonym for mBtn->GetEventHandler()->ProcessEvent() already mentioned in the comments.
Note that, generally speaking, you're not supposed to create wxEVT_BUTTON events from your own code. In this particular case and with current (and all past) version(s) of wxWidgets it will work, but a cleaner, and guaranteed to also work with the future versions, solution would be define your own custom event and generate it instead.

myComboBox->Dismiss(); not working under wxEVT_TEXT and wxEVT_COMBOBOX_DROPDOWN

My objective:
During wxEVT_COMBOBOX_DROPDOWN load up a choiceDialog and set the choice as combo box value and finally close the combobox using dismiss().
What I tried:
void Class_Scheduler_FNFrame::myComboBoxDropdown(wxCommandEvent& event)
{
SingleChoiceDialog1->ShowModal();
int i = SingleChoiceDialog1->GetSelection();
myComboBox->SetValue(wxString::Format(("%s"), myWxStringArray[i]));
myComboBox->Dismiss();
}
The value got changed but the dismiss(); is not working.
So I tried moving dismiss to wxEVT_TEXT.
void Class_Scheduler_FNFrame::myComboBoxTextUpdated(wxCommandEvent& event)
{
testLabel->SetLabel("This should have worked");
myComboBox->Dismiss();
}
Dismiss() is not working in wxEVT_TEXT as well. But when I type onto the combobox, after triggering wxEVT_COMBOBOX_DROPDOWN, dismiss() is working through wxEVT_TEXT .
Help!
You're trying to do something rather weird: have you ever seen a modal dialog show while the combobox dropdown is opened? I haven't and, generally speaking, there should be only a single modal element shown at each moment.
So why do you have this objective? What is the point of showing the dialog whenever a combobox is opened? It doesn't even seem like you're using it like a combobox at all. Maybe you're actually after some kind of wxFilePickerCtrl-like behaviour, i.e. a small button showing the dialog near a text control? Or maybe you want to use wxComboCtrl instead?
Anyhow, it should be possible to do what you want by postponing showing the dialog using CallAfter(), but I'm almost sure that you actually don't want to do that anyhow.

Qt: button - going back from "help.cpp" to "mainwindow.cpp"

I'm new at Qt. I've created small application and I created second page help.cpp. On MainWindow.cpp I have a button, that switches to help.cpp page.
Function which switches to "help" page:
void MainWindow::on_box1button_clicked()
{
helpwindow = new help(this);
helpwindow->show();
}
This code works properly.
On the "help" page I've got a QButton, which will switch back to mainwindow.cpp. How Can I code that button to actually make this action?
If your intention by "switching" is hiding one window and showing another one, so you can simply pass a reference of the main window to your help window and there when you want to switch back, you can hide/close itself and show the main window.
MainWindow (this code is fine)
helpwindow = new help(this);
helpwindow->show();
HelpWindow
When you want to switch back to the main window, you can do this:
// Hide the HelpWindow itself
// or this->close()
this->hide()
// Show the MainWindow (i.e. the parent window)
QWidget *parent = this->parentWidget();
parent->show();
Since you are creating a new help(this); on mainwindow it is better to close the help window
Use
this->close();

QSystemTrayIcon handle left and right click separately?

I have a class called StatusIcon that extends QSystemTrayIcon. I want to set it up so right click opens the context menu and left click opens a window.
Currently the default behaviour seems to be both left and right click open the context menu.
I need to find a way to block the left click and run my own code instead.
From the documentation it looks like this could be achieved using eventFilter I have setup an eventFilter method on StatusIcon with a qdebug in it. This doesn't get called with a right or left click.
I installed it using a line of code like:
this->installEventFilter(this)
I'm wondering if its not working as its already overriding the virtual method as I've got QSystemTrayIcon as the super class.
Does anyone know why eventFilter is not being called?
Could anyone think of a way to achieve this functionality?
You don't need eventFilter. For left click:
//somewhere in constructor
connect(tray,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(showHide(QSystemTrayIcon::ActivationReason)));
//...
void MainWindow::showHide(QSystemTrayIcon::ActivationReason r)
{
if (r == QSystemTrayIcon::Trigger)
{
if (!this->isVisible()) {
this->show();
} else {
this->hide();
}
}
}
For menu, just use setContextMenu():
QMenu *menu = new QMenu(this);
//for example
menu->addAction(showHideAct);
menu->addAction(optionAct);
menu->addAction(infoAct);
menu->addSeparator();
menu->addAction(quitAct);
tray = new QSystemTrayIcon();
tray->setIcon(QIcon("://data/tray.png"));
tray->setContextMenu(menu);//important method for you
tray->show();

wxWidgets - modeless wxDialog

I am creating my own subclass of wxDialog and it works well when used as a modeless dialog like so:
AddDialog newAddDialog = new AddDialog(this, wxID_ANY, _T("Dialog Title"), wxDefaultPosition, wxDefaultSize, 0);
if (newAddDialog.ShowModal() == wxID_OK)
{
//do something
}
When using ShowModal(), the flow of the program stops until OK or Cancel is pressed. I need the dialog to show up, but not stop the flow of the GUI, so I tried this:
AddDialog newAddDialog = new AddDialog(this, wxID_ANY, _T("Dialog Title"), wxDefaultPosition, wxDefaultSize, 0);
if (newAddDialog.Showl() == wxID_OK)
{
//do something
}
When using Show(), the dialog briefly shows up and then disappears. I thought it might be a scope issue, so I used a pointer for newAddDialog. Then, the dialog shows up, when when I click OK or Cancel, the dialog closes, but the if statement code does not execute even if OK is clicked.
Does anyone know how to proceed? Thanks.
Further clarification:
I have virtual void function in my Dialog subclass that I overide in another class. I can't seem to get the event working when I overide, however, if I have a void in the actual Dialog subclass, I get the event call. This seems to be an overide problem, but I don't know what the problem would be. This is not the main GUI that I'm calling in the OnInit() call - could that be a problem?
ShowModal blocks execution of your program and returns the outcome (like wxID_OK). On the other hand, Show just shows the dialog and returns immediately, so you can't check the outcome (what the user pressed for buttons) from it's return value. Instead you have to communicate the outcome of that dialog-box by sending an event from withing the dialog or something like that.
AddDialog newAddDialog = new AddDialog(...
Does this compile? Really?
The 'new' operator returns a pointer to void, so the code you have posted looks very odd indeed.
The usual way of doing this is:
AddDialog * newAddDialog = (AddDialog *) new AddDialog( ...
Or
AddDialog newAddDialog( ...