libyui-qt  2.56.2
YQMenuButton.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  Copyright (C) 2020 SUSE LLC
4  This library is free software; you can redistribute it and/or modify
5  it under the terms of the GNU Lesser General Public License as
6  published by the Free Software Foundation; either version 2.1 of the
7  License, or (at your option) version 3.0 of the License. This library
8  is distributed in the hope that it will be useful, but WITHOUT ANY
9  WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
11  License for more details. You should have received a copy of the GNU
12  Lesser General Public License along with this library; if not, write
13  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
14  Floor, Boston, MA 02110-1301 USA
15 */
16 
17 
18 /*-/
19 
20  File: YQMenuButton.cc
21 
22  Author: Stefan Hundhammer <shundhammer@suse.de>
23 
24 /-*/
25 
26 
27 #include <QPushButton>
28 #include <QMenu>
29 #include <QSize>
30 #include <QTimer>
31 
32 #define YUILogComponent "qt-ui"
33 #include <yui/YUILog.h>
34 
35 #include "utf8.h"
36 #include "YQUI.h"
37 #include "YQMenuButton.h"
38 #include <yui/YEvent.h>
39 
40 using std::string;
41 
42 
43 
44 YQMenuButton::YQMenuButton( YWidget * parent,
45  const string & label )
46  : QWidget( (QWidget *) parent->widgetRep() )
47  , YMenuButton( parent, label )
48  , _selectedItem( 0 )
49 {
50  setWidgetRep( this );
51  _qt_button = new QPushButton( fromUTF8( label ), this );
52  _qt_button->move( YQButtonBorder, YQButtonBorder );
53  setMinimumSize( _qt_button->minimumSize()
54  + 2 * QSize( YQButtonBorder, YQButtonBorder ) );
55 }
56 
57 
59 {
60  // NOP
61 }
62 
63 
64 void
65 YQMenuButton::setLabel( const string & label )
66 {
67  _qt_button->setText( fromUTF8( label ) );
68  YMenuButton::setLabel( label );
69 }
70 
71 
72 void
74 {
75  //
76  // Delete any previous menu
77  // (in case the menu items got replaced)
78  //
79 
80  _actionMap.clear();
81  _selectedItem = 0;
82 
83  if ( _qt_button->menu() )
84  delete _qt_button->menu();
85 
86 
87  //
88  // Create toplevel menu
89  //
90 
91  QMenu * menu = new QMenu( _qt_button );
92  YUI_CHECK_NEW( menu );
93  _qt_button->setMenu( menu );
94  menu->setProperty( "class", "ymenubutton QMenu" );
95 
96  connect( menu, &pclass(menu)::triggered,
97  this, &pclass(this)::menuEntryActivated );
98 
99  //
100  // Recursively add Qt menu items from the YMenuItems
101  //
102 
103  rebuildMenuTree( menu, itemsBegin(), itemsEnd() );
104 }
105 
106 
107 void
108 YQMenuButton::rebuildMenuTree( QMenu * parentMenu, YItemIterator begin, YItemIterator end )
109 {
110  for ( YItemIterator it = begin; it != end; ++it )
111  {
112  YMenuItem * item = dynamic_cast<YMenuItem *>( *it );
113  YUI_CHECK_PTR( item );
114  QIcon icon;
115 
116  if ( item->hasIconName() )
117  icon = YQUI::ui()->loadIcon( item->iconName() );
118 
119  if ( item->isSeparator() )
120  {
121  parentMenu->addSeparator();
122  }
123  else if ( item->isMenu() )
124  {
125  QMenu * subMenu = parentMenu->addMenu( fromUTF8( item->label() ));
126  item->setUiItem( subMenu );
127 
128  if ( ! icon.isNull() )
129  subMenu->setIcon( icon );
130 
131  connect( subMenu, &pclass(subMenu)::triggered,
132  this, &pclass(this)::menuEntryActivated );
133 
134  rebuildMenuTree( subMenu, item->childrenBegin(), item->childrenEnd() );
135  }
136  else // Plain menu item (leaf item)
137  {
138  // item->index() is guaranteed to be unique within this YMenuButton's items,
139  // so it can easily be used as unique ID in all Q3PopupMenus that belong
140  // to this YQMenuButton.
141 
142  QAction * action = parentMenu->addAction( fromUTF8( item->label() ) );
143  item->setUiItem( action );
144  _actionMap[ action ] = item;
145 
146  if ( ! icon.isNull() )
147  action->setIcon( icon );
148  }
149  }
150 }
151 
152 
153 void
155 {
156  if ( _actionMap.contains( action ) )
157  _selectedItem = _actionMap[ action ];
158 
159  if ( _selectedItem )
160  {
161  // yuiDebug() << "Selected menu entry \"" << fromUTF8( _selectedItem->label() ) << "\"" << endl;
162 
163  /*
164  * Defer the real returnNow() until all popup related events have been
165  * processed. This took me some hours to figure out; obviously
166  * exit_loop() doesn't have any effect as long as there are still
167  * popups open. So be it - use a zero timer to perform the real
168  * returnNow() later.
169  */
170 
171  /*
172  * The 100 delay is an ugly dirty workaround.
173  */
174  QTimer::singleShot( 100, this, SLOT( returnNow() ) );
175  }
176  else
177  {
178  yuiError() << "Unknown action \"" << action->text() << "\"" << endl;
179  }
180 }
181 
182 
183 void
185 {
186  if ( _selectedItem )
187  {
188  YQUI::ui()->sendEvent( new YMenuEvent( _selectedItem ) );
189  _selectedItem = 0;
190  }
191 }
192 
193 
194 void
195 YQMenuButton::setItemEnabled( YMenuItem * item, bool enabled )
196 {
197  QObject * qObj = static_cast<QObject *>( item->uiItem() );
198 
199  if ( qObj )
200  {
201  QMenu * menu = qobject_cast<QMenu *>( qObj );
202 
203  if ( menu )
204  menu->setEnabled( enabled );
205  else
206  {
207  QAction * action = qobject_cast<QAction *>( qObj );
208 
209  if ( action )
210  action->setEnabled( enabled );
211  }
212  }
213 
214  YMenuWidget::setItemEnabled( item, enabled );
215 }
216 
217 
218 void
220 {
221  _qt_button->setEnabled( enabled );
222  YWidget::setEnabled( enabled );
223 }
224 
225 
227 {
228  return 2*YQButtonBorder + _qt_button->sizeHint().width();
229 }
230 
231 
233 {
234  return 2*YQButtonBorder + _qt_button->sizeHint().height();
235 }
236 
237 
238 void
239 YQMenuButton::setSize( int newWidth, int newHeight )
240 {
241  _qt_button->resize( newWidth - 2 * YQButtonBorder,
242  newHeight - 2 * YQButtonBorder );
243  resize( newWidth, newHeight );
244 }
245 
246 
247 bool
249 {
250  _qt_button->setFocus();
251 
252  return true;
253 }
254 
255 
256 void
257 YQMenuButton::activateItem( YMenuItem * item )
258 {
259  if ( item )
260  YQUI::ui()->sendEvent( new YMenuEvent( item ) );
261 }
YQUI::sendEvent
void sendEvent(YEvent *event)
Widget event handlers (slots) call this when an event occured that should be the answer to a UserInpu...
Definition: YQUI.cc:480
YQMenuButton::preferredHeight
virtual int preferredHeight()
Preferred height of the widget.
Definition: YQMenuButton.cc:232
YQMenuButton::returnNow
void returnNow()
Triggered via menuEntryActivated() by zero timer to get back in sync with the Qt event loop.
Definition: YQMenuButton.cc:184
YQMenuButton::~YQMenuButton
virtual ~YQMenuButton()
Destructor.
Definition: YQMenuButton.cc:58
YQMenuButton::setSize
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
Definition: YQMenuButton.cc:239
YQMenuButton::rebuildMenuTree
virtual void rebuildMenuTree()
Rebuild the displayed menu tree from the internally stored YMenuItems.
Definition: YQMenuButton.cc:73
YQMenuButton::preferredWidth
virtual int preferredWidth()
Preferred width of the widget.
Definition: YQMenuButton.cc:226
YQMenuButton::menuEntryActivated
void menuEntryActivated(QAction *menuItem)
Triggered when any menu item is activated.
Definition: YQMenuButton.cc:154
YQMenuButton::YQMenuButton
YQMenuButton(YWidget *parent, const std::string &label)
Constructor.
Definition: YQMenuButton.cc:44
YQMenuButton::setItemEnabled
virtual void setItemEnabled(YMenuItem *item, bool enabled)
Enable or disable an item.
Definition: YQMenuButton.cc:195
YQUI::ui
static YQUI * ui()
Access the global Qt-UI.
Definition: YQUI.h:83
YQMenuButton::setEnabled
virtual void setEnabled(bool enabled)
Set enabled / disabled state.
Definition: YQMenuButton.cc:219
YQMenuButton::setKeyboardFocus
virtual bool setKeyboardFocus()
Accept the keyboard focus.
Definition: YQMenuButton.cc:248
YQMenuButton::setLabel
virtual void setLabel(const std::string &label)
Change the label on the button.
Definition: YQMenuButton.cc:65
YQMenuButton::activateItem
virtual void activateItem(YMenuItem *item)
Activate the item selected in the tree.
Definition: YQMenuButton.cc:257
YQUI::loadIcon
QIcon loadIcon(const string &iconName) const
Load an icon.
Definition: YQUI.cc:708