Disable splitter cursor for QDockWidget - c++

I have the following widget structure. CDockWidgetInfoBar is just a QDockWidget derived class
When I move over the QDockWidget (CDockWidgetInfoBar), I see this splitter cursor.
Where is it coming from? Can I disable it? Is it part of QDockWidgetLayout? However, QDockWidgetLayout is Qt private and shall not be used.
Any ideas?

It seems to be impossible or extremely painful for system.
I tried to do this as I did this here: How can I prevent transform cursor to SplitHCursor when it's under border between QHeaderView sections
But the main problem, that resize cursor appears before QEvent::Enter event occurs. (if you run next code, you will see resize cursor first, but you will not see "added" word). As I know, there is no any event which can catch cursor when it moves near edge of widget. So it is very difficult to catch this event. There is another way. In mouseMoveEvent every time check is cursor near the dock widget. But I think that it is extremely inefficient.
I wrote this code:
if (obj == ui->dockWidget && event->type() == QEvent::Enter)
{
qApp->setOverrideCursor(QCursor(Qt::ArrowCursor));
qDebug() << "added";
}
if (obj == ui->dockWidget && event->type() == QEvent::Leave)
{
qApp->restoreOverrideCursor();
}
But it really works after user trying to float dock.
I know that it is not full answer, but maybe it helps or prove that it is very difficult. Anyways, if someone will find efficient solution of this problem, it will be extremely great.

Related

QSlider postion changes only when minimazing app

