Hello community, here is the log from the commit of package libyui for openSUSE:Factory checked in at 2019-11-08 15:23:35 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libyui (Old) and /work/SRC/openSUSE:Factory/.libyui.new.2990 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libyui" Fri Nov 8 15:23:35 2019 rev:44 rq:746292 version:3.8.4 Changes: -------- --- /work/SRC/openSUSE:Factory/libyui/libyui.changes 2019-10-28 16:44:57.552593479 +0100 +++ /work/SRC/openSUSE:Factory/.libyui.new.2990/libyui.changes 2019-11-08 15:23:38.134862087 +0100 @@ -1,0 +2,14 @@ +Thu Nov 7 13:18:33 UTC 2019 - Stefan Hundhammer <[email protected]> + +- Support item status getting and setting for ItemSelector + (bsc#1084674) +- 3.8.4 + +------------------------------------------------------------------- +Thu Oct 31 14:04:38 UTC 2019 - Stefan Hundhammer <[email protected]> + +- Support custom status values (int, not just bool) in ItemSelector + (bsc#1084674) +- 3.8.3 + +------------------------------------------------------------------- Old: ---- libyui-3.8.2.tar.bz2 New: ---- libyui-3.8.4.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libyui-doc.spec ++++++ --- /var/tmp/diff_new_pack.jPNbNl/_old 2019-11-08 15:23:38.998863001 +0100 +++ /var/tmp/diff_new_pack.jPNbNl/_new 2019-11-08 15:23:38.998863001 +0100 @@ -20,7 +20,7 @@ %define so_version 10 Name: %{parent}-doc -Version: 3.8.2 +Version: 3.8.4 Release: 0 Source: %{parent}-%{version}.tar.bz2 ++++++ libyui.spec ++++++ --- /var/tmp/diff_new_pack.jPNbNl/_old 2019-11-08 15:23:39.022863026 +0100 +++ /var/tmp/diff_new_pack.jPNbNl/_new 2019-11-08 15:23:39.026863030 +0100 @@ -17,7 +17,7 @@ Name: libyui -Version: 3.8.2 +Version: 3.8.4 Release: 0 Source: %{name}-%{version}.tar.bz2 ++++++ libyui-3.8.2.tar.bz2 -> libyui-3.8.4.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/SOURCECONF.cmake new/libyui-3.8.4/SOURCECONF.cmake --- old/libyui-3.8.2/SOURCECONF.cmake 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/SOURCECONF.cmake 2019-11-07 15:05:08.000000000 +0100 @@ -105,6 +105,7 @@ YEventFilter.h YEnvVar.h YItem.h + YItemCustomStatus.h YIconLoader.h YMenuItem.h YMacro.h @@ -188,15 +189,16 @@ ) SET( EXAMPLES_LIST - ComboBox1.cc ComboBox1-editable.cc + ComboBox1.cc + CustomStatusItemSelector1.cc HelloWorld.cc ItemSelector1.cc ItemSelector2-minimalistic.cc + ManyWidgets.cc + PollEvent.cc SelectionBox1.cc SelectionBox2.cc SelectionBox3-many-items.cc Table-many-items.cc - ManyWidgets.cc - PollEvent.cc ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/VERSION.cmake new/libyui-3.8.4/VERSION.cmake --- old/libyui-3.8.2/VERSION.cmake 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/VERSION.cmake 2019-11-07 15:05:08.000000000 +0100 @@ -1,6 +1,6 @@ SET( VERSION_MAJOR "3") SET( VERSION_MINOR "8" ) -SET( VERSION_PATCH "2" ) +SET( VERSION_PATCH "4" ) SET( VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${GIT_SHA1_VERSION}" ) ##### This is need for the libyui core, ONLY. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/examples/CustomStatusItemSelector1.cc new/libyui-3.8.4/examples/CustomStatusItemSelector1.cc --- old/libyui-3.8.2/examples/CustomStatusItemSelector1.cc 1970-01-01 01:00:00.000000000 +0100 +++ new/libyui-3.8.4/examples/CustomStatusItemSelector1.cc 2019-11-07 15:05:08.000000000 +0100 @@ -0,0 +1,380 @@ +/* + Copyright (c) [2019] SUSE LLC + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) version 3.0 of the License. This library + is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. You should have received a copy of the GNU + Lesser General Public License along with this library; if not, write + to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + Floor, Boston, MA 02110-1301 USA +*/ + + +// Example for ItemSelector with custom status values. +// +// Compile with: +// +// g++ -I/usr/include/yui -lyui ItemSelector3-custom-states.cc -o ItemSelector3-custom-states +// +// For a very simple ItemSelector example, see ItemSelector2-minimalistic.cc. + +#define YUILogComponent "example" +#include "YUILog.h" + +#include "YUI.h" +#include "YWidgetFactory.h" +#include "YDialog.h" +#include "YAlignment.h" +#include "YButtonBox.h" +#include "YCheckBox.h" +#include "YFrame.h" +#include "YIntField.h" +#include "YItemCustomStatus.h" +#include "YItemSelector.h" +#include "YLabel.h" +#include "YLayoutBox.h" +#include "YPushButton.h" +#include "YRadioButton.h" +#include "YRadioButtonGroup.h" +#include "YEvent.h" + + +using std::string; + + +// Config options set by askConfigValues() + +bool notify = true; +int visibleItems = 6; + + +// The custom status values are just integers. An enum is a good and simple way +// to use more speaking names. + +enum CustomStatus +{ + MOD_DONT_INSTALL = 0, + MOD_INSTALL, + MOD_AUTOINSTALL +}; + +// "Software modules" used in this example to show automatic dependency +// handling and thus status change from the application's business logic. + +YDescribedItem * modKde = 0; +YDescribedItem * modXfce = 0; +YDescribedItem * modX11 = 0; +YDescribedItem * modOffice = 0; +YDescribedItem * modServer = 0; +YDescribedItem * modSdk = 0; + + +// Widgets + +YDialog * dialog = 0; +YItemSelector * selector = 0; +YLabel * resultField = 0; +YPushButton * resultButton = 0; +YPushButton * closeButton = 0; + + +// Function prototypes + +void createWidgets(); +void handleEvents(); +void handleItemClick( YItem * item ); +void handleDependencies(); +void autoSelectIfNeeded( YItem * item, bool needed ); +void updateResultField(); +void askConfigValues(); + + + +int main( int argc, char **argv ) +{ + YUILog::setLogFileName( "/tmp/libyui-examples.log" ); + YUILog::enableDebugLogging(); + + askConfigValues(); + + createWidgets(); + handleEvents(); + + dialog->destroy(); +} + + +/** + * Create the widget tree for the main dialog + **/ +void createWidgets() +{ + yuiMilestone() << endl; + + YWidgetFactory * fac = YUI::widgetFactory(); + + dialog = fac->createPopupDialog(); + YAlignment * mbox = fac->createMarginBox( dialog, 2, 2, 0.4, 0.4 ); + YAlignment * minWidth = fac->createMinWidth( mbox, 60 ); + YLayoutBox * vbox = fac->createVBox( minWidth ); + + fac->createHeading( vbox, "Add-on Software" ); + fac->createVSpacing( vbox, 0.2 ); + + YItemCustomStatusVector states; + // iconName textIndicator nextStatus + states.push_back( YItemCustomStatus( "checkbox-off", "[ ]", MOD_INSTALL ) ); + states.push_back( YItemCustomStatus( "checkbox-on", "[ +]", MOD_DONT_INSTALL ) ); + states.push_back( YItemCustomStatus( "checkbox-auto-selected", "[a+]", MOD_DONT_INSTALL ) ); + + selector = fac->createCustomStatusItemSelector( vbox, states ); + YUI_CHECK_PTR( selector ); + + modKde = new YDescribedItem( "KDE Plasma", "Full-fledged desktop" ); + modXfce = new YDescribedItem( "Xfce", "Lightweight desktop" ); + modX11 = new YDescribedItem( "X Window System", "X11, simple window manager, xterm" ); + modOffice = new YDescribedItem( "LibreOffice", "Office suite" ); + modServer = new YDescribedItem( "Server Tools", "Web server, database, file server" ); + modSdk = new YDescribedItem( "SDK", "Development tools" ); + + YItemCollection items; + items.push_back( modKde ); + items.push_back( modXfce ); + items.push_back( modX11 ); + items.push_back( modOffice ); + items.push_back( modServer ); + items.push_back( modSdk ); + selector->addItems( items ); // This is more efficient than repeatedly calling selector->addItem() + + selector->setVisibleItems( visibleItems ); + + if ( notify ) + selector->setNotify(); + + fac->createVSpacing( vbox, 0.4 ); + + YLayoutBox * hbox2 = fac->createHBox( vbox ); + resultField = fac->createOutputField( hbox2, "<Result>\n\n\n\n\n" ); + resultField->setStretchable( YD_HORIZ, true ); // allow stretching over entire dialog width + + if ( ! notify ) + resultButton = fac->createPushButton( hbox2, "&Result" ); + + fac->createVSpacing( vbox, 0.3 ); + + YAlignment * rightAlignment = fac->createRight( vbox ); + closeButton = fac->createPushButton( rightAlignment, "&Close" ); +} + + +/** + * Event loop and event handling for the main dialog + **/ +void handleEvents() +{ + yuiMilestone() << endl; + + while ( true ) + { + YEvent * event = dialog->waitForEvent(); + + if ( event ) + { + if ( event->widget() == closeButton || + event->eventType() == YEvent::CancelEvent ) // window manager "close window" button + { + break; // leave event loop + } + + if ( event->widget() == resultButton ) + { + handleDependencies(); + updateResultField(); + } + + if ( event->widget() == selector ) + { + // No YWidgetEvents from the ItemSelector in this mode (see below) + } + + if ( event->eventType() == YEvent::MenuEvent ) + { + // In this mode, the ItemSelector does not send YWidgetEvents, + // but YMenuEvents since (unlike YWidgetEvents) they can + // return the item that was changed. + // + // Still, this requires setNotify() (the notify option to be set). + + YMenuEvent * menuEvent = dynamic_cast<YMenuEvent *>( event ); + + if ( menuEvent ) + handleItemClick( menuEvent->item() ); + + updateResultField(); + } + } + } +} + + +/** + * Handler for user interaction (click or keyboard) with the ItemSelector's items. + **/ +void handleItemClick( YItem * item ) +{ + if ( ! item ) // This might be a legitimate YMenuEvent without an item + return; + + yuiMilestone() << "Item \"" << item->label() << "\"" << endl; + handleDependencies(); +} + + +/** + * Example business logic: Change some status values based on other status values. + * + * If 'notify' is set, this is done automatically on each mouse click / + * keyboard selection in the selector. Otherwise, the user needs to use the + * "Result" button. + **/ +void handleDependencies() +{ + bool needX11 = false; + bool needOffice = false; + + if ( modKde->selected() ) // YItem::selected() means YItem::status() != 0 + { + needX11 = true; + needOffice = true; + } + + if ( modXfce->selected() ) + needX11 = true; + + if ( modOffice->status() == MOD_INSTALL ) // not if MOD_AUTOINSTALL! + needX11 = true; + + autoSelectIfNeeded( modOffice, needOffice ); + autoSelectIfNeeded( modX11, needX11 ); +} + + +/** + * Example business logic: Set or reset "autoinstall" status of 'item' + * depending on the 'needed' flag. + * + * Notice that it is required to use YItemSelector::setItemStatus(), not just + * YItem::setStatus(): The widget needs to be notified that the item's status + * changed so it can update the status icon in the UI. + **/ +void autoSelectIfNeeded( YItem * item, bool needed ) +{ + if ( needed && item->status() == MOD_DONT_INSTALL ) + selector->setItemStatus( item, MOD_AUTOINSTALL ); + + if ( ! needed && item->status() == MOD_AUTOINSTALL ) + selector->setItemStatus( item, MOD_DONT_INSTALL ); +} + + +/** + * Show the selected items in the results field. + **/ +void updateResultField() +{ + selector->dumpItems(); + string result = ""; + + // Iterate over the selected items, i.e. the items with status() != 0. + // We might also simply iterate over all items if that is desired. + + for ( YItem * item: selector->selectedItems() ) + { + string action; + + switch ( item->status() ) + { + case MOD_INSTALL: action = "Install"; break; + case MOD_AUTOINSTALL: action = "Auto-install"; break; + default: continue; // Skip everything else completely + } + + if ( ! result.empty() ) + result += "\n"; + + result += action + " module " + item->label(); + } + + resultField->setText( result ); +} + + + +/** + * Ask the user some configuration values for the main dialog. + * All values are stored in global variables. + * + * +---------------------------+ + * | Program Configuration | + * | | + * | [x] Notify | + * | | + * | Visible Items: | + * | [ 6 ] | + * | | + * | [Continue] [Cancel] | + * +---------------------------+ + **/ +void askConfigValues() +{ + yuiMilestone() << endl; + + YWidgetFactory * fac = YUI::widgetFactory(); + + YDialog * dialog = fac->createPopupDialog(); + YAlignment * mbox = fac->createMarginBox( dialog, 2, 2, 0.4, 0.4 ); + YLayoutBox * vbox = fac->createVBox( mbox ); + + fac->createHeading( vbox, "Example Configuration" ); + fac->createVSpacing( vbox, 0.6 ); + + YAlignment * left = fac->createLeft( vbox ); + YCheckBox * notifyCheckBox = fac->createCheckBox( left, "&Notify", notify ); + + fac->createVSpacing( vbox, 0.6 ); + left = fac->createLeft( vbox ); + YIntField * visibleItemsField = fac->createIntField( left, "&Visible Items:", 1, 10, visibleItems ); + + fac->createVSpacing( vbox, 1 ); + + YButtonBox * buttonBox = fac->createButtonBox( vbox ); + YPushButton * continueButton = fac->createPushButton( buttonBox, "C&ontinue" ); + YPushButton * cancelButton = fac->createPushButton( buttonBox, "&Cancel" ); + + continueButton->setRole( YOKButton ); + continueButton->setDefaultButton(); + cancelButton->setRole( YCancelButton ); + + YEvent * event = dialog->waitForEvent(); + + if ( event->widget() == continueButton ) + { + notify = notifyCheckBox->value(); + visibleItems = visibleItemsField->value(); + + yuiMilestone() << "Notify: " << notify << endl; + yuiMilestone() << "Visible items: " << visibleItems << endl; + } + else if ( event->widget() == cancelButton || + event->eventType() == YEvent::CancelEvent ) // window manager "close window" button + { + dialog->destroy(); + exit( 1 ); + } + + dialog->destroy(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/examples/ItemSelector1.cc new/libyui-3.8.4/examples/ItemSelector1.cc --- old/libyui-3.8.2/examples/ItemSelector1.cc 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/examples/ItemSelector1.cc 2019-11-07 15:05:08.000000000 +0100 @@ -248,7 +248,7 @@ YAlignment * mbox = fac->createMarginBox( dialog, 2, 2, 0.4, 0.4 ); YLayoutBox * vbox = fac->createVBox( mbox ); - fac->createHeading( vbox, "Program Configuration" ); + fac->createHeading( vbox, "Example Configuration" ); fac->createVSpacing( vbox, 0.2 ); YAlignment * left = fac->createLeft( vbox ); @@ -278,6 +278,7 @@ YPushButton * cancelButton = fac->createPushButton( buttonBox, "&Cancel" ); continueButton->setRole( YOKButton ); + continueButton->setDefaultButton(); cancelButton->setRole( YCancelButton ); YEvent * event = dialog->waitForEvent(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/package/libyui-doc.spec new/libyui-3.8.4/package/libyui-doc.spec --- old/libyui-3.8.2/package/libyui-doc.spec 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/package/libyui-doc.spec 2019-11-07 15:05:08.000000000 +0100 @@ -20,7 +20,7 @@ %define so_version 10 Name: %{parent}-doc -Version: 3.8.2 +Version: 3.8.4 Release: 0 Source: %{parent}-%{version}.tar.bz2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/package/libyui.changes new/libyui-3.8.4/package/libyui.changes --- old/libyui-3.8.2/package/libyui.changes 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/package/libyui.changes 2019-11-07 15:05:08.000000000 +0100 @@ -1,4 +1,18 @@ ------------------------------------------------------------------- +Thu Nov 7 13:18:33 UTC 2019 - Stefan Hundhammer <[email protected]> + +- Support item status getting and setting for ItemSelector + (bsc#1084674) +- 3.8.4 + +------------------------------------------------------------------- +Thu Oct 31 14:04:38 UTC 2019 - Stefan Hundhammer <[email protected]> + +- Support custom status values (int, not just bool) in ItemSelector + (bsc#1084674) +- 3.8.3 + +------------------------------------------------------------------- Wed Oct 23 10:04:29 UTC 2019 - Stefan Hundhammer <[email protected]> - Don't enforce an initial selection for SingleItemSelector diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/package/libyui.spec new/libyui-3.8.4/package/libyui.spec --- old/libyui-3.8.2/package/libyui.spec 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/package/libyui.spec 2019-11-07 15:05:08.000000000 +0100 @@ -16,7 +16,7 @@ # Name: libyui -Version: 3.8.2 +Version: 3.8.4 Release: 0 Source: %{name}-%{version}.tar.bz2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YDescribedItem.h new/libyui-3.8.4/src/YDescribedItem.h --- old/libyui-3.8.2/src/YDescribedItem.h 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YDescribedItem.h 2019-11-07 15:05:08.000000000 +0100 @@ -35,7 +35,7 @@ class YDescribedItem: public YItem { public: - + /** * Constructor with the label, the description and optionally the selected * state. @@ -45,6 +45,7 @@ bool selected = false ) : YItem( label, selected ) , _description( description ) + , _enabled( true ) {} /** @@ -57,6 +58,7 @@ bool selected = false ) : YItem( label, iconName, selected ) , _description( description ) + , _enabled( true ) {} /** @@ -76,10 +78,25 @@ **/ void setDescription( const std::string & desc ) { _description = desc; } + /** + * Return 'true' if this item is enabled (which is the default). Items are + * only ever disabled if the application explicitly sets them to disabled. + **/ + bool enabled() const { return _enabled; } + + /** + * Set this item to enabled or disabled. + * + * Notice that this only stores that status internally. To have any effect + * on an associated widget, use the widget's method to enable or disable an + * item (which will usually call this method internally at some point). + **/ + void setEnabled( bool value ) { _enabled = value; } private: std::string _description; + bool _enabled; }; // class YDescribedItem diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YItem.h new/libyui-3.8.4/src/YItem.h --- old/libyui-3.8.2/src/YItem.h 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YItem.h 2019-11-07 15:05:08.000000000 +0100 @@ -54,7 +54,7 @@ **/ YItem( const std::string & label, bool selected = false ) : _label( label ) - , _selected( selected ) + , _status( selected ? 1 : 0 ) , _index( -1 ) , _data( 0 ) {} @@ -65,7 +65,7 @@ YItem( const std::string & label, const std::string & iconName, bool selected = false ) : _label( label ) , _iconName( iconName ) - , _selected( selected ) + , _status( selected ? 1 : 0 ) , _index( -1 ) , _data( 0 ) {} @@ -104,14 +104,28 @@ /** * Return 'true' if this item is currently selected. **/ - bool selected() const { return _selected; } + bool selected() const { return _status != 0; } /** * Select or unselect this item. This does not have any effect on any other * item; if it is desired that only one item is selected at any time, the * caller has to take care of that. **/ - void setSelected( bool sel = true ) { _selected = sel; } + void setSelected( bool sel = true ) { _status = sel ? 1 : 0; } + + /** + * Return the status of this item. This is a bit more generalized than + * 'selected'. Values other than 0 or 1 can mean different things to the + * application or to the specific widget. + **/ + int status() const { return _status; } + + /** + * Set the status of this item. Most widgets only use 0 for "not selected" + * or nonzero for "selected". Some widgets may make use of other values as + * well. + **/ + void setStatus( int newStatus ) { _status = newStatus; } /** * Set this item's index. @@ -193,7 +207,7 @@ std::string _label; std::string _iconName; - bool _selected; + int _status; int _index; void * _data; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YItemCustomStatus.h new/libyui-3.8.4/src/YItemCustomStatus.h --- old/libyui-3.8.2/src/YItemCustomStatus.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libyui-3.8.4/src/YItemCustomStatus.h 2019-11-07 15:05:08.000000000 +0100 @@ -0,0 +1,107 @@ +/* + Copyright (c) [2019] SUSE LLC + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) version 3.0 of the License. This library + is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. You should have received a copy of the GNU + Lesser General Public License along with this library; if not, write + to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + Floor, Boston, MA 02110-1301 USA +*/ + + +/*-/ + + File: YItemCustomStatus.h + + Author: Stefan Hundhammer <[email protected]> + +/-*/ + +#ifndef YItemCustomStatus_h +#define YItemCustomStatus_h + +#include <string> +#include <vector> + + +/** + * Class describing a non-binary status for an item. + * + * This is an extension of normal boolean item states: Rather than just "on" or + * "off" like for check boxes or radio buttons, a status of this kind can have + * any nonnegative integer number. The number is implicitly the index of this + * status in the corresponding vector. + * + * For symmetry with boolean states, a value of 0 is defined to have the same + * semantics as "off" / "unselected", 1 has the semantics of "on" / "fully + * selected", and all other values are purely application-defined. + **/ +class YItemCustomStatus +{ +public: + /** + * Constructor. + **/ + YItemCustomStatus( const std::string & iconName, + const std::string & textIndicator, + int nextStatus = -1 ) + : _iconName( iconName ) + , _textIndicator( textIndicator ) + , _nextStatus( nextStatus ) + {} + + /** + * The name of an icon to use in the widget in a graphical UI if an item + * has this status. + **/ + const std::string & iconName() const { return _iconName; } + + /** + * A text representation of this status in a text-based UI if an item has + * this status, for example "[ ]", "[x]" or "[ ], "[ +]", "[a+]". + * + * It is recommended to use the same character length for all states so all + * items line up properly, even if they have different states. + **/ + const std::string & textIndicator() const { return _textIndicator; } + + /** + * This returns the next status to cycle through if the user clicks on the + * status or cycles through status values with the corresponding shortcut + * key. + * + * If no such value was specified, this returns -1. The application can + * then still choose to set a different status depending on other + * application data. + **/ + int nextStatus() const { return _nextStatus; } + + /** + * Set the next status. This should only be done once when the status + * transition map is evaluated. + **/ + void setNextStatus( int value ) { _nextStatus = value; } + + /** + * Return 'true' if a next status to cylce to is defined for this status, + * 'false' if not. + **/ + bool hasNextStatus() const { return _nextStatus != -1; } + +protected: + + std::string _iconName; + std::string _textIndicator; + int _nextStatus; +}; + + +typedef std::vector<YItemCustomStatus> YItemCustomStatusVector; + + +#endif // YItemCustomStatus_h diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YItemSelector.cc new/libyui-3.8.4/src/YItemSelector.cc --- old/libyui-3.8.2/src/YItemSelector.cc 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YItemSelector.cc 2019-11-07 15:05:08.000000000 +0100 @@ -27,7 +27,7 @@ #include "YItemSelector.h" -#define DEFAULT_VISIBLE_ITEMS 3 +#define DEFAULT_VISIBLE_ITEMS 3 using std::string; @@ -35,25 +35,39 @@ struct YItemSelectorPrivate { YItemSelectorPrivate() - : visibleItems( DEFAULT_VISIBLE_ITEMS ) - {} + : visibleItems( DEFAULT_VISIBLE_ITEMS ) + {} - int visibleItems; + int visibleItems; + YItemCustomStatusVector customStates; }; -YItemSelector::YItemSelector( YWidget * parent, - bool enforceSingleSelection ) +YItemSelector::YItemSelector( YWidget * parent, + bool enforceSingleSelection ) : YSelectionWidget( parent, - "", // label - enforceSingleSelection ) + "", // label + enforceSingleSelection ) , priv( new YItemSelectorPrivate ) { YUI_CHECK_NEW( priv ); - setEnforceInitialSelection( false ); - setDefaultStretchable( YD_HORIZ, true ); - setDefaultStretchable( YD_VERT, true ); + init(); +} + + +YItemSelector::YItemSelector( YWidget * parent, + const YItemCustomStatusVector & customStates ) + : YSelectionWidget( parent, + "", // label + false ) // enforceSingleSelection ) + , priv( new YItemSelectorPrivate ) +{ + YUI_CHECK_NEW( priv ); + + priv->customStates = customStates; + init(); + checkCustomStates(); } @@ -63,9 +77,21 @@ } +void YItemSelector::init() +{ + setEnforceInitialSelection( false ); + + setDefaultStretchable( YD_HORIZ, true ); + setDefaultStretchable( YD_VERT, true ); +} + + const char * YItemSelector::widgetClass() const { + if ( usingCustomStatus() ) + return "YCustomStatusItemSelector"; + return enforceSingleSelection() ? "YSingleItemSelector" : "YMultiItemSelector"; } @@ -80,12 +106,105 @@ void YItemSelector::setVisibleItems( int newVal ) { if ( newVal < 1 ) - newVal = 1; + newVal = 1; priv->visibleItems = newVal; } +void YItemSelector::setItemStatus( YItem * item, int status ) +{ + if ( usingCustomStatus() ) + { + YUI_CHECK_INDEX( status, -1, customStatusCount() - 1 ); + item->setStatus( status ); + updateCustomStatusIndicator( item ); + + // Intentionally NOT calling the parent class implementation since that + // would only store 0 or 1 as the item's status. + } + else + { + // Let the parent class handle this and also take care of enforcing + // single selection (if configured). + + YSelectionWidget::setItemStatus( item, status ); + } +} + + +bool YItemSelector::usingCustomStatus() const +{ + return ! priv->customStates.empty(); +} + + +int YItemSelector::customStatusCount() const +{ + return priv->customStates.size(); +} + + +const YItemCustomStatus & +YItemSelector::customStatus( int index ) +{ + // std::vector::at() does bounds checking of 'index', possibly throwing a + // std::out_of_range exception. + // + // std::vector::operator[] does not do any checking and may just cause a + // segfault or misbehave in spectacular ways. + + return priv->customStates.at( (YItemCustomStatusVector::size_type) index ); +} + + +bool YItemSelector::validCustomStatusIndex( int index ) const +{ + return index >= 0 && index < customStatusCount(); +} + + +void YItemSelector::checkCustomStates() +{ + if ( priv->customStates.size() < 2 ) + YUI_THROW( YUIException( "Need at least 2 different custom status value definitions" ) ); + + int maxStatus = priv->customStates.size() - 1; + + for ( int i=0; i <= maxStatus; ++i ) + { + YItemCustomStatus & status = priv->customStates.at( (YItemCustomStatusVector::size_type) i ); + + if ( status.nextStatus() > maxStatus ) + { + yuiError() << "Invalid nextStatus " << status.nextStatus() + << " for status #" << i + << endl; + + status.setNextStatus( -1 ); + } + else if ( status.nextStatus() < -1 ) + status.setNextStatus( -1 ); + else + { + yuiDebug() << "Status #" << i << ": next status: #" << status.nextStatus() << endl; + } + } +} + + +int YItemSelector::cycleCustomStatus( int oldStatus ) +{ + if ( ! validCustomStatusIndex( oldStatus ) ) + { + yuiDebug() << "Invalid old status: " << oldStatus << endl; + return oldStatus; + } + else + return priv->customStates.at( oldStatus ).nextStatus(); +} + + const YPropertySet & YItemSelector::propertySet() { @@ -94,18 +213,20 @@ if ( propSet.isEmpty() ) { /* - * @property itemID Value The (first) currently selected item - * @property itemID CurrentItem The (first) currently selected item - * @property itemList SelectedItems All currently selected items - * @property itemList Items All items - * @property integer VisibleItems Number of items that are visible without scrolling - * @property string IconPath Base path for icons + * @property itemID Value The (first) currently selected item + * @property itemID CurrentItem The (first) currently selected item + * @property itemList SelectedItems All currently selected items + * @property itemList Items All items + * @property statusMap ItemStatus The (numeric) status values of the items + * @property integer VisibleItems Number of items that are visible without scrolling + * @property string IconPath Base path for icons */ propSet.add( YProperty( YUIProperty_Value, YOtherProperty ) ); propSet.add( YProperty( YUIProperty_CurrentItem, YOtherProperty ) ); propSet.add( YProperty( YUIProperty_SelectedItems, YOtherProperty ) ); propSet.add( YProperty( YUIProperty_Items, YOtherProperty ) ); - propSet.add( YProperty( YUIProperty_VisibleItems, YIntegerProperty ) ); + propSet.add( YProperty( YUIProperty_ItemStatus, YOtherProperty ) ); + propSet.add( YProperty( YUIProperty_VisibleItems, YIntegerProperty ) ); propSet.add( YProperty( YUIProperty_IconPath, YStringProperty ) ); propSet.add( YWidget::propertySet() ); } @@ -120,11 +241,12 @@ propertySet().check( propertyName, val.type() ); // throws exceptions if not found or type mismatch if ( propertyName == YUIProperty_Value ) return false; // Needs special handling - else if ( propertyName == YUIProperty_CurrentItem ) return false; // Needs special handling + else if ( propertyName == YUIProperty_CurrentItem ) return false; // Needs special handling else if ( propertyName == YUIProperty_SelectedItems ) return false; // Needs special handling - else if ( propertyName == YUIProperty_Items ) return false; // Needs special handling - else if ( propertyName == YUIProperty_VisibleItems ) setVisibleItems( val.integerVal() ); - else if ( propertyName == YUIProperty_IconPath ) setIconBasePath( val.stringVal() ); + else if ( propertyName == YUIProperty_Items ) return false; // Needs special handling + else if ( propertyName == YUIProperty_ItemStatus ) return false; // Needs special handling + else if ( propertyName == YUIProperty_VisibleItems ) setVisibleItems( val.integerVal() ); + else if ( propertyName == YUIProperty_IconPath ) setIconBasePath( val.stringVal() ); else { return YWidget::setProperty( propertyName, val ); @@ -140,10 +262,11 @@ propertySet().check( propertyName ); // throws exceptions if not found if ( propertyName == YUIProperty_Value ) return YPropertyValue( YOtherProperty ); - else if ( propertyName == YUIProperty_CurrentItem ) return YPropertyValue( YOtherProperty ); + else if ( propertyName == YUIProperty_CurrentItem ) return YPropertyValue( YOtherProperty ); else if ( propertyName == YUIProperty_SelectedItems ) return YPropertyValue( YOtherProperty ); - else if ( propertyName == YUIProperty_Items ) return YPropertyValue( YOtherProperty ); - else if ( propertyName == YUIProperty_VisibleItems ) return YPropertyValue( visibleItems() ); + else if ( propertyName == YUIProperty_Items ) return YPropertyValue( YOtherProperty ); + else if ( propertyName == YUIProperty_ItemStatus ) return YPropertyValue( YOtherProperty ); + else if ( propertyName == YUIProperty_VisibleItems ) return YPropertyValue( visibleItems() ); else if ( propertyName == YUIProperty_IconPath ) return YPropertyValue( iconBasePath() ); else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YItemSelector.h new/libyui-3.8.4/src/YItemSelector.h --- old/libyui-3.8.2/src/YItemSelector.h 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YItemSelector.h 2019-11-07 15:05:08.000000000 +0100 @@ -27,6 +27,7 @@ #include "YSelectionWidget.h" #include "YDescribedItem.h" +#include "YItemCustomStatus.h" class YItemSelectorPrivate; @@ -44,12 +45,42 @@ public: /** - * Constructor. + * Standard constructor. **/ YItemSelector( YWidget * parent, bool enforceSingleSelection = true ); /** + * Constructor for custom item status values. + * + * This makes it possible to set a wider variety of values than just 0 or + * 1. The semantics behind the individual status values is purely + * application defined; the specified customStates description only + * provides an icon (for graphical UIs) or a text representation (for + * text-based UIs) and an optional "next" status value that can be used to + * let the user cycle through different status values. The numeric value of + * each status is implicitly its index in the vector. + * + * Notice that this constructor is the only way to set custom status value + * descriptions; they cannot be changed anymore after initializing the + * widget. This is by design so that any derived widgets in concrete UIs do + * not have to bother with possibly recreating any subwidgets if this + * should change; this guarantees that it does not change, neither the fact + * that there are custom status values nor their number or indicator icons + * or texts. + * + * This constructor implicitly sets 'enforceSingleSelection' to 'false'. + * + * In this mode, the widget sends YMenuEvents (which include the item that + * the user changed) if the notify option is set. For anything beyond the + * simple status transitions that are defined here in 'customStates', it is + * highly recommended to set that notify option and to handle those + * YMenuEvents on the application level. + **/ + YItemSelector( YWidget * parent, + const YItemCustomStatusVector & customStates ); + + /** * Destructor. **/ virtual ~YItemSelector(); @@ -79,6 +110,48 @@ virtual void setVisibleItems( int newVal ); /** + * Set the status of an item. Unlike YItem::setStatus(), this informs the + * widget of the change so it can set the corresponding status icon. + * + * Reimplemented from YSelectionWidget. + **/ + virtual void setItemStatus( YItem * item, int status ); + + /** + * Return 'true' if this widget uses custom status values, 'false' if not + * (i.e. only 0 or 1). + **/ + bool usingCustomStatus() const; + + /** + * Return the number of custom status values or 0 if no custom status + * values are used. + **/ + int customStatusCount() const; + + /** + * Return the custom status with the specified index (counting from 0). + * + * Notice that this may throw a std::out_of_range exception if the index is + * invalid. + **/ + const YItemCustomStatus & customStatus( int index ); + + /** + * Return 'true' if a custom status index is within the valid range, + * i.e. 0..customStatusCount()-1, 'false' otherwise. + **/ + bool validCustomStatusIndex( int index ) const; + + /** + * Cycle through the custom status values according to the custom status + * table, i.e. return the 'nextStatus' field of table index 'oldStatus'. + * This may be -1 if no next status was specified there or if 'oldStatus' + * is out of range of that table. + **/ + int cycleCustomStatus( int oldStatus ); + + /** * Set a property. * Reimplemented from YWidget. * @@ -114,8 +187,32 @@ const char * userInputProperty() { return YUIProperty_Value; } +protected: + + /** + * Update the status indicator (status icon or text indicator) if this + * widget is using custom status values. + * + * Derived classes should overwrite this. + **/ + virtual void updateCustomStatusIndicator( YItem * item ) {} + + private: + /** + * Common initializations for all constructors. + **/ + void init(); + + /** + * Perform a sanity check on the custom status value descriptions. + **/ + void checkCustomStates(); + + + // Data members + ImplPtr<YItemSelectorPrivate> priv; }; // class YItemSelector diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YSelectionWidget.cc new/libyui-3.8.4/src/YSelectionWidget.cc --- old/libyui-3.8.2/src/YSelectionWidget.cc 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YSelectionWidget.cc 2019-11-07 15:05:08.000000000 +0100 @@ -441,6 +441,12 @@ } +void YSelectionWidget::setItemStatus( YItem * item, int status ) +{ + selectItem( item, status != 0 ); +} + + bool YSelectionWidget::itemsContain( YItem * wantedItem ) const { return itemsContain( wantedItem, itemsBegin(), itemsEnd() ); @@ -535,7 +541,21 @@ for ( YItemConstIterator it = itemsBegin(); it != itemsEnd(); ++it ) { - yuiMilestone() << ( (*it)->selected() ? " [x] " : " [ ] " ) + string status; + + switch ( (*it)->status() ) + { + case 0: status = "[ ]"; break; + case 1: status = "[x]"; break; + default: + { + char buffer[80]; + sprintf( buffer, "[%d]", (*it)->status() ); + status = buffer; + } + } + + yuiMilestone() << " " << status << " " << (*it)->label() << endl; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YSelectionWidget.h new/libyui-3.8.4/src/YSelectionWidget.h --- old/libyui-3.8.2/src/YSelectionWidget.h 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YSelectionWidget.h 2019-11-07 15:05:08.000000000 +0100 @@ -202,6 +202,17 @@ virtual void selectItem( YItem * item, bool selected = true ); /** + * Set the status of an item. + * + * This is similar to selectItem(), but with numeric values. + * + * This default implementation just calls selectItem() with 'status' + * converted to boolean. Derived classes can choose to make more detailed + * use of the numeric value. + **/ + virtual void setItemStatus( YItem * item, int status ); + + /** * Deselect all items. * * Derived classes can overwrite this function, but they should call this diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YUISymbols.h new/libyui-3.8.4/src/YUISymbols.h --- old/libyui-3.8.2/src/YUISymbols.h 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YUISymbols.h 2019-11-07 15:05:08.000000000 +0100 @@ -88,6 +88,7 @@ #define YUIWidget_CheckBox "CheckBox" #define YUIWidget_CheckBoxFrame "CheckBoxFrame" #define YUIWidget_ComboBox "ComboBox" +#define YUIWidget_CustomStatusItemSelector "CustomStatusItemSelector" #define YUIWidget_Empty "Empty" #define YUIWidget_Frame "Frame" #define YUIWidget_HBox "HBox" @@ -183,6 +184,7 @@ #define YUIProperty_ID "ID" #define YUIProperty_Item "Item" #define YUIProperty_Items "Items" +#define YUIProperty_ItemStatus "ItemStatus" #define YUIProperty_Label "Label" #define YUIProperty_Labels "Labels" #define YUIProperty_LastLine "LastLine" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YWidgetFactory.cc new/libyui-3.8.4/src/YWidgetFactory.cc --- old/libyui-3.8.2/src/YWidgetFactory.cc 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YWidgetFactory.cc 2019-11-07 15:05:08.000000000 +0100 @@ -305,3 +305,14 @@ return createItemSelector( parent, false ); // enforceSingleSelection } + + +YItemSelector * +YWidgetFactory::createCustomStatusItemSelector( YWidget * parent, + const YItemCustomStatusVector & customStates ) +{ + (void) customStates; + + return createItemSelector( parent, + false ); // enforceSingleSelection +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.8.2/src/YWidgetFactory.h new/libyui-3.8.4/src/YWidgetFactory.h --- old/libyui-3.8.2/src/YWidgetFactory.h 2019-10-23 14:13:27.000000000 +0200 +++ new/libyui-3.8.4/src/YWidgetFactory.h 2019-11-07 15:05:08.000000000 +0100 @@ -28,6 +28,7 @@ #include <string> #include "YTypes.h" +#include "YItemCustomStatus.h" class YWidget; @@ -92,24 +93,24 @@ YLayoutBox * createVBox ( YWidget * parent ); YLayoutBox * createHBox ( YWidget * parent ); - virtual YLayoutBox * createLayoutBox ( YWidget * parent, YUIDimension dimension ) = 0; - virtual YButtonBox * createButtonBox ( YWidget * parent ) = 0; + virtual YLayoutBox * createLayoutBox ( YWidget * parent, YUIDimension dimension ) = 0; + virtual YButtonBox * createButtonBox ( YWidget * parent ) = 0; // // Common Leaf Widgets // - virtual YPushButton * createPushButton ( YWidget * parent, const std::string & label ) = 0; + virtual YPushButton * createPushButton ( YWidget * parent, const std::string & label ) = 0; virtual YLabel * createLabel ( YWidget * parent, const std::string & text, bool isHeading = false, bool isOutputField = false ) = 0; YLabel * createHeading ( YWidget * parent, const std::string & label ); virtual YInputField * createInputField ( YWidget * parent, const std::string & label, bool passwordMode = false ) = 0; - virtual YCheckBox * createCheckBox ( YWidget * parent, const std::string & label, bool isChecked = false ) = 0; - virtual YRadioButton * createRadioButton ( YWidget * parent, const std::string & label, bool isChecked = false ) = 0; + virtual YCheckBox * createCheckBox ( YWidget * parent, const std::string & label, bool isChecked = false ) = 0; + virtual YRadioButton * createRadioButton ( YWidget * parent, const std::string & label, bool isChecked = false ) = 0; virtual YComboBox * createComboBox ( YWidget * parent, const std::string & label, bool editable = false ) = 0; - virtual YSelectionBox * createSelectionBox ( YWidget * parent, const std::string & label ) = 0; + virtual YSelectionBox * createSelectionBox ( YWidget * parent, const std::string & label ) = 0; virtual YTree * createTree ( YWidget * parent, const std::string & label, bool multiselection = false, bool recursiveselection = false ) = 0; - virtual YTable * createTable ( YWidget * parent, YTableHeader * header, bool multiSelection = false ) = 0; - virtual YProgressBar * createProgressBar ( YWidget * parent, const std::string & label, int maxValue = 100 ) = 0; + virtual YTable * createTable ( YWidget * parent, YTableHeader * header, bool multiSelection = false ) = 0; + virtual YProgressBar * createProgressBar ( YWidget * parent, const std::string & label, int maxValue = 100 ) = 0; virtual YRichText * createRichText ( YWidget * parent, const std::string & text = std::string(), bool plainTextMode = false ) = 0; virtual YBusyIndicator * createBusyIndicator ( YWidget * parent, const std::string & label, int timeout = 1000 ) = 0; @@ -123,7 +124,7 @@ YInputField * createPasswordField ( YWidget * parent, const std::string & label ); virtual YMenuButton * createMenuButton ( YWidget * parent, const std::string & label ) = 0; - virtual YMultiLineEdit * createMultiLineEdit ( YWidget * parent, const std::string & label ) = 0; + virtual YMultiLineEdit * createMultiLineEdit ( YWidget * parent, const std::string & label ) = 0; virtual YImage * createImage ( YWidget * parent, const std::string & imageFileName, bool animated = false ) = 0; virtual YLogView * createLogView ( YWidget * parent, const std::string & label, int visibleLines, int storedLines = 0 ) = 0; virtual YMultiSelectionBox *createMultiSelectionBox ( YWidget * parent, const std::string & label ) = 0; @@ -184,9 +185,10 @@ // More leaf widgets (moved to the end to maintain ABI compatibility) // - virtual YItemSelector * createItemSelector ( YWidget * parent, bool enforceSingleSelection = true ); - YItemSelector * createSingleItemSelector( YWidget * parent ); - YItemSelector * createMultiItemSelector ( YWidget * parent ); + virtual YItemSelector * createItemSelector ( YWidget * parent, bool enforceSingleSelection = true ); + YItemSelector * createSingleItemSelector ( YWidget * parent ); + YItemSelector * createMultiItemSelector ( YWidget * parent ); + virtual YItemSelector * createCustomStatusItemSelector ( YWidget * parent, const YItemCustomStatusVector & customStates ); protected:
