0

I have a QGraphicsView subclass where, on context menu on an item, I want to show a Properties dialog.

I would like the dialog to be centered in the view...

As I have it now, with no parent, it is shown in the center of the screen.

MyView::MyView(QWidget *parent) : QGraphicsView(parent) {}

void MyView::showProperties()
{
    TabDialog *tabDialog = new TabDialog();  // shows in center of screen
//    TabDialog *tabDialog = new TabDialog(this); // doesn't show at all
//    TabDialog *tabDialog = new TabDialog((QWidget*)this->parent()); // doesn't show at all
    tabDialog->setWindowFlags(Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint);
    tabDialog->exec();
    delete tabDialog;
}

The view is placed in a groupbox... so the parent is the groupbox...

How can I call the dialog using a parent ?

Thalia
  • 13,637
  • 22
  • 96
  • 190

1 Answers1

0

You have to set the dialog to be a top-level window, not simply a child widget that would be embedded in your view. Your setWindowsFlags call resets the relevant flags from the dialog. You need to manually preserve them.

You also should never use exec() to reenter the event loop since this requires that a lot of your other code needs to be reentrant as well.

A minimal fix would look like:

void MyView::showProperties()
{
  auto dialog = new TabDialog(this);
  dialog->setWindowFlags(Qt::Dialog | 
                         Qt::WindowCloseButtonHint | 
                         Qt::WindowSystemMenuHint);
  dialog->setAttribute(Qt::WA_DeleteOnClose);
  dialog->show();
}

Perhaps you'd want to cache the dialog:

class MyView : public ... {
  QPointer<TabDialog> m_tabDialog; // nulls itself when the dialog perishes
  QTimer m_tabDialogTimer;
  ...
};

MyView::MyView(...) {
  m_tabDialogTimer->setSingleShot(true);
  ...
}    

void MyView::showProperties() {
  if (! m_tabDialog) {
    m_tabDialog = new TabDialog(this);
    m_tabDialog->setWindowFlags(Qt::Dialog | 
                                Qt::WindowCloseButtonHint | 
                                Qt::WindowSystemMenuHint);
    QObject::connect(&m_tabDialogTimer, &QTimer::timeout, 
                     m_tabDialog, &QObject::deleteLater);
    QObject::connect(m_tabDialog, &QDialog::finished, [&this](int){
      // the dialog gets deleted 120 seconds after last use
      m_tabDialogTimer.start(120);
    });
  }
  m_tabDialogTimer.stop(); // reset pending timeout, if any
  m_tabDialog->show();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • With this change, my window will still show in the center of the window, not above the QGraphicsView. – Thalia Jun 30 '15 at 18:08
  • @Thalia That's the expected behavior. If you wish to show it exactly centered over a sub-widget of a top-level window, as I now presume you are, you need to do the positioning manually. Note, though, that modal dialogs behave differently on different platforms, so your positioning choices may be out of place or ignored. For example, on Mac, modal dialogs display as sheets dropping from the title bar of the window - so it doesn't matter that you wish to position it somewhere else, it simply would not look right for the platform, and by default your positioning choice is ignored. – Kuba hasn't forgotten Monica Jun 30 '15 at 18:12
  • @Thalia Manual positioning of the dialog is not trivial, unless the dialog has a fixed size, since the dialog's size is unknown until it is shown, so you'd need to activate your positioning code once the event loop has processed all events related to the dialog's visibility change. The exact behavior here will be very platform-dependent, I'm afraid, so it's questionable whether this makes much sense to attempt. You'd definitely want to test it on all of the platforms you are targeting. – Kuba hasn't forgotten Monica Jun 30 '15 at 18:16
  • Thanks for the Mac example - I never noticed it (not much osx experience but I do want multi-platform behavior). Still I expected if a widget has a parent, to be placed above the parent - without my having to move it manually. I guess the answer to my question is that is not impossible - but not advisable to do what I want either :-) – Thalia Jun 30 '15 at 18:18