I am using QSlider element in my app as a toogle switch. I took this project over from a colleage of mine who left. So far so good, except, that this switch has a black label around it. I can't really change the style and rework everything so, I am stuck with label and slider as switch.
I need to handle events from button clicked and button released. I do it like this-
bool CustomSlider::eventFilter(QObject *obj, QEvent *ev )
{
if (ev->type() == QEvent::MouseButtonRelease)
{
changeSliderValue();
}
if(ev->type() == QEvent::MouseButtonPress){
lastSaved = ui->horizontalSlider->value();
}
return QWidget::eventFilter(obj,ev);
And changeSliderValue()-
void CustomSlider::changeSliderValue()
{
int current = ui->horizontalSlider->value();
if(lastSaved==current){
if(current){
ui->horizontalSlider->setValue(0);
}else{
ui->horizontalSlider->setValue(1);
}
}
}
So, in short, if I click, it saves state of slider and when releasing it checks against saved state. I do it because QSlider has button pressed signal as well. I have put debug messages in my code and funny thing is debug messages fire. So my code works. If I call ui->horizontalSlider->value() I get the correct(changed) value But the slider is not moving. I have tried checking sequences, if it does not change value twice(it does not), I have tried calling repaint() and so far nothing works. Except if don't minimize(via minimize button) or click in different app(like web browser) and then I can see that slider moves to correct postion. I am completely confused. Has anyone encoutered something like this before?

QKeyEvent isAutoRepeat not working?

So, I have an application where if a particular button is kept pressed it plays an audio device, when the button is released it stops the audio device. I use keyPressEvent and KeyReleaseEvent to implement this which is similar to the code below:
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->isAutoRepeat())
{
event->ignore();
}
else
{
if(event->key() == Qt::Key_0)
{
qDebug()<<"key_0 pressed"<<endl;
}
else
{
QWidget::keyPressEvent(event);
}
}
}
void MainWindow::keyReleaseEvent(QKeyEvent *event)
{
if(event->isAutoRepeat())
{
event->ignore();
}
else
{
if(event->key() == Qt::Key_0)
{
qDebug()<<"key_0 released"<<endl;
}
else
{
QWidget::keyReleaseEvent(event);
}
}
}
But apparently isAutoRepeat function isn't working as I can see continuous print out of key_0 pressed and key_0 released despite the fact I haven't released the 0 key after I have pressed it. Is my code wrong or something else is wrong?
Thanks.
EDIT
I think this is happening because the MainWindow loses the keyboard focus. How can I actually find out which widget has the focus? I'm actually using some widgets when Qt::Key_0 pressed, but I thought I set all those possible widgets to Qt::NoFocus, I guess it's not working.
I'm trying to know which widget has the focus by doing the following:
QWidget * wigdet = QApplication::activeWindow();
qDebug()<<wigdet->accessibleName()<<endl;
but it always prints an empty string. How can I make it print the name of the widget which has the keyboard focus?
So as I also stumbled over this issue (and grabKeyboard didn't really help), I begun digging in qtbase. It is connected to X11 via xcb, and by default, in case of repeated keys, X11 sends for each repeated key a release-event immediately followed by a key-press-event. So holding down a key results in a sequence of XCB_BUTTON_RELEASE/XCB_BUTTON_PRESS-events beeing sent to the client (try it out with xev or the source at the end of this page).
Then, qt (qtbase/src/plugins/platforms/xcb/qxcbkeyboard.cpp) tries to figure out from these events whether its an autorepeat case: when a release is received, it uses a lookahead feature to figure if its followed by a press (with timestamps close enough), and if so it assumes autorepeat.
This does not always work, at least not on all platforms. For my case (old and outworn slow laptop (Intel® Celeron(R) CPU N2830 # 2.16GHz × 2) running ubuntu 16.04), it helped to just put a usleep (500) before that check, allowing the press event following the release event to arrive... it's around line 1525 of qxcbkeyboard.cpp:
// look ahead for auto-repeat
KeyChecker checker(source->xcb_window(), code, time, state);
usleep(500); // Added, 100 is to small, 200 is ok (for me)
xcb_generic_event_t *event = connection()->checkEvent(checker);
if (event) {
...
Filed this as QTBUG-57335.
Nb: The behaviour of X can be changed by using
Display *dpy=...;
Bool result;
XkbSetDetectableAutoRepeat (dpy, true, &result);
Then it wont send this release-press-sequences in case of a hold down key, but using it would require more changes to the autorepeat-detection-logic.
Anyway solved it.
The problem was that I have a widget which is a subclass of QGLWidget which I use to show some augmented reality images from Kinect. This widget takes over the keyboard focus whenever a keyboard button is pressed.
To solve this problem, I needed to call grabKeyboard function from the MainWindow class (MainWindow is a subclass of QMainWindow), so this->grabKeyboard() is the line I needed to add when key_0 button is pressed so that MainWindow doesn't lose the keyboard focus, and then when the key is released I needed to add the line this->releaseKeyboard() to resume normal behaviour, that is, other widgets can have the keyboard focus.

Cursor won't change for my QGraphicsView

I have created my own widget based on QGraphicsView. I did this in order to re-implement some mouse events as such:
void Workspace::mouseMoveEvent(QMouseEvent *event)
{
qDebug() << (QString("Mouse move (%1,%2)").arg(event->x()).arg(event->y()));
QGraphicsView::mouseMoveEvent(event);
}
as well as install an event filter
bool Workspace::eventFilter(QObject* obj, QEvent* e)
{
if(e->type() == QEvent::Enter)
qDebug() << "Entered Workspace";
}
I did not liked the default 'hand' mouse pointer though and I decided to change it using
this->setCursor(Qt::CrossCursor);
in my constructor.
What happens though is the mouse pointer changing into a cross only while being at the very first pixel of the widget. The moment I move further in it goes back to the default 'hand' cursor that is used to signify drag functionality.
Why is this happening and how can I change the cursor to whatever I like?
It seems that using
QApplication::setOverrideCursor(Qt::CrossCursor);
when entering the widget, and
QApplication::restoreOverrideCursor();
when exiting, does the trick.
I am not sure why setCursor did not work though.
EDIT
Actually using the above is not such a good idea, as it is simpler to just use
QApplication::changeOverrideCursor(*mCurrentCursor);
you will not have to worry about anything else this way, Qt will take care of stack en-queue/de-queue.

Qt QGraphicsScene does not fitInView() with scrollbars

QGraphicsView::fitInView() seems to ignore the presence of scrollbars, that apparently are overlaid. (It also uses a hardcoded 2 pixel margin.)
There is a related bug report (https://bugreports.qt-project.org/browse/QTBUG-1047) stating that calling fitInView() twice would resolve the problem.
In my case, it does not. Only triggering it twice manually fits regarding the scrollbars. This does not work:
void myGraphicsView::mousePressEvent(QMouseEvent *event) {
if( event->button() == Qt::LeftButton ) {
QGraphicsItem* clicked = scene()->itemAt( mapToScene( event->pos() ) );
qDebug() << clicked << clicked->boundingRect();
fitInView( clicked, Qt::KeepAspectRatio);
fitInView( clicked, Qt::KeepAspectRatio); // doesn't work for me
QGraphicsView::mousePressEvent(event);
return;
}
}
Is there another workaround?
Qt 4.8.1 with MSVC2010
Calling fitInView() twice does work, but you have to let Qt process its events between the two calls.
This also means you end up redrawing the graphicsview twice.
To avoid this, what I do is:
Disable updates
Call fitInView
Call QApplication::processEvents()
Call fitInView again
Enable updates
In your code it would look like this:
bool updateState = updatesEnabled();
setUpdatesEnabled(false);
fitInView(clicked, Qt::KeepAspectRatio);
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
fitInView(clicked, Qt::KeepAspectRatio);
setUpdatesEnabled(updateState);
The cause could be this (at least it looks like it is in the bug report): https://bugreports.qt.io/browse/QTBUG-42331 - please vote on it on the qt bug tracker to up its priority.
In short, fitInView has hardcoded margins and this can cause all kinds of havoc - the least of which is that now you lose a few pixels of display area and might also force unnecessary rescaling. It can cause runaway resizing and weird instabilities such as what the QTBUG-1047 bug submitter described.
You can fix the problem by reimplementing fitInView, based on the existing implementation but removing it's ridiculous margins. An example of that is available here in python, based on the original C++ version:
https://github.com/nevion/pyqimageview/blob/master/qimageview/widget.py#L276
Let me know if it fixes your problem! That way we can close out that since-2007 bug too.

QTooltip that does not depend on mouse

I currently am attempting to display a tooltip on focusOutEvent of a widget. This tooltip basically validates the data inside the Widget (QLineEdit). Now the problem is I want to display the errors or issues using a tooltip . Here is what I am doing
void MyLineEdit::focusOutEvent(QFocusEvent *e)
{
QLineEdit::focusOutEvent(e);
QToolTip::showText( this->mapToGlobal( QPoint( 0, 0 ) ), "Something got it" );
emit(focussed(false));
}
Now the problem is the QTooltip is not displayed that is probably because the mouse is moving. My question is how can I make QTooltip be displayed and keep it there until I wish to turn it off ??
A tooltip will only show up if a QHelpEvent was intercepted. While you can send one from focusOutEvent using QCoreApplication::PostEvent and subclass QWidget::event like this
bool MyLineEdit::event (QEvent *event)
{
if (event->type() == QEvent::ToolTip) {
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
QToolTip::showText(helpEvent->globalPos(), "Something got it");
return false;
}
return QWidget::event(event);
}
, this has two undesirable consequences.
1) The event would still be triggered whenever a tooltip would be shown normally (that is, when your mouse pointer stays on the widget for a couple of seconds). You will have to implement some kind of recognition mechanism to distinguish your own help events from the rest.
2) The tooltip is only active while the respective widget is focused. So, displaying a tooltip when the focus is lost will show it only for a couple of seconds, until the next event loop is processed.
There might be a workaround for the latter, but at this point, it is probably better to leave the tooltips for their intended purpose and implement your own pseudo-tooltip which you would control directly.