Qt - minimizing and maximizing app without standard titlebar buttons - c++

I have a Qt application where there is only one widget which is not a MainWindow, just a QLabel. It has not title bar (obtained through setWindowFlags(Qt::FramelessWindowHint)), thus the standard minimize and maximize buttons are not available. But there is a sidebar at the widget's side where we provide a minimize button that should behave as the standard minimize button.
How do I do it?
I tried the solutions at Minimizing a Qt application and Qt C++ minimize and maximize window. Neither works. I can hide the app of course, on clicking the minimize button. Problem is, how to restore it through standard mechanisms?
Scenarios:
On Mac, the dock icon is clicked. Thankfully, OS X native APIs can give me a notification when dock icon is clicked, so based on that, I can unhide the widget and make it active.
On Mac, the app icon is double clicked in /Applications, or clicked in Launchpad. How do I get a notification for this? The code doesn't even come to the main.cpp that I can unhide it from there if it is hidden.
On Windows, the application icon in the taskbar is clicked (the app does not have a tray icon). How do I get notification for that and unhide it?
On Windows, the app icon is double clicked either in Program Files, or may be a desktop shortcut icon. How do I get notification for this to unhide it?
If this aproach is not correct, how do I show and hide the app as per standard behavior on both Mac and Windows?
Platform - Qt 5.3.1, 32 bit.

This is not an answer, but it might help sorting out which events are triggered (points 1,2 and 3).
#include <QApplication>
class newapp : public QApplication {
Q_OBJECT
public:
newapp( int &argc, char **argv ) : QApplication(argc, argv) {}
protected:
bool event(QEvent *ev) {
std::cerr << "APPLICATION EVENT " << ev->type() << std::endl;
return QApplication::event(ev);
}
};
and in your main.cc you will have
newapp myapp(argc,argv);
instead of
QApplication myapp(argc,argv)
Once you identify the events triggered, you're almost done: you need to tell to you newapp to restore the size of the Qlabel (there are tons of ways to do this, so provide your implementation and you might get more focused help)
For point 4, it's something else due to the different behavior between OSes as in Windows double clicking for the second time an app, will launch another instance of the application (on OSx it will raise the first opened app). You might find something that suit you in this project HERE

Related

Linux Qt QSystemTrayIcon in console application

I have a working qt application. It is not a MainWindow application and has no GUI elements at all so far. It runs on startup of the linux box (as a background service). However, it has to wait for ~40-60 seconds until it can start while the IP/DHCP sorts its self out.
So I wanted to give the user some feedback as to what is going on. I thought it might be nice to add a system tray icon to look a little bit more professional then a terminal (though I could just do that).
However, after reading the documentation on QSystemTrayIcon I am still not sure if I have to use it as part of a MainWindow style application (i.e. do I need to add main window and make the sys tray a part of that), or can I just run it within my "console" style app?
i created a console application with system tray myself for win7 so i have no info about linux clients. it does not display any console, it only uses logging for output and the systemtray to display 'user readable content'.
your application need to use QApplication instead of QCoreApplication in order to draw widgets and create the QSystemTrayIcon to display the system tray icon. now just fill the menu as you please.
the code in main.cpp might look like this:
int main(int ac, char** av){
QApplication a(ac, av);
QSystemTrayIcon i;
QMenu* m = i.contextMenu();
m->addAction(tr("hello world!"));
i.show();
return a.exec();
}
cheers

Access native QFileDialog

I'm writing a ui test for a Qt application. Now this application raises a QFileDialog which must be automatically filled in and committed.
I already have a QTimer which runs even when the modal dialog is shown. This approach works for many dialogs e.g. QMessageBox or QColorDialog.
The Problem is, that the QFileDialog is a native dialog. So I can't search for the dialog widget, because there is none.
Is there a way to access the native dialog.
I'm developing on Ubuntu so I guess it's a GTK dialog. The tests will always run on Ubuntu.
Depending on your needs you could just set QFileDialog::DontUseNativeDialog to true using void QFileDialog::setOption(Option option, bool on = true) before you show the dialog. Then you should have a widget to search for.
See: http://doc.qt.io/qt-5/qfiledialog.html#setOption

wxFrame and wxTaskBarIcon taskbar event Mac OSX : callback not being triggered

