Pause application in QML when app is in background Symbian - background

I want to know of any pure QML way to find out whether the application is in the background or not and then accordingly stop or play music. In meego the alternate way to do is through the PlatformWindow Element but it does not exist in Symbian QML. Help needed please

Finally I got it working :) and i did it though Qt way... here are the steps
1) Create a class MyEventFilter
class myEventFilter : public QObject
{
bool eventFilter(QObject *obj, QEvent *event) {
switch(event->type()) {
case QEvent::WindowActivate:
emit qmlvisiblechange(true);
qDebug() << "Window activated";
bis_foreground=true;
return true;
case QEvent::WindowDeactivate:
emit qmlvisiblechange(false);
qDebug() << "Window deactivated";
bis_foreground=false;
return true;
default:
return false;
}
}
void dosomething();
private:
int something;
public:
bool bis_foreground;
Q_OBJECT
public slots:
Q_INVOKABLE QString checkvisibility() {
if (bis_foreground==true) return "true";
else return "false";
}
signals:
void qmlvisiblechange(bool is_foreground);
};
2) Then in main.cpp include this file include the class and add setContext propery like this
context->setContextProperty("myqmlobject", &ef);
3) in qml file call it like this:
Item {
id: name
Connections
{
target:myqmlobject
onQmlvisiblechange:
{
if(is_foreground)
{
//dont do anything...
}
else
{
playSound.stop()
}
}
}
}
Enjoy :)

Why do you need a pure QML way?
You can detect if an application has been sent to the background by installing an event filter.
Check: http://www.developer.nokia.com/Community/Wiki/Detecting_when_a_Qt_application_has_been_switched_to_the_background_and_when_resumed
For a "pure" QML way, there is the Symbian QML element:
http://doc.qt.nokia.com/qt-components-symbian/qml-symbian.html
It has a foreground property that indicates whether the app is in the foreground or in the background. You can try connecting to onForegroundChanged.
From the documentation, the Symbian element is not "creatable". It exists as a context property named symbian. So a sample usage would be:
import QtQuick 1.1
import com.nokia.symbian 1.1
PageStackWindow {
id: window
initialPage: MainPage {tools: toolBarLayout}
showStatusBar: true
showToolBar: true
function appForegroundChanged() {
console.log("Foreground: " + symbian.foreground)
}
function appCurrentTimeChanged() {
console.log("Current time: " + symbian.currentTime)
}
Component.onCompleted: {
symbian.currentTimeChanged.connect(appCurrentTimeChanged)
symbian.foregroundChanged.connect(appForegroundChanged)
}
ToolBarLayout {
id: toolBarLayout
ToolButton {
flat: true
iconSource: "toolbar-back"
onClicked: window.pageStack.depth <= 1 ? Qt.quit() : window.pageStack.pop()
}
}
}

Related

Is it possible to programatically create a xaml page?

I might write no sense on the next lines:
I tried to derive a struct named mainpage from winrt::Windows::UI::Xaml::Controls::Page and pass it to winrt::xaml_typename<>(), in "<>" is mainpage.
It will be understandable when you look at the code:
Point number 1 "(1)" is the mainpage.h file, is very short.
Point number 2 "(2)" is the App.cpp file, it only has the necessary.
//(1) mainpage.h
#pragma once
#include "pch.h"
struct mainpage : winrt::Windows::UI::Xaml::Controls::Page
{
mainpage() {
winrt::Windows::UI::Xaml::Controls::Button thebutton = winrt::Windows::UI::Xaml::Controls::Button();
thebutton.Click([&](const IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& event_arg)
{
thebutton.Content(winrt::box_value(L"Clicked"));
});
}
};
//(2) App.cpp
#include "pch.h"
#include "mainpage.h"
struct App : winrt::Windows::UI::Xaml::ApplicationT<App>
{
void OnLaunched(const winrt::Windows::ApplicationModel::Activation::LaunchActivatedEventArgs& event_arg)
{
winrt::Windows::UI::Xaml::Controls::Frame root_frame{ nullptr };
winrt::Windows::UI::Xaml::UIElement content = winrt::Windows::UI::Xaml::Window::Current().Content();
if (content)
{
root_frame = content.try_as<winrt::Windows::UI::Xaml::Controls::Frame>();
}
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (root_frame == nullptr)
{
// Create a Frame to act as the navigation context and associate it with
// a SuspensionManager key
root_frame = winrt::Windows::UI::Xaml::Controls::Frame();
root_frame.NavigationFailed({ this, &App::OnNavigationFailed });
if (event_arg.PreviousExecutionState() == winrt::Windows::ApplicationModel::Activation::ApplicationExecutionState::Terminated)
{
// Restore the saved session state only when appropriate, scheduling the
// final launch steps after the restore is complete
}
if (event_arg.PrelaunchActivated() == false)
{
if (root_frame.Content() == nullptr)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
root_frame.Navigate(winrt::xaml_typename<mainpage>(), box_value(event_arg.Arguments()));
}
// Place the frame in the current Window
winrt::Windows::UI::Xaml::Window::Current().Content(root_frame);
// Ensure the current window is active
winrt::Windows::UI::Xaml::Window::Current().Activate();
}
}
else
{
if (event_arg.PrelaunchActivated() == false)
{
if (root_frame.Content() == nullptr)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
root_frame.Navigate(winrt::xaml_typename<mainpage>(), box_value(event_arg.Arguments()));
}
// Ensure the current window is active
winrt::Windows::UI::Xaml::Window::Current().Activate();
}
}
}
void App::OnNavigationFailed(const IInspectable&, const winrt::Windows::UI::Xaml::Navigation::NavigationFailedEventArgs& event_arg)
{
throw winrt::hresult_error(E_FAIL, winrt::hstring(L"Failed to load Page ") + event_arg.SourcePageType().Name);
}
};
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) {
winrt::Windows::UI::Xaml::Application::Start([](auto &&) { winrt::make<App>(); });
}
If it is not possible, how can I properly create a page?
It is simple if you have installed the CppWinRT VSIX. Then create a "View model" and edit the files. You shouldn't derive the struct from the winrt::Windows::UI::Xaml::Controls::Page class because winrt::xaml_typename<> needs a WinRT class in <>.

