Repopulate window with new layout - c++

I'm building a Qt (C++ with QML) app that I wish to deploy across
multiple platforms, including desktop and mobile.
I've run into a difficulty in that I haven't found any way to (possibly
simulate) replacing the contents of the current (and only) application
window on an action (say a button press).
Note that I don't want to create a new window, I simply wish to change
the widgets shown in the current window.
For reference, a QML stub for the main window is shown below
ApplicationWindow {
id: appWindow
---
---
toolBar: ToolBar { // Should be replaced on button click (eg: new)
---
---
}
ListView { // I need a way to replace this with a new sub-window
id: listView
model: myModel
---
---
}
}

You can use a StackView component as well as a Loader for that.
The former is a good way to let the user move within the pages that compose your app, the latter indeed does exactly what you asked for (replace the content of the window).
The documentation already contains good examples of use for both components.

Related

MFC: After applying a CSplitterWnd to my CChildFrame the main window title isn't updated any more

Still using VS 2008, I have split my MDI view class in my CChildFrame to facilitate a navigation sidebar (a CListCtrl) next to my old CScrollView using a static splitter (source code). This however implied two side effects: Beside the mouse wheel no longer working (where I found a workaround for), the application window is no longer updated on SetPathName(). What do I need to do to bridge the splitter so the framework updates the application window again based on my CDocument?
On your MainFrame class, just put a method
void CMyFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
__super::OnUpdateFrameTitle(bAddToTitle);
}
and a breakpoint there, to see what happens. If needed, you will have to provide your own override instead of calling the __super implementation.

QT arranging Components in the StackView

We are developing QT cross platform application. Application has many functional Screens and navigations. For simplicity of handling screens we are using QT QML StackView. Each item pushed to StackView is Page. I am using following function to push and pop screens.
stackview.push(someurl); //push new url
stackview.pop(); //pop current URL or page
My Question is how can we reuse Components/Pages already pushed on to the stack?
Example : I have following screens A, B, C, D. stack is looking like A->B->C->D. Now from screen D i want to navigate to Screen A. Due to uniform architecture of the application i don't want to do 3 times pop(), instead application should reuse already pushed Screen A and bring it to top.
We can simply push the screen A to StackView (A->B->C->D->A), but we are connecting different Signal/Slot to/from each screen and it will not be good practice to connect every time screen is pushed, also don't want to grow the application StackView size.
What will be the best approach to use in this case ? Any other QT Component/Control which i can use in this case so that i can render Pages depending on Index?
We tried creating component in advance as qml Property and push it depending on URL. It is useful worked great in sample application. but in our application QML component data is closely dependent on C++ data( or some calculations at run time). Application is causing crash if we create component in advance. So we are not willing to use that approach.
property Page page1: Screen1{} //Screen1.qml
property Page page2: Screen2{} //Screen2.qml
property Page page3: Screen3{} //Screen3.qml
property Page page4: Screen4{} //Screen4.qml
Is it possible to laod Stackview component based on Index, i am not finding anything related to that in documents.
Due to uniform architecture of the application i don't want to do 3 times pop(), instead application should reuse already pushed Screen A and bring it to top.
You don't have to call pop() three times to get back to A. According to the documentation :
Item pop(Item item = undefined)
[...]
item: if specified, all items down to (but not including) item will be popped off. If item is null, all items down to (but not including) the first item will be popped. If not specified, only the current item will be popped.
Only call pop(null) once to have your stack going to the first A pushed.
An other possible approach is to use StackLayout that allow you to display QML Components based on an index.
StackLayout {
id: layout
Screen1 {}
Screen2 {}
Screen3 {}
Screen4 {}
}
Then you can select which screen appears by changing the currentIndex property : layout.currentIndex = 1 // display Screen2

How to add detachable areas (QDockWidget) to a QML application

