Tag: QWidget

Non closable QDialog

This is quite beginner post but I believe it’s good to share what we learn through experience with the people that are starting. In this entry I’ll show you how to have a UI non closable QDialog but that it can be close from the code.

In GitQlient I’m using this dialog to inform the user that the repository is being loaded. There is some data I’m loading in the cache/background (branches, tags, etc) that can take a bit if the repository is massive. In my case, I’m working with some repos that are quite big (~10 Gb only text files) and old. People usually forget to remove their branches and right know I can see around 2000 branches and close to 500 tags. In that case an async load is needed so the user has to wait.

How to do a non closable QDialog?

We want to prevent the user to close the dialog in all it’s forms:

  • Disabling the window close icon.
  • Disabling the Esc key that in QDialog closes/cancels the dialog.

Acting on the windows title

The way to do that is quite simple. In the first place we hide the close button:

setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint);

This will make the close button gone and keep the resize behaviour and dialog title. If you want a dialog only for the text you can do:

setWindowFlags(Qt::FramelessWindowHint);

That will remove the title bar and all it’s components.

Method 1: Acting on the Esc key event

QDialog process the Esc key as close/cancel. Since we don’t want that the user closes our dialog, we need to take care of that behaviour. To do that we need to capture the key press event and avoid processing it:

void WaitingDlg::keyPressEvent(QKeyEvent *e)
{
   if (e->key() == Qt::Key_Escape)
      return;

   QDialog::keyPressEvent(e);
}

The code is quite simple, we check the pressed key and if it’s the one we’re expecting, we don’t process the event.

Additionally, it’s also useful to have full control of another event: the closeEvent. That method plus a custom close method will give us the full behaviour:

void WaitingDlg::closeEvent(QCloseEvent *e)
{
   if (!mPrepareToClose)
      e->ignore();
   else
      QDialog::closeEvent(e);
}

void WaitingDlg::close()
{
   mPrepareToClose = true;

   QDialog::close();
}

In this code I’m using a class member to store when I do want to close the dialog, preventing the dialog to close if it wasn’t me how said it. The result is that this dialog can only be close by calling the close() method.

Method 2: Override reject method

Suggested in the comments by NickD2039 another possibility is to override the reject method, that would prevent the end user from closing the dialog. The code posted has a closeNow method that acts in a similar way to the method 1, it activates a control variable that finall calls accept.

I kind of like a bit more this code, since it’s a bit more elegant and requires you to write less code:

void closeNow()
{
   mPrepareToClose = true;
   accept();
   mPrepareToClose = false;
}

void accept()
{
   if (mPrepareToClose)
      QDialog::accept();
}

void reject()
{
   if (mPrepareToClose)
      QDialog::reject();
}

Where to find the source coude?

You can find the source code for the non closable dialog in my GitHub repository for Qt tips. Please noticed that I name it WaitingDlg since I did the code for GitQlient and that was its purpose.

Customization of a QCompleter

Time ago I had the task to create a QComboBox and a QLineEdit that open a completer so the user can select between all the suggested options. So far it seems a quite easy task by using the QCompleter that Qt provides.

The interesting part starts when I had to add customized styles for both the QComboBox and the QLineEdit, and make them match with the styles that I also had to add to the QCompleter. In addition I had a language constraint that initially I didn’t take into account but it impacted the performance of the widget. That’s the default filter implemented in QCompleter.

(more…)

CustomWindow in Qt (create your own QWindow)

Brief introduction

I’ve seen several questions in the Qt Forum about how to customize or create our CustomWindow predefined window title buttons or the styles of it. First of all is necessary to explain that this is not a trivial issue since the OS API defines these controls and styles.

In the case of Windows, the title bar is created by Windows Manager so it is impossible to modify it. If we want a personalized title bar or modify the styles of the border of the window or whatever, it is necessary to remove it and then, create our custom QWidget with our own title bar. Before we start to write our own custom QWindow we need to understand that is not an easy task. Our QWidget must fulfill the following requirements:

  • Catch some mouse events: press, release, move… In order to know where to move or how to resize the window.
  • Implement the top-right buttons behavior: close, minimize, maximize, restore…
  • Manage the include of the central widget that will has the main functionality.
  • We could want to add a top-left menu and the title of the window. It is necessary to implement too.
  • The good things that provide us a custom title bar is the possibility to add new buttons with extended functionality, customize the top-left menu with our own options and definitely, to have our application window style unified.

The best way to learn Qt goes trough code, code & code. In this case, create our custom window title and all the functionality it involves is a good way to learn the Qt window management.

(more…)