Qt Bluetooth LE - instant disconnect while writing descriptor - c++

I'm trying to use Qt Bluetooth on Qt 5.8 and WinRT. I understand it's something that MUST go wrong one way or another but I'd like to avoid mixing Qt and native Windows APIs. I'm pretty sure I'm missing something super obvious right now.
const QLowEnergyCharacteristic characteristic = m_service->characteristic(
QBluetoothUuid(QBluetoothUuid::GlucoseMeasurement));
if (!characteristic.isValid()) {
break;
}
m_notificationDesc = characteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
if (m_notificationDesc.isValid()) {
m_service->writeDescriptor(m_notificationDesc, enable_notification);
}
Where enable_notification is QByteArray::fromHex("0100");.
After calling writeDescriptor, I get QLowEnergyService::DescriptorWriteError and an instant disconnect. Any ideas?

Related

Qt5 Not Registering Touch Events

I'm working on determining if a certain touchscreen will be compatible with an application and recently got a loaner model of an Elo 2402L touchscreen. I've installed the driver the company provides and was able to see multi-touch events using the evtest utility (parser for /dev/input/eventX).
The thing is that I'm running Scientific Linux 6.4, which uses Linux kernel 2.6.32. I've seen a lot of mixed information on touchscreen compatibility for Linux kernels before 3.x.x. Elo says that their driver only supports single-touch for 2.6.32. Also, I've seen people say that the majority of the compatibility issues with touch events in this kernel version are with Xorg interfaces.
I developed a very simple Qt5 application to test whether Qt could detect the touch events or not, because I'm not sure whether Qt applications are X-based and if they read events directly from /dev/input or something else.
However, despite a simple mouse event handler being able to correctly register mouse events, I also created a simple touch event handler and nothing happens when I touch the main screen. There is a beep, as part of the driver that Elo provides makes a beep when the screen is touched, so I know that SOMETHING is registering that touch, but neither the desktop, nor this application seem to recognize the touch event.
Also, yes, the WA_AcceptTouchEvents attribute is set to true in the window's constructor.
I have a simple mainwindow.h:
...
protected:
int touchEvent(QTouchEvent *ev);
...
And mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent) {
...
setAttribute(Qt::WA_AcceptTouchEvents, true);
touchPoints = 0;
}
...
int MainWindow::touchEvent(QTouchEvent *ev) {
switch(ev->type()) {
case QEvent::TouchBegin:
touchPoints++;
break;
case QEvent::TouchEnd:
touchPoints--;
break;
}
ui->statusBar->showMessage("Touch Points: " + touchPoints);
}
Is there something wrong with the way I'm using the touch event handler? Or is there some issue with the device itself? Does Qt read input events directly from /dev/input, or does it get its input events from X?
Very confused here, as I haven't used Qt before and want to narrow down the cause before I say that it's the device causing the issue.
Also, if anyone has any insight into the device / kernel compatibility issue, that would be extremely helpful.
The QTouchEvent documentation says:
Touch events occur when pressing, releasing, or moving one or more
touch points on a touch device (such as a touch-screen or track-pad).
To receive touch events, widgets have to have the
Qt::WA_AcceptTouchEvents attribute set and graphics items need to have
the acceptTouchEvents attribute set to true.
Probably you just need to call setAttribute(Qt::WA_AcceptTouchEvents, true) inside the MainWindow constructor.
Is there something wrong with the way I'm using the touch event handler?
There is no touch event handler. If you change:
int touchEvent(QTouchEvent *ev);
to:
int touchEvent(QTouchEvent *ev) override;
(which you should always do when you are trying to override virtual functions so you can catch exactly this kind of mistake), you'll see that there is no such function for you to override. What you need to override is the event() handler:
protected:
bool event(QEvent *ev) override;
You need to check for touch events there:
bool MainWindow::event(QEvent *ev)
{
switch(ev->type()) {
case QEvent::TouchBegin:
touchPoints++;
break;
case QEvent::TouchEnd:
touchPoints++;
break;
default:
return QMainWindow(ev);
}
ui->statusBar->showMessage("Touch Points: " + touchPoints);
}
However, it might be better to work with gestures instead of touch events. But I don't know what kind of application you're writing. If you wanted to let Qt recognize gestures rather than implementing them yourself through touch events, you would first grab the gestures you want, in this case pinching:
setAttribute(Qt::WA_AcceptTouchEvents);
grabGesture(Qt::PinchGesture);
and then handle it:
bool MainWindow::event(QEvent *ev)
{
if (e->type() != QEvent::Gesture) {
return QMainWindow::event(e);
}
auto* gestEv = static_cast<QGestureEvent*>(e);
if (auto* gest = gestEv->gesture(Qt::PinchGesture)) {
auto* pinchGest = static_cast<QPinchGesture*>(gest);
auto sf = pinchGest->scaleFactor();
// You could use the pinch scale factor here to zoom an image
// for example.
e->accept();
return true;
}
return QMainWindow::event(e);
}
Working with gestures instead of touch events has the advantage of using the platform's gesture recognition facilities, like those of Android and iOS. But again, I don't know what kind of application you're writing and on what kind of platform you're working on.

