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