Run 2 UIs on diffrent monitor using qt-creator on Dual-Head Graphics Card - linux

I have a Dual-Display Graphics card, on my system (RHEL 6.3).
I have developed one simple application using qt creator (qt-4.8), which throws two different UIs.
When I execute this then both UIs starts in only one display.
What I need is my one UI should run on primary screen and one on secondary screen (i.e. 0.0 and 0.1).
How should I do this using qt-creator?
xclock -display :0.0
xclock -display :0.1
works fine.

You can use a QDesktopWidget to get screen information. It Allows you to query the amount of screens and the dimension of each one with
int QDesktopWidget::screenCount () const;
const QRect QDesktopWidget::availableGeometry ( int screen = -1 ) const;
From there, you can move your widget to any given screen. For instance, the following code move the widget to a given screen or to the default one if the specified screen is not available:
QDesktopWidget* w = QApplication::desktop();
//some value
int mydesiredscreen = 1;
//fallback to default screen if none
if(mydesiredscreen >= w->screenCount()) mydesiredscreen = -1;
QRect rect1 = w->availableGeometry(mydesiredscreen);
mywindow->move(rect1.topLeft());

Tejas,
To display your Second UI on Secondary Monitor you can use setParent property for your Second UI as :
int screenNumber = 1; /* Desired screen no */
QWidget secondaryUI_widget; /* Secondary UI Object which is to be displayed on secondary monitor */
QDesktopWidget myDesktopWidget; /* Create an object of QDesktopWidget */
secondUI_myDesktopWidget.setParent(myDesktopWidget(screenNumber));
The above line will set the desired screen on which you would like to display your page as parent for your UI object.
Now you can call show() function for your second UI anywhere in your program , the second UI will be displayed on desired screen number as being by screenNumber value

Related

GTK Data Capturing

I’m working in C on a project to capture data from a sensor and display it as part of a GUI application on the Raspberry Pi. I am using GTK 3.0, plus Cairo for graphing. I have built an application that works, but I want to make a modification to enable me to change the frequency of data capture.
Within my main code section I have a command like:-
gdk_threads_add_timeout (250, data_capture, widgets);
This all works, the data capture routine is triggered every 250mS, but I want to add functionality to the GUI to enable the user to change the speed. If I try to call this function from anywhere else other than main, it fails.
I have looked for other ways to do it, but I can’t find any examples or explanations of how I can do it.
Ideally what I would like is something like:-
void update_speed(button, widgets)
// Button to change speed has been pressed
read speed from GUI
update frequency
return
int main()
...
setup GUI
set default speed
start main GTK loop
Does anyone have any idea how I could achieve this?
Edit: Additional Code Snippet
(This is not the whole program, but an extract of main)
int main(int argc, char** argv) {
GtkBuilder *builder;
GtkWidget *window;
GError *err = NULL; // holds any error that occurs within GTK
// instantiate structure, allocating memory for it
struct app_widgets *widgets = g_slice_new(struct app_widgets);
// initialise GTK library and pass it in command line parameters
gtk_init(&argc, &argv);
// build the gui
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "../Visual/gui/main_window.glade", &err);
window = GTK_WIDGET(gtk_builder_get_object(builder, "main_application_window"));
// build the structure of widget pointers
widgets->w_spn_dataspeed = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spn_dataspeed"));
widgets->w_spn_refreshspeed = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spn_refreshspeed"));
widgets->w_adj_dataspeed = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "adj_dataspeed"));
widgets->w_adj_refreshspeed = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "adj_refreshspeed"));
// connect the widgets to the signal handler
gtk_builder_connect_signals(builder, widgets); // note: second parameter points to widgets
g_object_unref(builder);
// Set a timeout running to refresh the screen
gdk_threads_add_timeout(SCREEN_REFRESH_TIMER, (GSourceFunc)screen_timer_exe, (gpointer)widgets);
gdk_threads_add_timeout(DATA_REFRESH_TIMER, (GSourceFunc)data_timer_exe, (gpointer)widgets);
gtk_widget_show(window);
gtk_main();
// free up memory used by widget structure, probably not necessary as OS will
// reclaim memory from application after it exits
g_slice_free(struct app_widgets, widgets);
return (EXIT_SUCCESS);

