Klaim
Klaim

Reputation: 69752

Qt : Can a QMdiSubWindow be moved outside a QMdiArea and QMainWindow?

I'm writting some kind of editor and I'd like to allow the user to move freely windows inside an MdiArea AND allow them to move the windows out of the MdiArea, out of the main window of the application.

How should I do to achieve this?

Upvotes: 4

Views: 4264

Answers (2)

Klaim
Klaim

Reputation: 69752

I managed to find a simple solution that works with Qt. It's not perfect as I didn't implement drag'n'drop but I guess it can be done too with a system similar to Visual Studio 2010 windows docking.

Here is the setup :

  1. Make your widget class that is the content of the window -let's call it the document widget- inherit from something else than QDockWidget or QMdiSubWindow.
  2. Now the document widget needs to own (create, keep and destroy) a QDockWidget, that will be the outside window, and a QMdiSubWindow, that will be the inside window. They need to be hidden both.
  3. Assuming your main window have a QMdiArea in it's center, you'll have to add special code to register the inside window of your document in the QMdiArea.
  4. Add a button somewhere (in the windows title bars or in the document widget) that trigger switching from the inside window to the outside window.
  5. If we push that button and the document widget is in the inside window, we hide the inside window and then unregister the document widget from it. Then we register the document window int the outside window and show it.
  6. To do the reverse, just do 5 with switching the outside and inside window.
  7. you might have to add some special code to remove the document (meaning hide all windows and then unregister the inside window from the QMdiArea).

That way, the document widget will jump from a window inside the main window to a window outiside it without any problem, just by pushing a button.


I'm implementing this solution in an open source project. Once done and public I'll put links here.

edit: I've but my WIP FreeWindowManager.hpp implementation there (check the associated classes): https://code.google.com/archive/p/mjklaim-freewindows/source/default/source?page=2

Upvotes: 6

j_kubik
j_kubik

Reputation: 6181

Firstly, I want to say that such behavior should be avoided as it will be confusing to user. There are other methods of achieving such behavior (eg. toolbars).

I think you need to think about logic of your problem - dragging window out causes "unpinning" your window from main window, therefore your mdi child becomes regular toplevel window. Then draging it around should cause pinnig back at some point. You should define when exactly this unpinning and pinnng back should occur - when mdi chidld reaches edge of mdi area? or perhaps when cursor leaves mdi area while still dragging? Exact answer will be dependent on answer to this question.

One way of another, most likely you will need to create QMdiSubWindow descendant and reimplement QMdiSubWindow::moveEvent to check if "unpinnig" move was performed, and if so, call setParent(0) on widget embedded in QMdiSubWindow. Then your widget should also reimplement moveEvent for checking if it should be pinned back (if it already isn't that is) and creating new instance of your QMdiSubWindow descendant (if you delete'd it on unpinning), or use setWidget on stored copy of your QMdiSubWindow descendant (if you haven't delete'd it on unpinning).

Upvotes: 0

Related Questions