Changed event for JavaScript Binding in Qml?

I have a property which is defined by a JavaScript expression (currentContainer):
Item {
id: theContainer
property alias currentIndex: theListView.currentIndex
signal onCurrentIndexChanged()
property MyCustomCppContainer currentContainer: {
if(theListView.currentIndex >= 0)
theModel.getCustomContainer(theListView.currentIndex)
else
null
}
signal onCurrentContainerChanged() // nobody calls this signal (yet)
MyCustomCppModel {
id: theModel
}
ListView {
id: theListView
anchors.fill: parent
model: theModel
currentIndex: -1
onCurrentIndexChanged: theContainer.onCurrentIndexChanged()
/* Other properties stripped for example */
}
}
Sadly I always get the last selected container, not the currently selected one:
ContainerItem {
onCurrentIndexChanged: {
//On first change, currentContainer is null
//though the first one was selected
//After selecting the second entry
//I get the result I expected last time
console.log(currentContainer.name);
}
}
I think a solution would be to have another signal for currentContainer: onCurrentContainerChanged().
But who calls this special signal?
I could solve this using a C++ helper class:
class PropertyChangedHelper : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant theProperty WRITE setTheProperty NOTIFY thePropertyChanged)
public:
PropertyChangedHelper(QObject* parent = nullptr) : QObject(parent) {}
virtual ~PropertyChangedHelper() {}
void setTheProperty(QVariant) {
Q_EMIT thePropertyChanged();
}
Q_SIGNALS:
void thePropertyChanged();
private:
Q_DISABLE_COPY(PropertyChangedHelper)
};
Usage is quite simple:
PropertyChangedHelper {
theProperty: containerItem.currentContainer
onThePropertyChanged: {
console.log(containerItem.currentContainer.name);
}
}
I am not sure if this violates any Qml/QtQuick philosophies, but it works.

Catch mouse event on tree widget item in QTreeWidget

In tree widget I have following signal connected:
connect(mTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)),
SLOT(onItemClicked(QTreeWidgetItem*, int)));
where onItemClicked() slot is following:
void WidgetBox::onItemClicked(QTreeWidgetItem *item, int )
{
int index = getPageIndex(item);
setCurrentIndex(index);
}
int WidgetBox::getPageIndex(QTreeWidgetItem *item)
{
if (!item) return -1;
QTreeWidgetItem *parent = item->parent();
if(parent) // Parent is top level item
{
return mTreeWidget->indexOfTopLevelItem(parent);
}
else // Current item is top level
{
return item->treeWidget()->indexOfTopLevelItem(item);
}
}
void WidgetBox::setCurrentIndex(int index)
{
if (index != currentIndex() && checkIndex(index))
{
mTreeWidget->setCurrentItem(mTreeWidget->topLevelItem(index));
emit currentIndexChanged(index);
}
}
However I can't catch itemClicked() signal and onItemClicked() never executed because top level items has push button widget (set with setItemWidget() method) which intercepts mouse event and child items contain container widgets which may have any widget combinations in them.
Is there a good method here to invoke this itemClicked() signal for both top level and child items of tree widget?
installEventFilter() for all widgets found in an item by something like following:QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>();?
Or establish mouse event propagation somehow?
QCoreApplication::postEvent()?
How to organize such process better so all widgets process mouse event as they need to and TreeWidget issue SIGNAL(itemClicked()) as well?
Full sources to reproduce: https://github.com/akontsevich/WidgetBox
So solution is simple and following - just re-send void itemClicked(QTreeWidgetItem *item, int column); signal in PageEventFilter:
PageEventFilter::PageEventFilter(QObject *parent, QTreeWidgetItem *item)
: QObject(parent)
, mItem(item)
{
connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
mItem->treeWidget(), SIGNAL(itemClicked(QTreeWidgetItem*,int)));
}
bool PageEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
// Resend signal to QTreeWidget
emit itemClicked(mItem, 0);
return false; // Send event to the object (do not filter it)
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
P.S. Will leave previous answer as well if somebody needs code or idea.
Created event filter like this:
class PageEventFilter : public QObject
{
Q_OBJECT
public:
PageEventFilter(QObject *parent, QTreeWidgetItem *item);
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
QTreeWidgetItem *mItem;
};
bool PageEventFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
// Emitate mouse event for parent QTreeWidget
QMouseEvent *oldEvent = (QMouseEvent *)event;
QRect itemRect = mItem->treeWidget()->visualItemRect(mItem);
QPointF mousePos(itemRect.x() + 1, itemRect.y() + 1);
QMouseEvent *newEvent = new QMouseEvent(oldEvent->type(),
mousePos,
oldEvent->button(),
oldEvent->buttons(),
oldEvent->modifiers());
QCoreApplication::postEvent(mItem->treeWidget(), newEvent);
return false; // Sent event to the object (do not filter it)
}
else
{
// standard event processing
return QObject::eventFilter(obj, event);
}
}
Install it to a button in tree widget item. It creates and sends (imitates) mouse event to tree widget, however tree widget still does not send itemClicked(QTreeWidgetItem*, int) signal. What is the problem could be? Wrong mouse pos? Tried to send event to viewport() - no luck as well. Any way to solve this?

