libyui-qt  2.53.0
YQCustomStatusItemSelector.cc
1 /*
2  Copyright (C) 2019 SUSE LLC
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: YQCustomStatusItemSelector.cc
20 
21  Author: Stefan Hundhammer <shundhammer@suse.de>
22 
23 /-*/
24 
25 
26 #include <QToolButton>
27 
28 #define YUILogComponent "qt-ui"
29 #include <yui/YUILog.h>
30 #include <yui/YEvent.h>
31 #include "utf8.h"
32 #include "YQCustomStatusItemSelector.h"
33 #include "YQUI.h"
34 
35 
37  const YItemCustomStatusVector & customStates )
38  : YQItemSelector( parent, customStates )
39 {
41 }
42 
43 
45 {
46  // NOP
47 }
48 
49 
51 {
52  _statusIcons.clear();
53 
54  for ( int i=0; i < customStatusCount(); ++i )
55  _statusIcons << YQUI::ui()->loadIcon( customStatus( i ).iconName() );
56 }
57 
58 
60 {
61  YUI_CHECK_PTR( item );
62  YItemSelector::addItem( item );
63 
65  new YQCustomStatusSelectorItemWidget( this, item );
66  YUI_CHECK_NEW( itemWidget );
67 
68  itemWidget->createWidgets();
69  _itemWidgets[ item ] = itemWidget;
70 
71  connect( itemWidget, &pclass( itemWidget )::clicked,
72  this, &pclass( this )::itemClicked );
73 
74  // Intentionally not trying to deselect all other items if this one is
75  // selected because custom status mode guarantees not to have single
76  // selection.
77 }
78 
79 
80 void YQCustomStatusItemSelector::selectItem( YItem * item, bool selected )
81 {
82  item->setSelected( selected );
84 }
85 
86 
87 const QIcon &
89 {
90  static QIcon nullIcon = QIcon();
91 
92  if ( status >= 0 && status < _statusIcons.size() )
93  return _statusIcons.at( status );
94  else
95  return nullIcon;
96 }
97 
98 
100 {
101  YQSelectorItemWidget * itemWidgetBase = _itemWidgets.value( item );
102 
103  if ( ! itemWidgetBase )
104  YUI_THROW( YUIException( "Can't find selected item" ) );
105 
106  YQCustomStatusSelectorItemWidget * itemWidget =
107  dynamic_cast<YQCustomStatusSelectorItemWidget *>( itemWidgetBase );
108 
109  if ( itemWidget )
110  itemWidget->setStatusIcon();
111 }
112 
113 
115 {
116  YUI_CHECK_PTR( itemWidget );
117  YItem * item = itemWidget->item();
118 
119  int oldStatus = item->status();
120  int newStatus = cycleCustomStatus( oldStatus );
121 
122  yuiDebug() << "User clicked on item \"" << item->label() << "\""
123  << "; new status: " << newStatus
124  << endl;
125 
126  if ( newStatus >= 0 && newStatus != oldStatus )
127  {
128  item->setStatus( newStatus );
129  itemWidget->setStatusIcon();
130  }
131 
132  // Send the event even if newStatus == -1: This is particularly interesting
133  // for the application so it can handle this on the application level.
134  //
135  // It might not always be useful or practical for the application to
136  // predefine a status transition in the custom status table, in particular
137  // if the next status to use depends on other information.
138 
139  if ( notify() )
140  YQUI::ui()->sendEvent( new YMenuEvent( item ) );
141 }
142 
143 
145 {
146  // send an activation event for this widget
147  if ( notify() )
148  YQUI::ui()->sendEvent( new YMenuEvent( item ) );
149 }
150 
151 
152 
153 //-----------------------------------------------------------------------------
154 
155 
156 
157 
159  YItem * item )
160  : YQSelectorItemWidget( parent, item )
161 {
162 
163 }
164 
165 
167 {
168  // NOP
169 }
170 
171 
172 QAbstractButton *
174  QWidget * parent )
175 {
176  QToolButton * toggle = new QToolButton( this );
177  YUI_CHECK_NEW( toggle );
178  toggle->setText( " " + fromUTF8( label ) );
179  toggle->setAutoRaise( true );
180  toggle->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
181  toggle->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, // horizontal: let it grow
182  QSizePolicy::Fixed ) ); // vertical: use sizeHint()
183  setStatusIcon( toggle );
184 
185  connect( toggle, &pclass( toggle )::clicked,
186  this, &pclass( this )::slotClicked );
187 
188  return toggle;
189 }
190 
191 
193 {
194  setStatusIcon( _headingToggle );
195 }
196 
197 
198 void YQCustomStatusSelectorItemWidget::setStatusIcon( QAbstractButton * toggle )
199 {
200  int status = _item->status();
201 
202  if ( ! _parent->validCustomStatusIndex( status ) )
203  {
204  yuiError() << "Invalid status " << status << " for item " << _item << endl;
205  status = 0;
206  }
207 
208  YQCustomStatusItemSelector * parent = dynamic_cast<YQCustomStatusItemSelector *>( _parent );
209 
210  if ( parent )
211  {
212  QIcon icon = parent->statusIcon( status );
213 
214  if ( ! icon.isNull() )
215  toggle->setIcon( icon );
216  }
217 }
218 
219 
221 {
222  // This magic number in should really come from the widget style and some
223  // queries like
224  //
225  // style()->pixelMetric( QStyle::PM_RadioButtonLabelSpacing );
226  //
227  // and then added up from all the necessary individual pieces. But most
228  // of those things are never clearly specified. In the Qt code itself
229  // there are gems like "width += 4" at strategic places. So there is no
230  // realistic way for us on this level to do that right.
231 
232  return 24;
233 }
234 
235 
237 {
238  emit clicked( this );
239 }
ItemSelector widget with support for custom status values, not just 0 or 1.
const QIcon & statusIcon(int status) const
Return the status icon for the specified status.
virtual ~YQCustomStatusItemSelector()
Destructor.
virtual void activateItem(YItem *item)
Activate selected item.
virtual void selectItem(YItem *item, bool selected=true)
Select or deselect an item.
virtual void updateCustomStatusIndicator(YItem *item)
Update the status indicator (the status icon) for an item.
void preloadStatusIcons()
Preload and cache the status icons.
void itemClicked(YQCustomStatusSelectorItemWidget *itemWidget)
Cycle the status of an item and report the click to the calling application.
YQCustomStatusItemSelector(YWidget *parent, const YItemCustomStatusVector &customStates)
Constructor.
virtual void addItem(YItem *item)
Add an item.
Class for the widgets of one YQCustomStatusItemSelector item.
void slotClicked()
Forwarder slot from the heading toggle to this class.
virtual int itemDescriptionIndent() const
Return the amount of indentation in pixels for the description text.
void clicked(YQCustomStatusSelectorItemWidget *itemWidget)
Emitted when the user clicks on the heading toggle to change the status or uses a keyboard operation ...
virtual QAbstractButton * createHeadingToggle(const std::string &label, QWidget *parent)
Create the appropriate toggle button for this item and connect it to appropriate slots.
YQCustomStatusSelectorItemWidget(YQItemSelector *parent, YItem *item)
Constructor.
void setStatusIcon()
Set the correct status icon according to the status of this item.
Class for the widgets of one ItemSelector item.
virtual void createWidgets()
Create the subwidgets.
static YQUI * ui()
Access the global Qt-UI.
Definition: YQUI.h:83
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
QIcon loadIcon(const string &iconName) const
Load an icon.
Definition: YQUI.cc:708