Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 2

Qt-interest Archive, January 2002
Connecting focus


Message 1 in thread

I have some menu items that I would like to have
enabled only when a certain tab in a TabView is
the current selection and other menu items that
I would like to enable only when a TextEdit has
been selected. How can I connect this input focus
to something? QWidget::focusInEvent() and
QWidget::focusOutEvent() are not appearing in
the connections dialog for these widgets.

Thanks in advance,
-- 
 [ signature omitted ] 

Message 2 in thread

I had a similar problem. For the textedits, I just overloaded 
focusIn/OutEvent() to emit lostFocus and gainedFocus (two custom signals). I 
imagine it wouldn't be much different for the tabs.

ry

On Sunday 06 January 2002 05:17 pm, Jeff Shipman wrote:
> I have some menu items that I would like to have
> enabled only when a certain tab in a TabView is
> the current selection and other menu items that
> I would like to enable only when a TextEdit has
> been selected. How can I connect this input focus
> to something? QWidget::focusInEvent() and
> QWidget::focusOutEvent() are not appearing in
> the connections dialog for these widgets.
>
> Thanks in advance,
-- 
 [ signature omitted ] 

Message 3 in thread

ryan bobko wrote:

> I had a similar problem. For the textedits, I just overloaded 
> focusIn/OutEvent() to emit lostFocus and gainedFocus (two custom signals). I 
> imagine it wouldn't be much different for the tabs.
> 
> ry
> 
> On Sunday 06 January 2002 05:17 pm, Jeff Shipman wrote:
> 
>>I have some menu items that I would like to have
>>enabled only when a certain tab in a TabView is
>>the current selection and other menu items that
>>I would like to enable only when a TextEdit has
>>been selected. How can I connect this input focus
>>to something? QWidget::focusInEvent() and
>>QWidget::focusOutEvent() are not appearing in
>>the connections dialog for these widgets.
>>
>>Thanks in advance,
>>

How do you do this, though? I tried making a function
called void QTextEdit::focusInEvent(QFocusEvent *e), but
I get the error:

main.cpp:43: no `void QTextEdit::focusInEvent(QFocusEvent *)' member 
function declared in class `QTextEdit'

Plus, I don't want it to happen with _every_ TextEdit
and TabView in my application, just a certain one. Does
this mean I would have to subclass? If so, is there a way
to use my subclassed widget inside the designer?

These are probably elementary questions related to C++,
but I'm also new with C++. I'd appreciate any help or
examples you can provide.

Thank you.

-- 
 [ signature omitted ] 

Message 4 in thread

Hello,

Couldn't you just use the QWidget::setFocus() slot and connect that to your 
menu's?

Maybe I missed something, but that would be the simplest thing to do and it 
would not require you to subclass the QTextEdit widget.

Wynn


Message 5 in thread

Hi,

> ryan bobko wrote:
> 
> > I had a similar problem. For the textedits, I just overloaded
> > focusIn/OutEvent() to emit lostFocus and gainedFocus (two 
> custom signals). I 
> > imagine it wouldn't be much different for the tabs.
> > 
> > ry
> > 
> > On Sunday 06 January 2002 05:17 pm, Jeff Shipman wrote:
> > 
> >>I have some menu items that I would like to have
> >>enabled only when a certain tab in a TabView is
> >>the current selection and other menu items that
> >>I would like to enable only when a TextEdit has
> >>been selected. How can I connect this input focus
> >>to something? QWidget::focusInEvent() and
> >>QWidget::focusOutEvent() are not appearing in
> >>the connections dialog for these widgets.
> >>
> >>Thanks in advance,
> >>
> 
> How do you do this, though? I tried making a function
> called void QTextEdit::focusInEvent(QFocusEvent *e), but
> I get the error:
> 
> main.cpp:43: no `void QTextEdit::focusInEvent(QFocusEvent *)' member 
> function declared in class `QTextEdit'

You need to subclass QTextEdit and override the focus events,
remembering to call the inherited ones.

> Plus, I don't want it to happen with _every_ TextEdit
> and TabView in my application, just a certain one.