How to manage tall menus (lists of languages)?

My application supports over 30 languages:
What is the right way to manage the situation where the menu is too tall for the screen? I will slowly get extra languages added and I do not know how to cater for it.
The standard menu implementation provides the functionality to automatically add scrollbars, should the number of entries exceed the menu's maximum height. By default a popup menu's height is set to 0, instructing the system to use the screen height as the menu's maximum height.
This works for a number of scenarios, and you don't have to do anything to get that behavior. It does fail, though, for multimonitor setups, where the height of the primary display is larger than the height of the display, where the application is displayed.
To work around this, you can set the respective popup menu's maximum height, whenever it is displayed. The appropriate place would be CWnd::OnInitMenuPopup:
void CMainFrame::OnInitMenuPopup( CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu ) {
CFrameWnd::OnInitMenuPopup( pPopupMenu, nIndex, bSysMenu );
if ( !bSysMenu && ( nIndex == 3 ) ) { // Apply appropriate filter
MENUINFO mi = { 0 };
mi.cbSize = sizeof( mi );
mi.fMask = MIM_MAXHEIGHT;
mi.cyMax = 150; // Pick an appropriate value
pPopupMenu->SetMenuInfo( &mi );
}
}
This callback is called, whenever a popup menu is about to be displayed. The height has been arbitrarily set to 150. You can pick any value you see fit in your application (e.g. the minimum height of all displays, a value based on the height of the display, where the menu will be displayed, etc.).
Scrollbars are added automatically, as can be seen in the following screenshot:

GTK3 GtkLayout with cairo, cannot get update region

I am trying to draw a GtkLayout using cairo. The layout is huge and I need to get the part that is visible in the container window and update that part only. With GTK2 the expose event data was sufficient to do this. I am not successful with GTK3.
In the function to handle "draw" events, I did the following:
GdkWindow *gdkwin; // window to draw
cairo_region_t *cregion; // update regions
cairo_rectangle_int_t crect; // enclosing rectangle
gdkwin = gtk_layout_get_bin_window(GTK_LAYOUT(layout));
cregion = gdk_window_get_update_area(gdkwin);
cairo_region_get_extents(cregion,&crect);
expy1 = crect.y; // top of update area
expy2 = expy1 + crect.height; // bottom of update area
The problem is that cregion has garbage. Either gdk_window_get_update_area() is buggy or I am not using the right drawing window.
Passing the GtkLayout as follows also does not work (this is the function arg for g_signal_connect):
void draw_function(GtkWidget *layout, cairo_t *cr, void *userdata)
Whatever gets passed is not the GtkLayout from g_signal_connect, but something else.
================= UPDATE ====================
I found a way to do what I want without using GtkLayout.
I am using a GtkDrawingArea inside a viewport.
I can scroll to any window within the large graphic layout
and update that window only. Works well once I figured out
the cryptic docs.
scrwing = gtk_scrolled_window_new(0,0);
gtk_container_add(GTK_CONTAINER(vboxx),scrwing);
drwing = gtk_drawing_area_new();
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrwing),drwing);
gtk_scrolled_window_set_policy(SCROLLWIN(scrwing),ALWAYS,ALWAYS);
scrollbar = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrwing));

How to limit frame resizing based on view's size? MFC doc/view architecture