C++/Qt: Pass variables between C++ and Qt GUI without the C++ part including the Qt library

Closed:
Thanks everyone for the ideas, will try to work with your provided suggestions so solve my problem!
Problem:
"C++ main" (which CANNOT #include QObject or any Qt lib) gets data, processes the data and passes it into a separate Qt process (Qt GUI in this case).
Data gets visualized within the Qt GUI and provides feedback, e.g. you can send commands to the "C++ main" (like START/STOP MEASUREMENT).
Visualization of the problem in best paint quality.
Question:
Is there any possible way for the "C++ main" to get feedback from the Qt GUI WITHOUT including Qt in "C++ main" in any way? (The "C++ main" runs on an I/O-card which is not able to process/load the Qt lib.)
Thank you in advance for helpful answers!
Without much code on what goes on in your "C++ main" it is difficult to answer. But if you have class with a proper interface that is created in main and then used for the IO you could do something like the following:
class MyIoHandler {
public:
enum Command {START, STOP};
MyIoHandler() {}
void command(Command command) { d_command = command; } // Set the command
void getData(MyData& data) { data = d_data; } // Do a deep copy
private:
void run()
{
while(d_command == START) {
readDataFromIO();
d_data = data;
}
}
Command d_command;
MyData d_data;
};
Then the GUI just need to call the correct functions on the class to interface with the IO handler. There is no need for the main class to know how the GUI looks, but the GUI must know how the class looks.
This is also working on the assumption that they are in the same executable (from the comments) and
You just need to take care about threading etc.
But as mentioned, without some structure or code examples it is very difficult to give a useful answer.
I normally use QUdpSocket (in the Qt world) to talk to my other apps (effectively for IPC). Then your c++ world you can use normal sockets sys/socket.h for the same job. Since your comms is simplistic - i.e. message passing this is quite easy to do. There is some effort creating your c++ / Qt class to handle your UDP, but from then on its really easy.
The main drawback for me is that the two programs have to agree on a port to use (The IP address would be loop back address 127.0.0.1). So you may have a configuration file, or a command line parameter to set this...

C++ Global Hotkeys with platform APIs

I'm working on an application for taking screenshots on Windows, OSX and Linux in C++/Qt. Now I need to set global hotkeys, so the user can take screenshots when the application is running in the background. I tried with Qxt and UGlobalHotkey, which are both Qt libraries, but neither of them seemed to work.
I tried to implement it for OSX with Carbon (tutorial), but I need to call a class member function, which just doesn't work. Could someone provide me with an example? You can find my code here. The function i need to call is new_screenshot().
Or is there any other way to achieve something like this? I really need my application to take a screenshot from the background, otherwise it's pretty useless (yes, I should probably have implemented it at the very beginning to see if it even works). Would it maybe be better to have a separate client for every platform (Cocoa Swift for OSX, GTK for Linux, C# client for Windows)? I have often thought about this the past few days.
Do I understand correctly that you want to call new_screenshot from the hot key event handler? If so, InstallApplicationEventHandler lets you pass a pointer to user data in 4th argument. Pass a pointer to your MainWindow instance (based on code from the tutorial):
MainWindow *mainWindow = ... // get main window somehow
InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,mainWindow,NULL);
Then you can use it in the event handler.
OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{
//Do something once the key is pressed
static_cast<MainWindow*>(userData)->new_screenshot();
return noErr;
}
I did something in the past with MFC and WIN32 API....so it only works on Windows...but pressing ALT+F10 was able to hide/show a window...
void CWinHideDlg::OnButtonActive()
{
CString tmp;
GetDlgItemText(IDC_BUTTON_ACTIVE,tmp);
if(0 == strcmp(tmp.GetBuffer(tmp.GetLength()),"Activate"))
{
m_myAtom=GlobalAddAtom("MY_GLOBAL_HOT_HIDE_KEY");
int err=RegisterHotKey(this->GetSafeHwnd(),m_myAtom,MOD_ALT,VK_F10);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Stop");
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(TRUE);
SetDlgItemText(IDC_STATIC_INFO,"Set the mouse over the window \nand press ALT + F10 to hide it...");
}
else
{
UnregisterHotKey(this->GetSafeHwnd(),m_myAtom);
GlobalDeleteAtom(m_myAtom);
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(FALSE);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Activate");
}
}
Basically this code activates/deactivates the hot key ALT+F10, once it activates you can hide/unhide a running window on the system by setting the mouse pointer over the window and press ALT+F10...
This is from the WindowProc function:
if(message == WM_HOTKEY)
{
CString tmp;
POINT pc;
GetCursorPos(&pc);
if(GetAsyncKeyState(VK_F10))
{
HWND hwnd=::WindowFromPoint(pc);
if(hwnd)
{
tmp.Format("%08Xh",hwnd);
m_HideWins.InsertString(m_HideWins.GetCount(),tmp);
::ShowWindow(hwnd,SW_HIDE);
}
}
}
You can use the code to register your own HOT Key and use it to take a screenshot...
Hope it helps...