Then you just connect the signals from that one text editor to the
appropriate slots.  If a widget emits a signal which hasn't been
connected up, then the signals go "nowhere", which is just what you
want, no?

> Does
> this mean I would have to subclass? If so, is there a way
> to use my subclassed widget inside the designer?

Yes, it's in the Designer documentation under Custom Widgets.  I've done
this a lot recently, and my widgets work as sweet as a nut in designer.

-- Paul.


Message 6 in thread

Hi,

> Couldn't you just use the QWidget::setFocus() slot and 
> connect that to your 
> menu's?

You connect signals to slots; setFocus is not a signal so it isn't a
stimulus and can't be used as you describe.

> Maybe I missed something, but that would be the simplest 
> thing to do and it 
> would not require you to subclass the QTextEdit widget.

If you want to know when your widget gains and relinquishes focus, then
you'll need the focus events.

-- Paul.


Message 7 in thread


Paul Curtis schrieb:
> 
> Hi,
> 
> > Couldn't you just use the QWidget::setFocus() slot and
> > connect that to your
> > menu's?
> 
> You connect signals to slots; setFocus is not a signal so it isn't a
> stimulus and can't be used as you describe.

Obviously what he meant was to connect the menu's clicked signal to the
setFocus slot.

> > Maybe I missed something, but that would be the simplest
> > thing to do and it
> > would not require you to subclass the QTextEdit widget.
> 
> If you want to know when your widget gains and relinquishes focus, then
> you'll need the focus events.

That is unfortunately true, though I absolutely hate it. Why can't
Trolltech just simply have the widgets emit a "focusGained" and
"focusLost" signal upon that event?

Greetings,
Arne


Message 8 in thread

Arne,

> > > Couldn't you just use the QWidget::setFocus() slot and connect
that 
> > > to your menu's?
> > 
> > You connect signals to slots; setFocus is not a signal so it isn't a

> > stimulus and can't be used as you describe.
> 
> Obviously what he meant was to connect the menu's clicked 
> signal to the setFocus slot.

The original question posed was to enable a menu item based upon the
focused state of a widget: when that widget is focused, the menu item
should be enabled, else not.  Your "corrected" connection scheme doesn't
work.  I present the way that I deal with this type of situation in code
below.

> > > Maybe I missed something, but that would be the simplest thing to
do 
> > > and it would not require you to subclass the QTextEdit widget.
> > 
> > If you want to know when your widget gains and relinquishes focus, 
> > then you'll need the focus events.
> 
> That is unfortunately true, though I absolutely hate it. Why 
> can't Trolltech just simply have the widgets emit a 
> "focusGained" and "focusLost" signal upon that event?

Note that QWidget emits no signals whatsoever.  I believe that this is
possibly because the Trolls know that if they started to emit signals in
QWidget for one event type, they'd be asked to emit them for all event
types, and the whole world would be swamped with emits, sapping the
speed of applications.

It's no hardship to subclass.  As I don't use Designer to cook up my
forms, it's not an issue for me.  Designer doesn't do what I need for my
GUIs, and until it does it's consigned to the bit bucket.  I still
potter about now and then, and have added my own custom widgets to
Designer, but it's far too limited for my tastes.

Now, back to code.

The way that I typically deal with the poster's situation is to
periodically update the GUI, which is a centralised "now I'm ready to do
something, set the state" type of affair.  I install an event filter on
the application and listen in for all focusIn events.  My event filter
is like this:

bool
StudioWindow::eventFilter(QObject *o, QEvent *e)
{
  if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease)
    {
      setKeyboardStateLabels();  // CAPS, NUM, and others...
    }
  else if (e->type() == QEvent::FocusIn)
    {
      // Some guff removed here for my application and own style...
      updateGUI((QWidget *)o);
    }

  return QMainWindow::eventFilter(o, e);
}

Then, updateGUI does a lot of work.  This code shows what I do, and I've
cut it down a bit, but it gives you a flavor of what can be done, e.g.
enabling/disabling menu items based on focused widgets, filling in menu
entry text based of the focused widget, and using Qt's reflection
capability to enable/disable actions based on the slots presented by a
focused widget.  This is quite some code, but it shows what can be
done...