"matchMedia" support in Dart

How to use window.matchMedia in Dart?
I have found corresponding method:
MediaQueryList matchMedia(String query)
And "MediaQueryList" method:
void addListener(MediaQueryListListener listener)
But: MediaQueryListListener has no constructor and looks like some sort of a generated stub.
I have JS example:
var mq = window.matchMedia( "(min-width: 500px)" );
// media query event handler
if (matchMedia) {
var mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
// window width is at least 500px
}
else {
// window width is less than 500px
}
}
And it has good support http://caniuse.com/#feat=matchmedia
As pointed in a comment it doesn't seem to be implemented in Dart for now.
However you can use dart:js to do that like this :
import 'dart:js';
main() {
if (context['matchMedia'] != null) {
final mq = context.callMethod('matchMedia', ['(min-width: 500px)']);
mq.callMethod('addListener', [widthChange]);
widthChange(mq);
}
}
widthChange(mq) {
if (mq['matches']) {
print('window width is at least 500px');
} else {
print('window width is less than 500px');
}
}

How can you detect the connection and disconnection of external monitors on the Mac?

Do you have any idea how I can detect additional screens being plugged in / unplugged in a Cocoa application?
I want to detect the moment when the user plugs or unplugs another screen to his Mac. How could I do this?
Your answer lies in Quartz.
#include <ApplicationServices/ApplicationServices.h>
CGError CGDisplayRegisterReconfigurationCallback (
CGDisplayReconfigurationCallBack proc,
void *userInfo
);
And then your proc looks like:
MyCGDisplayReconfigurationCallBack(
CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags,
void *userInfo) {
if (flags & kCGDisplayAddFlag || flags & kCGDisplayRemoveFlag) {
DoStuff(display, flags, userInfo);
}
}
In Swift5:
extension ScreenDetector {
static let callback: CGDisplayReconfigurationCallBack = { (displayId, flags, userInfo) in
guard let opaque = userInfo else {
return
}
let mySelf = Unmanaged<ScreenDetector>.fromOpaque(opaque).takeUnretainedValue()
if flags.contains(.addFlag) {
//Add Display...
}else if flags.contains(.removeFlag) {
//Removed Display...
}
}
func addObervers() {
let userData = Unmanaged<ScreenDetector>.passUnretained(self).toOpaque()
CGDisplayRegisterReconfigurationCallback(ScreenDetector.callback, userData)
}
func removeObservers() {
let userData = Unmanaged<ScreenDetector>.passUnretained(self).toOpaque()
CGDisplayRemoveReconfigurationCallback(ScreenDetector.callback, userData)
}
}
If someone is interested in doing this in Swift 2.3, I scratched my head for a little while to translate #iluvcapra 's code:
let userData = UnsafeMutablePointer<ViewController>(Unmanaged.passUnretained(self).toOpaque()) //use the class name of your "self" for future reference inside the callback
CGDisplayRegisterReconfigurationCallback({ (display: UInt32, flags: CGDisplayChangeSummaryFlags, userInfo: UnsafeMutablePointer<Swift.Void>) in
let mySelf = Unmanaged<ViewController>.fromOpaque(COpaquePointer(userInfo)).takeUnretainedValue() //change here to your class name
if flags.rawValue & CGDisplayChangeSummaryFlags.AddFlag.rawValue > 0 {
//do stuff on connect
mySelf.someFunction()
} else if flags.rawValue & CGDisplayChangeSummaryFlags.RemoveFlag.rawValue > 0 {
//do stuff on disconnect
}
}, userData)