Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / qt / 2009-01

QTabWidget problem

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

zeljko

Hi all,

After latest patches about focuspolicy (I've completely removed handling of tab & backtab from qt, now LCL controls that part), we have pending problem with QTabWidget. QTabWidget::keyPressEvent(QKeyEvent *e) drive us into problem since it handles Tab key before that event is passed to LCL, and sets focus to tabbar.Original code is here (shorten)
void QTabWidget::keyPressEvent(QKeyEvent *e)
{

    Q_D(QTabWidget);
    if (((e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab) &&
          count() > 1 && e->modifiers() & Qt::ControlModifier)
                page = 0;
            }
            if (d->tabs->isTabEnabled(page)) {
                setCurrentIndex(page);
                break;
            }

.... blablablbalbla

}
if (!qApp->focusWidget()) <--------- THIS IS PROBLEM d->tabs->setFocus(); <--------- THIS IS PROBLEM
} else {

        e->ignore();
    }

}

So, QT always handles tab key at this place, and if qApp->focusWidget() returns NULL our focus is jailed into tabbar, and we must use mouse to get out of tabbar. That's because we set QtClickFocus on all widgets with TabStop=TRUE, and tabbar searches for widget with QtStrongFocus or QtTabFocus.

So, in short - we have two solutions:

1.QLCLTabWidget which overrides keyPressEvent().
2.Write completely new TQtTabWidget from stratch.

Den ?

zeljko

Den Jean
to zeljko
zeljko wrote 7 lines
Hi all, After latest patches about focuspolicy (I've completely removed handling of tab & backtab from qt, now LCL controls that part), we have pending problem with QTabWidget. QTabWidget::keyPressEvent(QKeyEvent *e) drive us into problem since it handles Tab key before that event is passed to LCL, and sets focus to tabbar.

I am not convinced the analysis is correct, focus is probably not nil.

The Qt tab dialog
see example program qt-x11-opensource-src-4.4.3/examples/dialogs/tabdialog works correctly, you can tab from child field to
child field and Ctrl-tab to next page.

Show quoted text 17 lines
Original code is here (shorten) void QTabWidget::keyPressEvent(QKeyEvent *e) .... blablablbalbla } if (!qApp->focusWidget()) <--------- THIS IS PROBLEM d->tabs->setFocus(); <--------- THIS IS PROBLEM } else { e->ignore(); } So, QT always handles tab key at this place, and if qApp->focusWidget() returns NULL our focus is jailed into tabbar, and we must use mouse to get out of tabbar. That's because we set QtClickFocus on all widgets with TabStop=TRUE, and tabbar searches for widget with QtStrongFocus or QtTabFocus.

Though the binding does not allow overriding of virtual methods in pascal and we sometimes need to manually write qlcl* to override stuff, note however that almost all these methods are called upon from the eventfilter, if you carefully craft your eventfilter, the unwanted call to keyPressEvent can be avoided.

Anyhow if you let Qt do its work -> it works fine, it you want to silence (shut up) Qt and let LCL do this work, well you should be able to this with the eventfilters. The fact that it does not work now, is proof that your existing eventfilters manage to shut up Qt, but the correct LCL calls are not there!

I will look into your eventfilters

kind regards,

Den Jean

zeljko
to Den Jean
Den Jean wrote 5 lines
Though the binding does not allow overriding of virtual methods in pascal and we sometimes need to manually write qlcl* to override stuff, note however that almost all these methods are called upon from the eventfilter, if you carefully craft your eventfilter, the unwanted call to keyPressEvent can be avoided.

Hm....I've already tried to "shut up" qtabbar & qtabwidget by setting result to true in eventFilter if Key=TAB or BACKTAB, and sent SlotKey() to LCL - but nothing happens.

Show quoted text 6 lines
Anyhow if you let Qt do its work -> it works fine, it you want to silence (shut up) Qt and let LCL do this work, well you should be able to this with the eventfilters. The fact that it does not work now, is proof that your existing eventfilters manage to shut up Qt, but the correct LCL calls are not there!

We'll .... it's possible that LCL calls are incorrect , I've lost some time against this problem and couldn't find the way to fix it.

I will look into your eventfilters

tnx.

z.

Den Jean
to zeljko
zeljko wrote
We'll .... it's possible that LCL calls are incorrect , I've lost some time against this problem and couldn't find the way to fix it.

try this for a starter, should move this temp ugly fix to a more appropriate place in lcl/qt, probably you know better, problem is that LCL/qt/NoteBook does not return it is focused.

Index: lcl/include/application.inc
=================================================================== --- lcl/include/application.inc (revision 18497)
+++ lcl/include/application.inc (working copy)
@@ -1840,10 +1840,12 @@
procedure TApplication.DoTabKey(AControl: TWinControl; var Key: Word;

   Shift: TShiftState);