void
StudioWindow::updateGUI(QWidget *focus)
{
  // This code deals with not updating the underlying main window when a
popup or
  // something else is going on.  Found by extensive experimentation...
  if (!focus)
    focus = qApp->focusWidget();
  if (qApp->activePopupWidget())
    return;
  if (focus == menuBar())
    return;
  if (focus && focus->topLevelWidget() &&
focus->topLevelWidget()->inherits("QDialog"))
    return;

  // Do stuff with the focused widget...
  // Some more guff elided here

  // Typically I update things such as editor line/column information,
but also I update the main
  // window's caption based on a focused code editor.

  QString cap = PRODUCT_BRANDING;
  switch (m_state)
    {
      case editing: break;
      case building: cap += " [building]"; break;
      case debugging_run: cap += " [run]"; break;
      case debugging_stopped: cap += " [break]"; break;
    }
  if (!titleName.isEmpty())
    cap += QString(" - [%1]").arg(titleName);
  setCaption(cap);

  // Get the filename property associated with the current focused
widget.  Uses Qt's
  // property system.
  QString fileName;
  QWidget *widget = findProperty("fileName");
  if (widget)
    fileName = widget->property("fileName").toString();

  // I then set the action enabled/disabled depending upon what the
widget says it can do.
  // I use the reflection (meta) capabilities of Qt to see what slots a
widget procised, and then
  // enable or disable a menu entry based on that slot.  For instance,
multiple Qt widgets provide
  // cut/copy/paste slots (e.g. QTextEdit, QLineEdit, and my own
CodeEdit), so I use reflection to
  // see whether a widget provides the slot.  If it does, then I know I
can call cut() using a proxy
  // action, and the Edit|Cut menu item should be enabled.  I also see
whether there is a gating
  // predicate property, such as "cutAvailable" or "canCut"; if there's
a cut() slot but the canCut
  // property returns false, then I don't enable the menu item.

  setAction(actions->m_editCutAction,       SLOT(cut()),
"canCut");
  setAction(actions->m_editCopyAction,      SLOT(copy()),
"canCopy");
  setAction(actions->m_editPasteAction,     SLOT(paste()),
"canPaste");
  setAction(actions->m_editDeleteAction,    SLOT(del()),
"canDelete");
  setAction(actions->m_editRemoveAction,    SLOT(del()),
"canDelete");
  // etc.

  // This sets up some stuff in a derived QAction that, for instance,
turns
  // a regular menu item's menu text from "Save" to "Save <filename>",
where filename
  // is taken from the focused editor widget.  I derived a new type of
Qaction that can do this...
 
actions->m_fileSaveAction->setArgument(QFileInfo(fileName).fileName());
 
actions->m_fileSaveAsAction->setArgument(QFileInfo(fileName).fileName())
;

  // And now just some boilerplate other enable/disable stuff...
 
actions->m_solutionNewFileAction->setEnabled(m_projectWindow->selectedIt
em() != NULL);
 
actions->m_solutionAddExistingItemAction->setEnabled(m_projectWindow->se
lectedItem() != NULL);
 
actions->m_solutionAddNewItemAction->setEnabled(m_projectWindow->selecte
dItem() != NULL);
  actions->m_fileCloseSolutionAction->setEnabled(projectSystem &&
projectSystem->haveSolution());
}

The great thing about Qt 3 is the reflection stuff.  It means, for
instance, that I can provide a menu entry "Cut" that invokes the cut()
slot of the focused widget, and I enable or disable that by listening to
focusIn events using an event filter and using the property system to
query the capabilities of the focused widget.  This is how a lot of my
stuff is now done.  It means that my "Cut" menu entry will cut anything
from any widget if that widget presents a cut() slot; so, I design all
widgets now with cut/copy/paste/clear/refresh slots if applicable.

If anybody is interested in the nuts and bolts of this, I can at least
provide some assistance or code, or perhaps a demo project.

-- Paul.