I have a derived class for wxFrame (MyFrame) (for OSX - Yosemite platform), where it calls:
Bind(wxEVT_TASKBAR_RIGHT_DOWN), &HandleTaskBarEvent, this);
The issue is HandleTaskBarEvent is not being invoked when I right click the icon in the dock.
I see the generic right click menu that Mac has (Open at Login, Keep in Dock, etc) for the main icon in the dock.
Also, I created a wxTaskBarIcon. I am guessing this will be utilized for the minimized icon in the dock after the frame is minimized.
systemIcon = new wxTaskBarIcon(); //declared in header
systemIcon.Bind(wxEVT_TASKBAR_RIGHT_DOWN, &HandleTaskBarEvent, this);
Popup = new wxMenu(); //declared in header
QuitMenu = new wxMenuItem(Popup, wxID_ANY, wxString(wxT("Quit")), wxEmptyString, wxITEM_NORMAL); //declared in header
Popup->Append(QuitMenu)
Popup->Bind(wxEVT_COMMAND_MENU_SELECTED, &CloseFunc, this, QuitMenu->GetId());
This is inside the same derived class(MyFrame).
I call Iconize() inside that MyFrame same function, which works as expected. It minimized the window.
This is the HandleTaskBarEvent function (virtual)
void MyFrame::HandleTaskBarEvent(wxTaskBarIconEvent& event)
{
if(event.GetEventType() == wxEVT_TASKBAR_RIGHT_DOWN)
{
systemIcon->PopupMenu(Popup);
}
}
I saw this post : Mouse Events of WxPython TaskBarIcon on Mac OSX are not triggering
and there seems to be a bug about it. But I am not able to find that bug or its status online. It is mentioned that the issue is with wxPython, but seems related to my problem.
Also I created a derived class for wxTaskBarIcon and overrode CreatePopupMenu and made systemIcon as an instance of MyTaskBarIcon, but that function is not being triggered for any clicks(left,right, etc). Also the main wxFrame 's Bind callback (HandleTaskBarEvent) is not being triggered, hence the systemIcon is not being able to popup the menu.
I am not using mouse for my Mac (using trackpad instead). Not sure if it should make any difference to right click code, but adding the information here anyways.
So I am thinking this could be wxWidget-OSX specific issue, because the code works on Windows as expected.
Does anyone know if this is purely wxWidget-OSX incomplete feature, if there is any open bugs about it, and more importantly if there is any solution to show the popup menu items for the minimized icon in the dock, and to handle the click events for the menu.
Thanks in advance.
This is a limitation of the OS X wxTaskBarIcon implementation. See wxTaskBarIcon on OSX - two-finger click does not send mouse event and related/linked issues.
The only way I know of (on OS X) is overriding wxTaskBarIcon::CreatePopupMenu().
You should be able to have something like:
MyApp::wxApp/
MyTaskBarIcon::wxTaskBarIcon (override CreatePopupMenu(), return a new wxMenu)
This is the model I use in a few applications and it works the same on Windows and OS X (albeit no specific click handlers as mentioned).

Modal QMessageBox does not behave like native Windows dialogs

My application has a dialog that asks the user via a QMessageBox whether he wants to discard all changes he made or wants to keep editing. I want this dialog to be modal to the whole application.
I read somewhere that this is the standard behavior for a QMessageBox, so I dont have to set it explicitly with something like:
mbox.setWindowModality(Qt::ApplicationModal);
I wonder why it behaves differently from other modal dialogs in the OS (Windows 7 in my case). On the one hand it functions like it should, i.e. all other input methods in the application are blocked until the user answeres the dialog. However, it doesn't 'blink'* if the user clicks any other window of the application. Is there any way to get Qt to behave like a native Windows dialog?
Thanks in advance!
*If you don't know what I mean with this 'blinking': Just open notepad on a Windows OS, type some text and try to close it. A dialog pops up that asks to save, discard or keep editing. Now click somewhere on the editor window -> the border and titlebar of the dialog flashes/blinks a few times.
The problem arises when the message box has no parent. This works fine for me:
QMessageBox box(this);
box.setStandardButtons(QMessageBox::Close);
box.exec();
But this does not:
QMessageBox box;
box.setStandardButtons(QMessageBox::Close);
box.exec();
This makes sense... the message box can't blink unless it knows that its parent was clicked on.
A simple solution that comes into my mind and if you want to deploy your application only on windows you should #include <windows.h> and use the MessageBoxA API.
Besides that this works great for me in Windows and ubuntu
if (QMessageBox::question(this,"Close?","Close this dialog?",QMessageBox::Yes,QMessageBox::No) == QMessageBox::Yes)
{
this->close();
}

HowTo correctly close QDialog when main windows is hidden?

I have some kind of dilemma.
I'm using:
MSVS 2008
Qt 4.7.3 (with Qt VS Add-in 1.1.9)
I wrote small Qt application, base on QMainWindow class, where also exists settings dialog (QDialog). Every works fine in GUI mode. After that I started to change my project to make it visible only in tray. Just comment in main.cpp show() method, like this:
MainWindow w;
//w.show();
return app.exec();
But from tray, I need to launch settings dialog, which is implemented in mainwindow.h/.cpp files. I added to tray menu action (QAction) which is starts that settings dialog. And here comes the unexpected problem: when I tried to close this settings dialog with [ X ] close button (in top right corner) my app closed!
Here is the action slot:
void MainWindow::onOpenSettingsDlgClicked()
{
SettingsDlg dlg( this );
dlg.exec();
}
I have tried to reimplement virtual reject() method for the settings dialog class, and set there only hide() function, but that solution not helped.
What I'm doing wrong?
Thanks you!
You should turn off the quitOnLastWindowClosed property which is turned on by default as defined in the doc (http://doc.qt.nokia.com/latest/qapplication.html#quitOnLastWindowClosed-prop)
This said, you'll have to handle the termination of your QApplication yourself, maybe with an [quit] entry in the tray menu.
Just found another option which seems better is to override closeEvent of the QDialog to only hide it.
void PrefDialog::closeEvent(QCloseEvent *event) {
this->hide();
event->ignore();
}
I found this seems better because it doesn't change the global application behaviour.