MFC doc/view architecture, sdi (more precisely multiple top-level windows).
In my view class, I set my "playground" (i.e. logical space) with SetScrollSizes(); Then I want to limit maximum frame window size to that of view's maximum size.
Here is what I'm doing but I think there might be better solution, please advice:
I'm implementing OnGetMinMaxInfo() in my CMainFrame. There I try to get active view's scroll sizes, and set lpMMI->ptMaxTrackSize appropriately. Below is the code:
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Call base version:
CFrameWndEx::OnGetMinMaxInfo(lpMMI);
// Get active view:
CScrollView *pScrollView = (CScrollView *)GetActiveView();
if (pScrollView && pScrollView->IsKindOf(RUNTIME_CLASS(CMyFckinView)))
{
// Get total size of playground:
CSize sizePlayground = pScrollView->GetTotalSize();
// Test if the size is non-zero, i.e. there is at least one node displayed:
if (sizePlayground.cx && sizePlayground.cy/* && !IsPrintPreview()*/)
{
// Set maximum window size to match our playground size:
CRect rectClient, rectWindow;
pScrollView->GetClientRect(&rectClient);
this->GetWindowRect(&rectWindow);
if (rectWindow.top > -5000 && rectWindow.left > -5000) // Avoid when minimized...
{
lpMMI->ptMaxTrackSize.x = sizePlayground.cx + (rectWindow.Width() - rectClient.Width());
lpMMI->ptMaxTrackSize.y = sizePlayground.cy + (rectWindow.Height() - rectClient.Height());
return;
}
}
}
}
This works but has one problem: When print preview is displayed (standard MFC print preview), I obviously want to allow free window resizing, so I use runtime info GetActiveView()->IsKindOf(...) to determine that active view is really my view, and not print-preview's view (which is CPreviewViewEx). But when I close the print preview, OnGetMinMaxInfo is not called, so I'm unable to adjust frame size according to my view again. As soon as I move the window OnGetMinMaxInfo gets called again and correctly adjusts frame size, but without manually moving the window old size (to which the print preview was sized to) is retained and has ugly artifact.
What can I do? Basically if I could trap the moment when print preview is closed, I could use following trick:
// Trigger the WM_MINMAXINFO message:
CFrameWnd *pFrame = GetParentFrame();
RECT rectWindow;
pFrame->GetWindowRect(&rectWindow);
pFrame->MoveWindow(&rectWindow);
But I don't know how to trap print-preview closure.
What I'm trying to accomplish seems quite standard: who would want to have frame window resized bigger than view's logical size (set by SetScrollSizes())? So there should be some more natural solution maybe?
In your CMyFckinView, handle a message that is reliably sent when the print preview is closed and then post a user message to the mainframe which will trigger your "force minmax" code. Perhaps WM_FOCUS or WM_ACTIVATE?

C++, MFC Feature Pack,Mdi childs visibility

I have an MDI MFC FEATURE PACK app in vs2008.
I do need to determine what child window(s) are visible , even if multiple tab groups are created by the user, and also what is the last activated MDI child. I have found that in my mainframe CMDIFrameWndEx class, the methods
m_wndClientArea.FindActiveTabWnd ();
m_wndClientArea.GetFirstTabWnd ();
m_wndClientArea.GetNextTabWnd ();
that could potentially let me navigate through all tab grops. Trouble is that these methods return an CMFCTabControl that does not offer any method/member to obtain an pointer to the MDI child windows in the tab. It only gives the index of the active tab.
So how do I get the CMDIChildWndEx* pointer of the "in front" window of the given tabgroup?
Because your CMDIChildWndEx instances are wrapped in a tab control wrapper you can get the active tab and then the wnd from that, e.g.
int nActive = pTabCtrl->GetActiveTab();
CWnd * pWnd = pTabCtrl->GetTabWndNoWrapper( nActive );
CMDIChildWndEx * pChild = dynamic_cast<CMDIChildWndEx*>(pWnd);
It was wonderful to find this code - exactly what I needed to redraw my active tab windows in each tab group since with multiple (split) tab groups, they were not being redrawn correctly. However, to make the loop work I had to do the following (CChildFrame is my derived frame type):
m_arrpActiveChilds.RemoveAll ();
const CObList& TabGroups =m_wndClientArea.GetMDITabGroups();
if (TabGroups.GetCount ()>0) {
POSITION crtPos = TabGroups.GetHeadPosition ();
CMFCTabCtrl* pCrtTabCtrl;
do {
pCrtTabCtrl=DYNAMIC_DOWNCAST(CMFCTabCtrl, TabGroups.GetNext(crtPos));
int nActive = pCrtTabCtrl->GetActiveTab();
CWnd * pWnd = pCrtTabCtrl->GetTabWndNoWrapper( nActive );
CChildFrame * pChild = dynamic_cast<CChildFrame*>(pWnd);
m_arrpActiveChilds.Add (pChild);
} while(crtPos != NULL);

Resources