How do I add detachable areas to a QML ApplicationWindow?
Take the following application (Tiled) as an example. It has multiple detachable areas. In the first image all areas are attached, while in the second one area is in the process of being detached/reattached:
From C++ this can be realized with QDockWidget (see this question). But is there a solution with QML?
I made a simple working example. You can find it here. There must be enough comments for you to sort it out.
I used dynamic creation of objects like that:
dynamically create component(DetachableItem.qml) and assign it to property(not necessary, but it is easier to find it)
create connection for this component's attached property, where I can call some function when it changes;
move the item into another window pushing the object into it's data property
move it back the same way - pushing it to data property of main window and hiding separate window.
Feel free to ask question or proposing some improvements. I am interested in any suggestions how to improve it!
UPD: I updated the example with new commit where I got rid of dynamic objects creation. If you are still interested in dynamic object creation, you can checkout to this commit
Just an idea on how to achieve such behaviour. Have a look at the Window QML class and dynamic object creation to actually create a window by request.
Some (UNTESTED) pseudo-code, just to give an idea "DockWindow.qml":
import QtQuick 2.0
import QtQuick.Window 2.2
Rectangle {
id: dockWidget
property Window window: null
property Item embedIn: null
parent: window ? window : embedIn
readonly property bool detached: window
function detach() {
if (!window) {
window = Qt.createQmlObject('
import QtQuick.Window 2.2
Window { flags: …; }
', dockWidget, "dockWidget");
}
}
function close() {
if (window) {
window.close();
}
}
}
Note: This code will not work out of the box and probably leads to a dependency loop on the "parent" property!
As one possible solution you can create custom QDialog, use inside it QQuickView with desired qml stuff loaded from appropriate qml file. Communication with your main qml window and dialog will be done through Q_PROPERTY and Q_INVOKABLE defines in your custom dialog.
The pointer to your QDialog instance, for example, can be propagated to the QML as context property with help of QQmlContext::setContextProperty.
You can use KDDockWidget they have exported it to qml, its not LGPL though..

Gtkmm 3.0 How to switch between frames or windows

I'm rather new to C++, I have a bit of experience with MCV programming in Java. im using GTKmm on C++
What I'm trying to do is writing an application for teaching assistants to submit and edit applications to various positions, and administrators to come in view, and accept these applications.
What I'm trying to do at the begging is create 3 'frames' (I'm working on the submitting application for students only at the moment)
This first will have 2 buttons 1 for selecting if you're a student/admin
Upon clicking you're a student I want to hide this frame and show my second frame
The second frame will have another 2 buttons one for creating an application, and the other for editing applications
My core problem is that I don't understand how to switch between the frames, I've written all the code for my Model, and understand everything I want it to do however I cant seem to find how to do this...
My only idea would be to create windows for each of these, make them look all nice w/e, then when a button is pressed have that window close and a string written to file I can access to see which button has been pressed, then open a new window accordingly. Should I do it like this or is there a better way?
I think I can suggest a better/more idiomatic option for any version >= GTK+ 3.10 - which, to be fair, arrived about half a year after the accepted answer.
If you want to switch between widgets one-at-a-time without any accessories like tabs, then a Gtk::Stack seems like a better option. Because it's specifically geared for one-at-a-time presentation, without any redundancy and (theoretical) overhead from a Notebook's manual tabbing features, which you'd just be disabling straight away! It's a container with multiple children, with one visible at any given moment, and of course methods to change the active child.
You can hook up your own widgets and/or events to manage which of the Stack's children is shown. Alternatively - albeit possibly just restoring the redundancy in this case - there's a StackSwitcher companion widget, which is pretty much a vertical tab-bar as seen in the GTK+ demo and GNOME Tweak Tool.
Easiest way is to use a Notebook widget. You can hide the tabs since you will be controlling which page is showing, using method set_show_tabs(false). Put the top level widget for each of your frames in a pane using method append_page(), and switch between them using set_current_page(). You might want to hide the notebook's bevel if it's distracting, using method set_show_bevel(false).
Use signals to make a widget (e.g. "I'm a student" button) on one page do something (e.g. go to the second page). If you don't know what this means or how to do it, go through the gtkmm tutorial, it will explain this and more.
A bit too late ! But here is my try :
Gtk::Notebook is great but it is not ideal in switching between app frames on menu item clicks. Gtk::Stack, since gtkmm 3.10, exists to mitigate this. Assuming you're using glade and Gtk::Builder :
class
class AppName : public Gtk::ApplicationWindow
{
public:
//...Your app methods and callbacks
void on_mb_itemname_selected(); // The call back for our menu item click/select
private:
//Builder which will help build the app from a .glade file
Glib::RefPtr<Gtk::Builder> _builder;
//...
//Your menu item to activate a particular frame
Gtk::MenuItem * _mb_itemname;
//Your handle to Gtk::Stack which is usually the stack for the whole app
Gtk::Stack * _app_stack;
//...
}
constructor
AppName::AppName(BaseObjectType *cobj,
Glib::RefPtr<Gtk::Builder>& ref_builder)
:Gtk::ApplicationWindow(cobj),_builder(ref_builder)
{
//.. Other setup
_builder->get_widget("your_glade_id_to_stack",_app_stack);
_builder->get_widget("your_glade_id_to_menu_item",_mb_itemname);
// Connect signal_select of our menu item to appropriate signal handler.
mb_itemname->signal_select().connect(
sigc::mem_fun(*this,&AppName::on_mb_itemname_selected));
}
our callback
void AppName::on_mb_itemname_selected()
{
// Change the visible child of the stack concerned.
Gtk::StackTransitionType ttype = STACK_TRANSITION_TYPE_NONE;
_app_stack->set_visible_child("your_widget_name",ttype);
// Note that widget name is not widget glade id.
// You can set your widget under name Packing -> Name
return;
}

How to show available windows in the Window menu

I have a MFC MDI application that I've recently ported from VS2003 to VS2008, and at the same time moved from Stingray Objective Studio 2006 v2 to v10.1. On the previous versions of my application, if I had more than one view open, the Window menu would be populated by an enumerated list of available views, e.g. 1 MyViewA, 2 MyViewB etc... If I had a large number of views, I would also get a Windows... menu option to allow me to select a view. This no longer happens, which is breaking some of my GUI level regression tests. My guess is that this functionality was implemented by either CMDIFrameWnd or SECMDIFrameWnd but I couldn't find a reference to it in the documentation. Does anyone know how I can get this functionality back.
First thing I'd do is create a new MDI application with the ClassWizard and check if the functionality you're missing is present. If so, poke around and see if you can tell what's different. One place to look may be the menu resource for the main menu.
If there is no in-built functionality to provide what you need, you can dynamically build the menu with the following pseudocode:
foreach registered CDocumentTemplate
foreach document
foreach view
{
if (numberOfWindowMenuItems < 5)
{
Add menu item
}
else
{
Add "Windows..." menu item
break all loops;
}