libyui-qt  2.52.2
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 }
virtual void updateCustomStatusIndicator(YItem *item)
Update the status indicator (the status icon) for an item.
void itemClicked(YQCustomStatusSelectorItemWidget *itemWidget)
Cycle the status of an item and report the click to the calling application.
Class for the widgets of one YQCustomStatusItemSelector item.
virtual void addItem(YItem *item)
Add an item.
const QIcon & statusIcon(int status) const
Return the status icon for the specified status.
void clicked(YQCustomStatusSelectorItemWidget *itemWidget)
Emitted when the user clicks on the heading toggle to change the status or uses a keyboard operation ...
virtual void createWidgets()
Create the subwidgets.
YQCustomStatusItemSelector(YWidget *parent, const YItemCustomStatusVector &customStates)
Constructor.
virtual void activateItem(YItem *item)
Activate selected item.
YQCustomStatusSelectorItemWidget(YQItemSelector *parent, YItem *item)
Constructor.
QIcon loadIcon(const string &iconName) const
Load an icon.
Definition: YQUI.cc:708
void preloadStatusIcons()
Preload and cache the status icons.
ItemSelector widget with support for custom status values, not just 0 or 1.
void setStatusIcon()
Set the correct status icon according to the status of this item.
void slotClicked()
Forwarder slot from the heading toggle to this class.
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 ~YQCustomStatusSelectorItemWidget()
Destructor.
virtual QAbstractButton * createHeadingToggle(const std::string &label, QWidget *parent)
Create the appropriate toggle button for this item and connect it to appropriate slots.
virtual ~YQCustomStatusItemSelector()
Destructor.
Class for the widgets of one ItemSelector item.
virtual void selectItem(YItem *item, bool selected=true)
Select or deselect an item.
virtual int itemDescriptionIndent() const
Return the amount of indentation in pixels for the description text.
static YQUI * ui()
Access the global Qt-UI.
Definition: YQUI.h:83