begin
+writeln('====@@@*** DoTabKey called on ',AControl.ClassName,' with anoTabToSelectNext in Navigation:',anoTabToSelectNext in Navigation,' AControl.Focused:',AControl.Focused,' not WANTSPECIALKEY:',AControl.Perform(CM_WANTSPECIALKEY, Key, 0) = 0); if (Key = VK_TAB) and ((Shift - [ssShift]) = []) and
- (anoTabToSelectNext in Navigation) and AControl.Focused and
+ (anoTabToSelectNext in Navigation) and (AControl.Focused or (AControl.ClassName='TNotebook')) and (AControl.Perform(CM_WANTSPECIALKEY, Key, 0) = 0) then

   begin

+ writeln(' DoTabKey calls AControl.PerformTab on:',AControl.ClassName);

     // traverse tabstop controls inside form
     AControl.PerformTab(not (ssShift in Shift));
     Key := VK_UNKNOWN;
zeljko
to Den Jean
Den Jean wrote 7 lines
On Thursday 29 January 2009 21:15:43 zeljko wrote: > We'll .... it's possible that LCL calls are incorrect , I've lost some > time against this problem and couldn't find the way to fix it. try this for a starter, should move this temp ugly fix to a more appropriate place in lcl/qt, probably you know better, problem is that LCL/qt/NoteBook does not return it is focused.

yes, that's ugly patch, I'll fix it in another way ... inside qt. TQtWinApi.getFocus() is quilty for that, I mean FTabBar is pure QWidget and QApplication_focusWidget() returns that one, but FTabBar isn't TQtWidget ... so that's problem :)
I didn't test for focus since visually TabBar have focus :) tnx for analysis.

z

Show quoted text 31 lines
Index: lcl/include/application.inc =================================================================== --- lcl/include/application.inc (revision 18497) +++ lcl/include/application.inc (working copy) @@ -1840,10 +1840,12 @@ procedure TApplication.DoTabKey(AControl: TWinControl; var Key: Word; Shift: TShiftState); begin +writeln('====@@@*** DoTabKey called on ',AControl.ClassName,' with anoTabToSelectNext in Navigation:',anoTabToSelectNext in Navigation,' AControl.Focused:',AControl.Focused,' not WANTSPECIALKEY:',AControl.Perform(CM_WANTSPECIALKEY, Key, 0) = 0); if (Key = VK_TAB) and ((Shift - [ssShift]) = []) and - (anoTabToSelectNext in Navigation) and AControl.Focused and + (anoTabToSelectNext in Navigation) and (AControl.Focused or (AControl.ClassName='TNotebook')) and (AControl.Perform(CM_WANTSPECIALKEY, Key, 0) = 0) then begin + writeln(' DoTabKey calls AControl.PerformTab on:',AControl.ClassName); // traverse tabstop controls inside form AControl.PerformTab(not (ssShift in Shift)); Key := VK_UNKNOWN; _______________________________________________ Qt mailing list http://www.lazarus.freepascal.org/mailman/listinfo/qt
Unknown author
yes, that's ugly patch, I'll fix it in another way ... inside qt. TQtWinApi.getFocus() is quilty for that, I mean FTabBar is pure QWidget and QApplication_focusWidget() returns that one, but FTabBar isn't TQtWidget ...

Well this one liner is pretty.
As Tabbar is private subwidget, the solution
to return public TabWidget is acceptable.

Index: lcl/interfaces/qt/qtwidgets.pas
===================================================================
--- lcl/interfaces/qt/qtwidgets.pas	(revision 18503)
+++ lcl/interfaces/qt/qtwidgets.pas	(working copy)
@@ -5590,6 +5590,7 @@
      objectName is qt_tabwidget_tabbar.}
     FTabBar := QLCLTabWidget_tabBarHandle(QTabWidgetH(Widget));
     QWidget_setFocusPolicy(FTabBar, QtNoFocus);
+    setProperty(FTabBar, 'lclwidget', Int64(PtrUInt(Self)));
   end;
   Result := FTabBar;
 end;
zeljko
to Unknown author
Show quoted text 22 lines
>yes, that's ugly patch, I'll fix it in another way ... inside qt. >TQtWinApi.getFocus() is quilty for that, I mean FTabBar is pure QWidget > and QApplication_focusWidget() returns that one, but FTabBar isn't > TQtWidget ... Well this one liner is pretty. As Tabbar is private subwidget, the solution to return public TabWidget is acceptable. Index: lcl/interfaces/qt/qtwidgets.pas =================================================================== --- lcl/interfaces/qt/qtwidgets.pas (revision 18503) +++ lcl/interfaces/qt/qtwidgets.pas (working copy) @@ -5590,6 +5590,7 @@ objectName is qt_tabwidget_tabbar.} FTabBar := QLCLTabWidget_tabBarHandle(QTabWidgetH(Widget)); QWidget_setFocusPolicy(FTabBar, QtNoFocus); + setProperty(FTabBar, 'lclwidget', Int64(PtrUInt(Self))); end; Result := FTabBar; end;

no, I've already introduced TQtTabBar (but firs on my mind was adding property) instead of adding property to FTabBar.
I'll extend TQtTabBar later so it can be created as separate widget, so we can get better control from LCL over it.

tnx.

zeljko