ACC SHELL

Path : /usr/share/YaST2/include/autoinstall/
File Upload :
Current File : //usr/share/YaST2/include/autoinstall/StorageDialog.ycp

/**
 * File:
 *	StorageDialog.ycp
 *
 * Module:
 *	Partitioning
 *
 * Summary:
 *	Display and handle main dialog.
 *
 * Authors:
 *	Sven Schober (sschober@suse.de)
 *
 * $Id: StorageDialog.ycp 2810 2008-05-29 14:49:59Z sschober $
 */
{
    textdomain "autoinst";
    import "Label";
    import "Popup";
    import "String";
    import "AutoinstStorage";
    import "AutoinstPartPlan";

    include "autoinstall/common.ycp";
    include "autoinstall/tree.ycp";
    include "autoinstall/DriveDialog.ycp";
    include "autoinstall/VolgroupDialog.ycp";
    include "autoinstall/PartitionDialog.ycp";

    //Storage::GetTargetMap(); // initialize libstorage

    define boolean startsWith( string haystack, string needle ){
      return substring( haystack, 0, size(needle)) == needle;
    }

    /**
     * Displayed when tree is empty
     */
    define term EmptyDialog(){
      return `Label(`id(`treeinspect),_("Nothing selected"));
    }

    /**
     * Top level event handler
     *
     * Catches all events not handled by the currently active
     * subdialog (one of: Drive, Partition or LVM).
     *
     * The general idea is (like with dispatchMenuEvent()):
     *
     * When the user clicks on a button (Add {Drive, Partition,
     * LVM}, Remove):
     *
     *	1. the check() function on the currently active dialog is
     *	called. If there were any changes to the settings the user
     *	is asked if these should be saved (this does not happen for
     *	delete events).
     *
     *	2. for the 'add'-type button events the according new() dialog
     *	function is called; for delete events the according delete()
     *	function is called.
     */
    define void StorageEventHandler(){
      y2milestone( "DriveEventHandler(): current event: '%1'", currentEvent);
      if( is( currentEvent, map) ){
	if( `addDrive == currentEvent["WidgetID"]:`Empty ){
	  /* 'Add Drive' button clicked */
	  y2milestone( "'Add Drive' button clicked" );
	  callDialogFunction( currentDialog, `check );
	  updateCurrentDialog("drive");
	  callDialogFunction( currentDialog, `new );
	}
	else if( `addPart == currentEvent["WidgetID"]:`Empty ){
	  /* 'Add Partition' button clicked */
	  y2milestone( "'Add Partition' button clicked" );
	  callDialogFunction( currentDialog, `check );
	  string item = currentTreeItem();
	  if( "" != item  ){
	    stack[`which] = stripTypePrefix( item );
	  }
	  else{
	    y2error( "No item selected.");
	  }
	  updateCurrentDialog("part");
	  callDialogFunction( currentDialog, `new );
	}
	else if( `addVG == currentEvent["WidgetID"]:`Empty ){
	  /* 'Add Volume Group' button clicked */
	  y2milestone( "'Add Volume Group' button clicked" );
	  callDialogFunction( currentDialog, `check );
	  updateCurrentDialog("volgroup");
	  callDialogFunction( currentDialog, `new );
	}
	else if( `delete == currentEvent["WidgetID"]:`Empty ){
	  /* 'Delete' button clicked */
	  y2milestone( "'Delete' button clicked" );
	  string item = currentTreeItem();
	  if( "" != item ){
	    stack[`which] = stripTypePrefix( item );
	    callDialogFunction( updateCurrentDialog(getTypePrefix(item)), `delete );
	    if( 0 == AutoinstPartPlan::getDriveCount() ){
	      /* if last drive was removed display new drive dialog */
	      updateCurrentDialog("drive");
	      callDialogFunction( currentDialog, `new );
	    }
	    else{
	      /* else display the now selected item */
	      item = currentTreeItem();
	      stack[`which] = stripTypePrefix( item );
	      callDialogFunction( updateCurrentDialog(getTypePrefix(item)), `display );
	    }
	  }
	  else{
	    y2milestone( "No item selected." );
	  }
	}
	else if( `apply == currentEvent["WidgetID"]:`Empty ){
	  y2milestone("Apply button clicked in dialog '%1'. Storing settings.", currentDialog );
	  callDialogFunction( currentDialog, `store );
	  /* reflect changes to AutoinstPartPlan in tree widget */
	  AutoinstPartPlan::updateTree();
	}
      }

    }

    /*
     * TODO: this distinction between tree- and widget
     * events might be superflous and could be genralized.
     */

    /*
     * Generic tree event dispatching
     */
    define void dispatchMenuEvent( map event ){
      string item = currentTreeItem();
      if( "" == item ){
	/* User deselected current tree item. Happens when she clicks on empty line. */
	y2milestone("Deselection event. Nothing happens, deliberately.");
      }
      else{
	/* User selected a new tree item. */

	/* 1. check for changed settings in current dialog */
	callDialogFunction( currentDialog, `check);
	/* 2. display new dialog */
	stack[`which] = stripTypePrefix( item );
	callDialogFunction(updateCurrentDialog(getTypePrefix(item)),`display );
      }

    }

    /*
     * Generic widget event dispatching
     *
     * First, the dialog specific event handler gets a shot
     * afterwards the toplevel one kicks in.
     */
    define void dispatchWidgetEvent( map event ){
      any eventHandler = currentDialog[`eventHandler]:nil;
      currentEvent = event;
      eval( eventHandler );
      if( size(currentEvent) != 0 ){
	/*
	 * the subdialog event handler didn't process the event, so 
	 * we call the toplevel handler
	 */
	StorageEventHandler();
      }
    }

    /**
     * Main Partitioning Dialog
     * @return symbol
     */
    define symbol StorageDialog()
    {
      term contents =
	`HBox(
	  `HWeight(33,
	   `VBox(
	    `Tree(`id(`tree),`opt(`notify),_("Partition p&lan"), []),
	    `VSpacing(0.3),
	    `VBox(
		`HBox(
		  `HSpacing(1),
		  `HWeight(50, `PushButton(`id(`addDrive), _("Add D&rive")) ),
		  `HWeight(50, `PushButton(`id(`addPart),  _("Add &Partition"))),
		  `HSpacing(1)
		 ),
		 `HBox(
		  `HSpacing(1),
		  `HWeight(50, `PushButton(`id(`addVG),    _("Add &Volume Group")) ),
		  `HWeight(50, `PushButton(`id(`delete),   _("&Delete"))),
		  `HSpacing(1)
		 )
	    ),
	    `VSpacing(1)
	   )
	  ),
	  `HSpacing(1),
	  `HWeight(66,
	   `VBox(
	      `VSpacing(1),
	      `Frame( "",
		      `Top(
			`ReplacePoint(`id(replacement_point), EmptyDialog())
		      )
	       ),
		`VSpacing(1),
		`HBox(
		    `Left(`PushButton(`id(`back), Label::BackButton()) ),
		    `HStretch(),
		    `Right(`PushButton(`id(`next), Label::FinishButton()))
		  )
	    )
	   ),
	   `HSpacing(1)
	  );

      UI::OpenDialog( `opt(`defaultsize), contents );
      AutoinstPartPlan::updateTree();


      /* if there is no drive in partition plan, the user surely
       * wants to create one
       */
      updateCurrentDialog("drive");
      if( 0 == AutoinstPartPlan::getDriveCount() ){
	callDialogFunction( currentDialog, `new );
      }
      else{
	string item = currentTreeItem();
	stack[`which] = stripTypePrefix( item );
	callDialogFunction( currentDialog, `display );
      }

      while(true){
	map event = UI::WaitForEvent();
	string item = currentTreeItem();

	y2milestone( "Got event: '%1'", event );
	y2milestone( "Selected tree item: '%1'", item);

	/*
	 * MAIN EVENT HANDLING
	 *
	 * General Event Handling Idea:
	 *
	 * There is a global map "dialogs" that maps dialog types to a
	 * dialog map, which in turn stores call backs for stuff like
	 * displaying the dialog contents, eventhandling, getting and setting
	 * of settings,...
	 *
	 * This architecture avoids long if-elseif-cascades.
	 */
	symbol event_id = `Empty;
	if( is( event["ID"]:nil, symbol ) ){
	  event_id = event["ID"]:`Empty;
	}
	if( event_id == `abort ||
	    event_id == `back  ||
	    event_id == `cancel){
	  return event_id;
	}
	else if( event_id == `next ||
		 event_id == `finish ){
	  callDialogFunction( currentDialog, `check );
	  if( AutoinstPartPlan::checkSanity() ){
	    /* Only return successfully if plan is sane */
	    return event_id;
	  }
	}
	else if( event["EventType"]:"" == "MenuEvent" ||
	    /* ncurses sends following kind of event: */
	    event["WidgetID"]:`Empty == sTree ){
	  /* Tree Event */
	  dispatchMenuEvent(event);
	}
	else if( event["EventType"]:"" == "WidgetEvent" ){
	  /* Button was pressed */
	  dispatchWidgetEvent(event);
	}
      }
      return (symbol)`Empty;
    }

    // EOF
}

ACC SHELL 2018