Register Global Hotkey under Qt and Mac OS X

Having read through various posts and threads that lead me nowhere I need your help.
I do have a Qt Application for Mac OS X that at some point of use will be in the background and not active. When this is the case I want to add a global hotkey so that the user can easily turn certain features on or off by clicking pre-defined hotkeys.
The following isn't working while the app is in the background and not focused.
QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_F12), parent);
shortcut->setContext(Qt::ApplicationShortcut);
So far I found Qxt which happens to be outdated for Qt 5.5.
Then there is DDHotkey which requires a certain compiler which we can not use for various reasons.
Lastly, I found the solution of adding a global AppleScript which registers an event, again, not what I am looking for.
tell application "System Events" to tell process "myApp"
click menu item "myButton" of menu 1 of menu bar item "Menu" of menu bar 1
end tell
Is there a way to use objective-c or cocoa to accomplish exactly what I am looking for?
Please lead me in the right direction if I may have missed something.
Thanks in advance!
To those who seek a more Qt way, check the following repository:
https://github.com/ddqd/qxtglobalshortcut5
It makes use of the outdated qxt library but gets it working again.
The person tested it until Qt 5.4, we use it successfully under Qt 5.5.
This might be what you're looking for
https://github.com/jaz303/JFHotkeyManager
You could also look at this example from Apple, using the RegisterEventHotKey API call which I think will point you in the right direction.
https://developer.apple.com/library/prerelease/mac/samplecode/FunkyOverlayWindow/Listings/FunkyOverlayWindow_OverlayWindow_m.html#//apple_ref/doc/uid/DTS10000391-FunkyOverlayWindow_OverlayWindow_m-DontLinkElementID_8
Or you could try this code
#import <Carbon/Carbon.h>
EventHandlerUPP hotKeyFunction;
pascal OSStatus hotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{
Notify *obj = userData;
[obj foo];
return noErr;
}
#implementation Notify
- (id)init
{
self = [super init];
if (self) {
//handler
hotKeyFunction = NewEventHandlerUPP(hotKeyHandler);
EventTypeSpec eventType;
eventType.eventClass = kEventClassKeyboard;
eventType.eventKind = kEventHotKeyReleased;
InstallApplicationEventHandler(hotKeyFunction,1,&eventType,self,NULL);
//hotkey
UInt32 keyCode = 80; //F19
EventHotKeyRef theRef = NULL;
EventHotKeyID keyID;
keyID.signature = 'FOO '; //arbitrary string
keyID.id = 1;
RegisterEventHotKey(keyCode,0,keyID,GetApplicationEventTarget(),0,&theRef);
}
return self;
}
- (void)foo
{
}
#end
And the header
#include "notify.mm"
#interface Notify
- (id)init;
- (void)foo;
#end
Simply this is just a object with a method and a constructor, in objective-c this is called init, or initialize, and variants. Calling it should be straight forward with "new".
E.x
#include "notify.h"
int main(){
Notify* object = new Notify();
}
However, some basic understanding of Objective-C is needed. It's mostly syntax differences in my opinion. But I'm no Objective-C expert myself. Anyway, there is a lot of ways to solve it, this might not be the best idea. You can also call Objective-C code from inside of a C++ class of yours. Take a look at the links bellow for a great example of how that's done.
https://el-tramo.be/blog/mixing-cocoa-and-qt/
https://github.com/remko/mixing-cocoa-and-qt/
http://philjordan.eu/article/mixing-objective-c-c++-and-objective-c++

Programming with Qt creator and Cocoa ( copying the selected text from the current application)

I would like to know if there is a way to use the Cocoa API in a Qt application.
I've already used the Windows API to get the selected text from the active application.
I'd like to do the same with mac os.
I tried to make a simple "hello world" application C++ with xCode, including the <Cocoa/Cocoa.h> but it didn't work as I excepted.
Is there a way to get this "hello word" application to build with Cocoa?
And, also If that is possible, can I get the selected text from the active windows with Cocoa API?
EDIT :
All right, so I successfully build something using Cocoa.h, thanks to this thread : How to mix Qt, C++ and Obj-C/Cocoa.
For the selection problem you could check out the answers I posted which tell you how to do it.
For those who could be interested : I found a way to get the current selected text.
Just by simulating cmd + c :
So thanks to this thread, I changed the code to obtain the "c" key which is represented by the integer 8 (Found in NSEvent.h), so here's the code :
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventRef saveCommandDown = CGEventCreateKeyboardEvent(source, (CGKeyCode)8, YES);
CGEventSetFlags(saveCommandDown, kCGEventFlagMaskCommand);
CGEventRef saveCommandUp = CGEventCreateKeyboardEvent(source, (CGKeyCode)8, NO);
CGEventPost(kCGAnnotatedSessionEventTap, saveCommandDown);
CGEventPost(kCGAnnotatedSessionEventTap, saveCommandUp);
CFRelease(saveCommandUp);
CFRelease(saveCommandDown);
CFRelease(source);
Now you just have to access the clipboard from Qt to get the selection. (If ask, I can put the code to do so)
Anyway, thanks to the stackoverflow community ;)