From a1be6c4aade7c07d656f720001d711bbbe16cb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Thu, 27 Feb 2020 23:44:21 +0100 Subject: [PATCH] Version19.136 --- css/{swad19.133.1.css => swad19.136.css} | 7 + sql/swad.sql | 4 +- swad_changelog.h | 10 +- swad_database.c | 6 +- swad_global.h | 1 + swad_program.c | 511 +++++++++++++++-------- swad_program.h | 2 +- swad_syllabus.c | 4 +- swad_text.c | 56 ++- 9 files changed, 412 insertions(+), 189 deletions(-) rename css/{swad19.133.1.css => swad19.136.css} (99%) diff --git a/css/swad19.133.1.css b/css/swad19.136.css similarity index 99% rename from css/swad19.133.1.css rename to css/swad19.136.css index 99333d767..bc0e0f7da 100644 --- a/css/swad19.133.1.css +++ b/css/swad19.136.css @@ -1584,6 +1584,13 @@ a:hover img.CENTRE_PHOTO_SHOW text-decoration:underline; } +/****************************** Course program *******************************/ +.PRG_COL1 + { + box-sizing:border-box; + width:64px; + } + /********************************** Notice ***********************************/ .NOTICE_HIGHLIGHT { diff --git a/sql/swad.sql b/sql/swad.sql index 9ee8a8ef9..05b7df9cb 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -1036,9 +1036,9 @@ CREATE TABLE IF NOT EXISTS prg_grp ( -- CREATE TABLE IF NOT EXISTS prg_items ( ItmCod INT NOT NULL AUTO_INCREMENT, + CrsCod INT NOT NULL DEFAULT -1, ItmInd INT NOT NULL DEFAULT 0, Level INT NOT NULL DEFAULT 1, - CrsCod INT NOT NULL DEFAULT -1, Hidden ENUM('N','Y') NOT NULL DEFAULT 'N', UsrCod INT NOT NULL, StartTime DATETIME NOT NULL, @@ -1046,7 +1046,7 @@ CREATE TABLE IF NOT EXISTS prg_items ( Title VARCHAR(2047) NOT NULL, Txt TEXT NOT NULL, UNIQUE INDEX(ItmCod), - INDEX(CrsCod,Hidden)); + UNIQUE INDEX(CrsCod,ItmInd)); -- -- Table prj_config: stores the configuration of projects for each course -- diff --git a/swad_changelog.h b/swad_changelog.h index a6974623f..2226e2206 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -497,8 +497,8 @@ enscript -2 --landscape --color --file-align=2 --highlight --line-numbers -o - * En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 19.135 (2020-02-27)" -#define CSS_FILE "swad19.133.1.css" +#define Log_PLATFORM_VERSION "SWAD 19.136 (2020-02-27)" +#define CSS_FILE "swad19.136.css" #define JS_FILE "swad19.91.1.js" /* * @@ -523,6 +523,12 @@ Param // TODO: Miguel Damas: por defecto, marcar "Permitir que los profesores..." en los test (que ya esté marcado en lugar de desmarcado) // TODO: Si el alumno ha marcado "Permitir que los profesores...", entonces pedir confirmación al pulsar el botón azul, para evitar que se envíe por error antes de tiempo + Version 19.136: Feb 27, 2020 Indent items in course program. (282292 lines) + 3 changes necessary in database: +DROP INDEX CrsCod ON prg_items; +ALTER TABLE prg_items CHANGE COLUMN CrsCod CrsCod INT NOT NULL DEFAULT -1 AFTER ItmCod; +ALTER TABLE prg_items ADD UNIQUE INDEX(CrsCod,ItmInd); + Version 19.135: Feb 27, 2020 Buttons in course program to indent items. Not finished. (282097 lines) 1 change necessary in database: ALTER TABLE prg_items ADD COLUMN Level INT NOT NULL DEFAULT 1 AFTER ItmInd; diff --git a/swad_database.c b/swad_database.c index d4e9eea91..97f3fc778 100644 --- a/swad_database.c +++ b/swad_database.c @@ -2211,9 +2211,9 @@ mysql> DESCRIBE prg_items; | Field | Type | Null | Key | Default | Extra | +-----------+---------------+------+-----+---------+----------------+ | ItmCod | int(11) | NO | PRI | NULL | auto_increment | +| CrsCod | int(11) | NO | MUL | -1 | | | ItmInd | int(11) | NO | | 0 | | | Level | int(11) | NO | | 1 | | -| CrsCod | int(11) | NO | MUL | -1 | | | Hidden | enum('N','Y') | NO | | N | | | UsrCod | int(11) | NO | | NULL | | | StartTime | datetime | NO | | NULL | | @@ -2225,9 +2225,9 @@ mysql> DESCRIBE prg_items; */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS prg_items (" "ItmCod INT NOT NULL AUTO_INCREMENT," + "CrsCod INT NOT NULL DEFAULT -1," "ItmInd INT NOT NULL DEFAULT 0," "Level INT NOT NULL DEFAULT 1," - "CrsCod INT NOT NULL DEFAULT -1," "Hidden ENUM('N','Y') NOT NULL DEFAULT 'N'," "UsrCod INT NOT NULL," "StartTime DATETIME NOT NULL," @@ -2235,7 +2235,7 @@ mysql> DESCRIBE prg_items; "Title VARCHAR(2047) NOT NULL," // Prg_MAX_BYTES_PROGRAM_ITEM_TITLE "Txt TEXT NOT NULL," // Cns_MAX_BYTES_TEXT "UNIQUE INDEX(ItmCod)," - "INDEX(CrsCod,Hidden))"); + "UNIQUE INDEX(CrsCod,ItmInd))"); /***** Table prj_config *****/ /* diff --git a/swad_global.h b/swad_global.h index 01e2167af..aac22af13 100644 --- a/swad_global.h +++ b/swad_global.h @@ -543,6 +543,7 @@ struct Globals bool LstIsRead; // Is the list already read from database, or it needs to be read? unsigned Num; // Number of items long *LstItmCods; // List of items codes + unsigned MaxLevel; // Maximum level of items unsigned CurrentPage; } Prg; struct diff --git a/swad_program.c b/swad_program.c index 540de3510..20855dafe 100644 --- a/swad_program.c +++ b/swad_program.c @@ -66,7 +66,7 @@ extern struct Globals Gbl; /*****************************************************************************/ long Prg_CurrentItmCod; // Used as parameter in contextual links -unsigned Prg_CurrentItmInd; // Used as parameter in contextual links +unsigned Prg_CurrentIndex; // Used as parameter in contextual links /*****************************************************************************/ /***************************** Private prototypes ****************************/ @@ -78,18 +78,19 @@ static void Prg_PutIconsListItems (void); static void Prg_PutIconToCreateNewItem (void); static void Prg_PutButtonToCreateNewItem (void); static void Prg_ParamsWhichGroupsToShow (void); -static void Prg_ShowOneItem (long ItmCod,unsigned MaxItmInd,bool PrintView); +static void Prg_ShowOneItem (long ItmCod,unsigned MaxIndex,bool PrintView); +static void Prg_WriteNumItem (unsigned Level); static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item, - unsigned MaxItmInd, + unsigned MaxIndex, const char *Anchor); static void Prg_SetCurrentItmCod (long ItmCod); static long Prg_GetCurrentItmCod (void); -static void Prg_SetCurrentItmInd (unsigned ItmInd); +static void Prg_SetCurrentIndex (unsigned Index); static unsigned Prg_GetCurrentItmInd (void); static void Prg_PutParams (void); -static void Prg_PutParamItmInd (unsigned ItmInd); +static void Prg_PutParamItmInd (unsigned Index); static unsigned Prg_GetParamItmInd (void); static void Prg_GetDataOfItem (struct ProgramItem *Item, @@ -99,11 +100,14 @@ static void Prg_ResetItem (struct ProgramItem *Item); static void Prg_GetPrgItemTxtFromDB (long ItmCod,char Txt[Cns_MAX_BYTES_TEXT + 1]); static void Prg_PutParamItmCod (long ItmCod); +static unsigned Prg_GetMaxItemLevel (void); static unsigned Prg_GetMaxItemIndex (void); -static unsigned Prg_GetPrevItemIndex (unsigned ItmInd); -static unsigned Prg_GetNextItemIndex (unsigned ItmInd); -static void Prg_ExchangeItems (unsigned ItmIndTop,unsigned ItmIndBottom); -static long Prg_GetItmCodFromItmInd (unsigned ItmInd); +static unsigned Prg_GetPrevItemIndex (unsigned Index); +static unsigned Prg_GetNextItemIndex (unsigned Index); +static unsigned Prg_GetItemLevelFromIndex (unsigned Index); +static unsigned Prg_GetNextIndexNotChild (const struct ProgramItem *Item); +static void Prg_ExchangeItems (unsigned TopIndex,unsigned BottomIndex); +static void Prg_MoveItemAndChildrenToRight (unsigned Index,unsigned NextIndex); static bool Prg_CheckIfSimilarPrgItemExists (const char *Field,const char *Value,long ItmCod); static void Prg_ShowLstGrpsToEditPrgItem (long ItmCod); @@ -143,6 +147,10 @@ static void Prg_ShowAllItems (void) /***** Get list of program items *****/ Prg_GetListPrgItems (); + if (Gbl.Prg.Num) + Gbl.Prg.MaxLevel = Prg_GetMaxItemLevel (); + else + Gbl.Prg.MaxLevel = 0; /***** Compute variables related to pagination *****/ Pagination.NumItems = Gbl.Prg.Num; @@ -237,7 +245,7 @@ static void Prg_PutIconToCreateNewItem (void) /***** Put form to create a new program item *****/ Prg_SetCurrentItmCod (-1L); - Prg_SetCurrentItmInd (0); + Prg_SetCurrentIndex (0); Ico_PutContextualIconToAdd (ActFrmNewPrgItm,NULL,Prg_PutParams, Txt_New_item); } @@ -251,7 +259,7 @@ static void Prg_PutButtonToCreateNewItem (void) extern const char *Txt_New_item; Prg_SetCurrentItmCod (-1L); - Prg_SetCurrentItmInd (0); + Prg_SetCurrentIndex (0); Frm_StartForm (ActFrmNewPrgItm); Prg_PutParams (); Btn_PutConfirmButton (Txt_New_item); @@ -271,12 +279,15 @@ static void Prg_ParamsWhichGroupsToShow (void) /************************** Show one program item ****************************/ /*****************************************************************************/ -static void Prg_ShowOneItem (long ItmCod,unsigned MaxItmInd,bool PrintView) +#define Prg_WIDTH_NUM_ITEM 20 + +static void Prg_ShowOneItem (long ItmCod,unsigned MaxIndex,bool PrintView) { char *Anchor = NULL; static unsigned UniqueId = 0; char *Id; struct ProgramItem Item; + unsigned ColSpan; Dat_StartEndTime_t StartEndTime; char Txt[Cns_MAX_BYTES_TEXT + 1]; @@ -287,33 +298,72 @@ static void Prg_ShowOneItem (long ItmCod,unsigned MaxItmInd,bool PrintView) /***** Set anchor string *****/ Frm_SetAnchorStr (Item.ItmCod,&Anchor); - /***** Write first row of data of this program item *****/ + /***** Start row *****/ HTM_TR_Begin (NULL); - /* Forms to remove/edit this program item */ + /***** Forms to remove/edit this program item *****/ if (!PrintView) { - HTM_TD_Begin ("rowspan=\"2\" class=\"LT COLOR%u\"",Gbl.RowEvenOdd); - Prg_PutFormsToRemEditOnePrgItem (&Item,MaxItmInd,Anchor); + HTM_TD_Begin ("class=\"PRG_COL1 LT COLOR%u\"",Gbl.RowEvenOdd); + Prg_PutFormsToRemEditOnePrgItem (&Item,MaxIndex,Anchor); HTM_TD_End (); } - /* Program item title */ + /***** Indent depending on the level *****/ + if (Item.Level > 1) + { + HTM_TD_Begin ("colspan=\"%u\" class=\"COLOR%u\"", + Item.Level - 1,Gbl.RowEvenOdd); + HTM_TD_End (); + } + + /***** Item number *****/ + HTM_TD_Begin ("class=\"%s RT COLOR%u\" style=\"width:%dpx;\"", + Item.Hidden ? "ASG_TITLE_LIGHT" : + "ASG_TITLE", + Gbl.RowEvenOdd, + Item.Level * Prg_WIDTH_NUM_ITEM); + Prg_WriteNumItem (Item.Level); + HTM_TD_End (); + + /***** Title, groups and text *****/ + /* Begin title, groups and text */ + ColSpan = Gbl.Prg.MaxLevel - Item.Level + 1; if (PrintView) - HTM_TD_Begin ("class=\"%s LT\"", - Item.Hidden ? "ASG_TITLE_LIGHT" : - "ASG_TITLE"); + HTM_TD_Begin ("colspan=\"%u\" class=\"LT\"", + ColSpan); else - HTM_TD_Begin ("class=\"%s LT COLOR%u\"", - Item.Hidden ? "ASG_TITLE_LIGHT" : - "ASG_TITLE", - Gbl.RowEvenOdd); + HTM_TD_Begin ("colspan=\"%u\" class=\"LT COLOR%u\"", + ColSpan,Gbl.RowEvenOdd); HTM_ARTICLE_Begin (Anchor); + + /* Title */ + HTM_DIV_Begin ("class=\"%s\"", + Item.Hidden ? "ASG_TITLE_LIGHT" : + "ASG_TITLE"); HTM_Txt (Item.Title); + HTM_DIV_End (); + + /* Groups */ + if (Gbl.Crs.Grps.NumGrps) + Prg_GetAndWriteNamesOfGrpsAssociatedToItem (&Item); + + /* Text */ + Prg_GetPrgItemTxtFromDB (Item.ItmCod,Txt); + Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, + Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML + Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links + + HTM_DIV_Begin ("class=\"PAR %s\"",Item.Hidden ? "DAT_LIGHT" : + "DAT"); + HTM_Txt (Txt); + HTM_DIV_End (); + + /* End title, groups and text */ HTM_ARTICLE_End (); HTM_TD_End (); - /* Start/end date/time */ + /***** Start/end date/time *****/ UniqueId++; for (StartEndTime = (Dat_StartEndTime_t) 0; @@ -323,14 +373,14 @@ static void Prg_ShowOneItem (long ItmCod,unsigned MaxItmInd,bool PrintView) if (asprintf (&Id,"scd_date_%u_%u",(unsigned) StartEndTime,UniqueId) < 0) Lay_NotEnoughMemoryExit (); if (PrintView) - HTM_TD_Begin ("rowspan=\"2\" id=\"%s\" class=\"%s LT\"", + HTM_TD_Begin ("id=\"%s\" class=\"%s LT\"", Id, Item.Hidden ? (Item.Open ? "DATE_GREEN_LIGHT" : "DATE_RED_LIGHT") : (Item.Open ? "DATE_GREEN" : "DATE_RED")); else - HTM_TD_Begin ("rowspan=\"2\" id=\"%s\" class=\"%s LT COLOR%u\"", + HTM_TD_Begin ("id=\"%s\" class=\"%s LT COLOR%u\"", Id, Item.Hidden ? (Item.Open ? "DATE_GREEN_LIGHT" : "DATE_RED_LIGHT") : @@ -346,40 +396,40 @@ static void Prg_ShowOneItem (long ItmCod,unsigned MaxItmInd,bool PrintView) HTM_TR_End (); - /***** Write second row of data of this program item *****/ - HTM_TR_Begin (NULL); - - /* Text of the program item */ - Prg_GetPrgItemTxtFromDB (Item.ItmCod,Txt); - Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, - Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML - Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links - if (PrintView) - HTM_TD_Begin ("class=\"LT\""); - else - HTM_TD_Begin ("class=\"LT COLOR%u\"",Gbl.RowEvenOdd); - if (Gbl.Crs.Grps.NumGrps) - Prg_GetAndWriteNamesOfGrpsAssociatedToItem (&Item); - HTM_DIV_Begin ("class=\"PAR %s\"",Item.Hidden ? "DAT_LIGHT" : - "DAT"); - HTM_Txt (Txt); - HTM_DIV_End (); - HTM_TD_End (); - - HTM_TR_End (); - /***** Free anchor string *****/ Frm_FreeAnchorStr (Anchor); Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; } +/*****************************************************************************/ +/******************** Write number of item in legal style ********************/ +/*****************************************************************************/ + +static void Prg_WriteNumItem (unsigned Level) + { + static unsigned CodItem[100] = {0}; // TODO: Limit level? + unsigned N; + + CodItem[Level]++; + + for (N = 1; + N <= Level; + N++) + { + if (N > 1) + HTM_Txt ("."); + + HTM_Unsigned (CodItem[N]); + } + } + /*****************************************************************************/ /**************** Put a link (form) to edit one program item *****************/ /*****************************************************************************/ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item, - unsigned MaxItmInd, + unsigned MaxIndex, const char *Anchor) { extern const char *Txt_Move_up_X; @@ -391,12 +441,12 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item, char StrItemIndex[Cns_MAX_DECIMAL_DIGITS_UINT + 1]; Prg_SetCurrentItmCod (Item->ItmCod); // Used as parameter in contextual links - Prg_SetCurrentItmInd (Item->ItmInd); // Used as parameter in contextual links + Prg_SetCurrentIndex (Item->Index); // Used as parameter in contextual links /***** Initialize item index string *****/ snprintf (StrItemIndex,sizeof (StrItemIndex), "%u", - Item->ItmInd); + Item->Index); switch (Gbl.Usrs.Me.Role.Logged) { @@ -417,7 +467,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item, HTM_BR (); /***** Put icon to move up the item *****/ - if (Item->ItmInd > 1) + if (Item->Index > 1) { Lay_PutContextualLinkOnlyIcon (ActUp_PrgItm,NULL,Prg_PutParams, "arrow-up.svg", @@ -429,7 +479,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item, Ico_PutIconOff ("arrow-up.svg",Txt_Movement_not_allowed); /***** Put icon to move down the item *****/ - if (Item->ItmInd < MaxItmInd) + if (Item->Index < MaxIndex) { Lay_PutContextualLinkOnlyIcon (ActDwnPrgItm,NULL,Prg_PutParams, "arrow-down.svg", @@ -445,7 +495,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item, /***** Icon to increase the level of an item *****/ if (Item->Level > 1) { - Lay_PutContextualLinkOnlyIcon (ActRgtPrgItm,NULL,Prg_PutParams, + Lay_PutContextualLinkOnlyIcon (ActLftPrgItm,NULL,Prg_PutParams, "arrow-left.svg", Str_BuildStringStr (Txt_Increase_level_of_X, StrItemIndex)); @@ -457,7 +507,7 @@ static void Prg_PutFormsToRemEditOnePrgItem (const struct ProgramItem *Item, /***** Icon to decrease level item *****/ if (Item->Level < LastLevel + 1) { - Lay_PutContextualLinkOnlyIcon (ActLftPrgItm,NULL,Prg_PutParams, + Lay_PutContextualLinkOnlyIcon (ActRgtPrgItm,NULL,Prg_PutParams, "arrow-right.svg", Str_BuildStringStr (Txt_Decrease_level_of_X, StrItemIndex)); @@ -490,14 +540,14 @@ static long Prg_GetCurrentItmCod (void) return Prg_CurrentItmCod; } -static void Prg_SetCurrentItmInd (unsigned ItmInd) +static void Prg_SetCurrentIndex (unsigned Index) { - Prg_CurrentItmInd = ItmInd; + Prg_CurrentIndex = Index; } static unsigned Prg_GetCurrentItmInd (void) { - return Prg_CurrentItmInd; + return Prg_CurrentIndex; } /*****************************************************************************/ @@ -521,9 +571,9 @@ static void Prg_PutParams (void) /******************** Write parameter with index of item *********************/ /*****************************************************************************/ -static void Prg_PutParamItmInd (unsigned ItmInd) +static void Prg_PutParamItmInd (unsigned Index) { - Par_PutHiddenParamUnsigned (NULL,"ItmInd",ItmInd); + Par_PutHiddenParamUnsigned (NULL,"Index",Index); } /*****************************************************************************/ @@ -532,13 +582,13 @@ static void Prg_PutParamItmInd (unsigned ItmInd) static unsigned Prg_GetParamItmInd (void) { - long ItmInd; + long Index; - ItmInd = Par_GetParToLong ("ItmInd"); - if (ItmInd < 0) + Index = Par_GetParToLong ("Index"); + if (Index < 0) Lay_ShowErrorAndExit ("Wrong item index."); - return (unsigned) ItmInd; + return (unsigned) Index; } /*****************************************************************************/ @@ -644,7 +694,8 @@ void Prg_GetDataOfItemByCod (struct ProgramItem *Item) "NOW() BETWEEN StartTime AND EndTime," // row[7] "Title" // row[8] " FROM prg_items" - " WHERE ItmCod=%ld AND CrsCod=%ld", + " WHERE ItmCod=%ld" + " AND CrsCod=%ld", // Extra check Item->ItmCod,Gbl.Hierarchy.Crs.CrsCod); /***** Get data of program item *****/ @@ -689,7 +740,7 @@ static void Prg_GetDataOfItem (struct ProgramItem *Item, Item->ItmCod = Str_ConvertStrCodToLongCod (row[0]); /* Get index of the program item (row[1]) */ - Item->ItmInd = Str_ConvertStrToUnsigned (row[1]); + Item->Index = Str_ConvertStrToUnsigned (row[1]); /* Get level of the program item (row[2]) */ Item->Level = Str_ConvertStrToUnsigned (row[2]); @@ -728,7 +779,7 @@ static void Prg_GetDataOfItem (struct ProgramItem *Item, static void Prg_ResetItem (struct ProgramItem *Item) { Item->ItmCod = -1L; - Item->ItmInd = 0; + Item->Index = 0; Item->Level = 1; Item->Hidden = false; Item->UsrCod = -1L; @@ -768,7 +819,8 @@ static void Prg_GetPrgItemTxtFromDB (long ItmCod,char Txt[Cns_MAX_BYTES_TEXT + 1 /***** Get text of program item from database *****/ NumRows = DB_QuerySELECT (&mysql_res,"can not get program item text", "SELECT Txt FROM prg_items" - " WHERE ItmCod=%ld AND CrsCod=%ld", + " WHERE ItmCod=%ld" + " AND CrsCod=%ld", // Extra check ItmCod,Gbl.Hierarchy.Crs.CrsCod); /***** The result of the query must have one row or none *****/ @@ -831,7 +883,7 @@ void Prg_ReqRemPrgItem (void) /***** Show question and button to remove the program item *****/ Prg_SetCurrentItmCod (Item.ItmCod); - Prg_SetCurrentItmInd (Item.ItmInd); + Prg_SetCurrentIndex (Item.Index); Ale_ShowAlertAndButton (ActRemPrgItm,NULL,NULL,Prg_PutParams, Btn_REMOVE_BUTTON,Txt_Remove_item, Ale_QUESTION,Txt_Do_you_really_want_to_remove_the_item_X, @@ -890,7 +942,8 @@ void Prg_HidePrgItem (void) /***** Hide program item *****/ DB_QueryUPDATE ("can not hide program item", "UPDATE prg_items SET Hidden='Y'" - " WHERE ItmCod=%ld AND CrsCod=%ld", + " WHERE ItmCod=%ld" + " AND CrsCod=%ld", // Extra check Item.ItmCod,Gbl.Hierarchy.Crs.CrsCod); /***** Show program items again *****/ @@ -915,7 +968,8 @@ void Prg_ShowPrgItem (void) /***** Hide program item *****/ DB_QueryUPDATE ("can not show program item", "UPDATE prg_items SET Hidden='N'" - " WHERE ItmCod=%ld AND CrsCod=%ld", + " WHERE ItmCod=%ld" + " AND CrsCod=%ld", // Extra check Item.ItmCod,Gbl.Hierarchy.Crs.CrsCod); /***** Show program items again *****/ @@ -931,8 +985,8 @@ void Prg_MoveUpPrgItem (void) extern const char *Txt_The_item_has_been_moved_up; extern const char *Txt_Movement_not_allowed; struct ProgramItem Item; - unsigned ItmIndTop; - unsigned ItmIndBottom; + unsigned TopIndex; + unsigned BottomIndex; /***** Get program item code *****/ if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L) @@ -942,18 +996,18 @@ void Prg_MoveUpPrgItem (void) Prg_GetDataOfItemByCod (&Item); /***** Get item index *****/ - ItmIndBottom = Prg_GetParamItmInd (); + BottomIndex = Prg_GetParamItmInd (); /***** Move up item *****/ - if (ItmIndBottom > 1) + if (BottomIndex > 1) { /* Indexes of items to be exchanged */ - ItmIndTop = Prg_GetPrevItemIndex (ItmIndBottom); - if (!ItmIndTop) + TopIndex = Prg_GetPrevItemIndex (BottomIndex); + if (!TopIndex) Lay_ShowErrorAndExit ("Wrong index of item."); /* Exchange items */ - Prg_ExchangeItems (ItmIndTop,ItmIndBottom); + Prg_ExchangeItems (TopIndex,BottomIndex); /* Success alert */ Ale_ShowAlert (Ale_SUCCESS,Txt_The_item_has_been_moved_up); @@ -975,9 +1029,9 @@ void Prg_MoveDownPrgItem (void) extern const char *Txt_Movement_not_allowed; extern const char *Txt_No_items; struct ProgramItem Item; - unsigned ItmIndTop; - unsigned ItmIndBottom; - unsigned MaxItmInd; // 0 if no items + unsigned TopIndex; + unsigned BottomIndex; + unsigned MaxIndex; // 0 if no items /***** Get program item code *****/ if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L) @@ -987,23 +1041,23 @@ void Prg_MoveDownPrgItem (void) Prg_GetDataOfItemByCod (&Item); /***** Get item index *****/ - ItmIndTop = Prg_GetParamItmInd (); + TopIndex = Prg_GetParamItmInd (); /***** Get maximum item index *****/ - MaxItmInd = Prg_GetMaxItemIndex (); + MaxIndex = Prg_GetMaxItemIndex (); /***** Move down item *****/ - if (MaxItmInd) + if (MaxIndex) { - if (ItmIndTop < MaxItmInd) + if (TopIndex < MaxIndex) { /* Indexes of items to be exchanged */ - ItmIndBottom = Prg_GetNextItemIndex (ItmIndTop); - if (!ItmIndBottom) + BottomIndex = Prg_GetNextItemIndex (TopIndex); + if (!BottomIndex) Lay_ShowErrorAndExit ("Wrong index of item."); /* Exchange items */ - Prg_ExchangeItems (ItmIndTop,ItmIndBottom); + Prg_ExchangeItems (TopIndex,BottomIndex); /* Success alert */ Ale_ShowAlert (Ale_SUCCESS,Txt_The_item_has_been_moved_down); @@ -1024,7 +1078,12 @@ void Prg_MoveDownPrgItem (void) void Prg_MoveRightPrgItem (void) { + extern const char *Txt_The_item_has_been_moved_to_the_right; + extern const char *Txt_Movement_not_allowed; struct ProgramItem Item; + unsigned PrevIndex; + unsigned PrevLevel; + unsigned NextIndex; /***** Get program item code *****/ if ((Item.ItmCod = Prg_GetParamItmCod ()) == -1L) @@ -1034,7 +1093,27 @@ void Prg_MoveRightPrgItem (void) Prg_GetDataOfItemByCod (&Item); /***** Move right item (increase level) *****/ - // TODO: Implement + /* Index of previous item */ + PrevIndex = Prg_GetPrevItemIndex (Item.Index); + if (PrevIndex) // Must be >= 1 + { + PrevLevel = Prg_GetItemLevelFromIndex (PrevIndex); + if (Item.Level <= PrevLevel) + { + /* Get index of next item not children */ + NextIndex = Prg_GetNextIndexNotChild (&Item); + + /* Move item and its children to right */ + Prg_MoveItemAndChildrenToRight (Item.Index,NextIndex); + + /* Success alert */ + Ale_ShowAlert (Ale_SUCCESS,Txt_The_item_has_been_moved_to_the_right); + } + else + Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); + } + else + Ale_ShowAlert (Ale_WARNING,Txt_Movement_not_allowed); /***** Show program items again *****/ Prg_SeeCourseProgram (); @@ -1062,6 +1141,34 @@ void Prg_MoveLeftPrgItem (void) Prg_SeeCourseProgram (); } +/*****************************************************************************/ +/******************* Get maximum level in a course program *******************/ +/*****************************************************************************/ +// Return 0 if no items + +static unsigned Prg_GetMaxItemLevel (void) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned MaxLevel = 0; + + /***** Get maximum item index in a course program from database *****/ + DB_QuerySELECT (&mysql_res,"can not get last item index", + "SELECT MAX(Level)" + " FROM prg_items" + " WHERE CrsCod=%ld", + Gbl.Hierarchy.Crs.CrsCod); + row = mysql_fetch_row (mysql_res); + if (row[0]) // There are items + if (sscanf (row[0],"%u",&MaxLevel) != 1) + Lay_ShowErrorAndExit ("Error when getting maximum item level."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return MaxLevel; + } + /*****************************************************************************/ /**************** Get maximum item index in a course program *****************/ /*****************************************************************************/ @@ -1072,7 +1179,7 @@ static unsigned Prg_GetMaxItemIndex (void) { MYSQL_RES *mysql_res; MYSQL_ROW row; - unsigned ItmInd = 0; + unsigned MaxIndex = 0; /***** Get maximum item index in a course program from database *****/ DB_QuerySELECT (&mysql_res,"can not get last item index", @@ -1082,125 +1189,215 @@ static unsigned Prg_GetMaxItemIndex (void) Gbl.Hierarchy.Crs.CrsCod); row = mysql_fetch_row (mysql_res); if (row[0]) // There are items - if (sscanf (row[0],"%u",&ItmInd) != 1) + if (sscanf (row[0],"%u",&MaxIndex) != 1) Lay_ShowErrorAndExit ("Error when getting last item index."); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); - return ItmInd; + return MaxIndex; } /*****************************************************************************/ -/*********** Get previous item index to a given index in a course ************/ +/******** Get previous item index to a given index in current course *********/ /*****************************************************************************/ // Input item index can be 1, 2, 3... n-1 // Return item index will be 1, 2, 3... n if previous item exists, or 0 if no previous item -static unsigned Prg_GetPrevItemIndex (unsigned ItmInd) +static unsigned Prg_GetPrevItemIndex (unsigned Index) { MYSQL_RES *mysql_res; MYSQL_ROW row; - unsigned PrevItmInd = 0; + unsigned PrevIndex = 0; /***** Get previous item index in a course from database *****/ // Although indexes are always continuous... // ...this implementation works even with non continuous indexes if (!DB_QuerySELECT (&mysql_res,"can not get previous item index", - "SELECT MAX(ItmInd) FROM prg_items" - " WHERE CrsCod=%ld AND ItmInd<%u", - Gbl.Hierarchy.Crs.CrsCod,ItmInd)) + "SELECT MAX(ItmInd)" // row[0] + " FROM prg_items" + " WHERE CrsCod=%ld" + " AND ItmInd<%u", + Gbl.Hierarchy.Crs.CrsCod,Index)) Lay_ShowErrorAndExit ("Error: previous item index not found."); /***** Get previous item index (row[0]) *****/ row = mysql_fetch_row (mysql_res); if (row) if (row[0]) - if (sscanf (row[0],"%u",&PrevItmInd) != 1) + if (sscanf (row[0],"%u",&PrevIndex) != 1) Lay_ShowErrorAndExit ("Error when getting previous item index."); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); - return PrevItmInd; + return PrevIndex; } /*****************************************************************************/ -/************** Get next item index to a given index in a course *************/ +/********** Get next item index to a given index in current course ***********/ /*****************************************************************************/ // Input item index can be 0, 1, 2, 3... n-1 // Return item index will be 1, 2, 3... n if next item exists, or 0 if no next item -static unsigned Prg_GetNextItemIndex (unsigned ItmInd) +static unsigned Prg_GetNextItemIndex (unsigned Index) { MYSQL_RES *mysql_res; MYSQL_ROW row; - unsigned NextItmInd = 0; + unsigned NextIndex = 0; /***** Get next item index in a course from database *****/ // Although indexes are always continuous... // ...this implementation works even with non continuous indexes if (!DB_QuerySELECT (&mysql_res,"can not get next item index", - "SELECT MIN(ItmInd) FROM prg_items" - " WHERE CrsCod=%ld AND ItmInd>%u", - Gbl.Hierarchy.Crs.CrsCod,ItmInd)) + "SELECT MIN(ItmInd)" // row[0] + " FROM prg_items" + " WHERE CrsCod=%ld" + " AND ItmInd>%u", + Gbl.Hierarchy.Crs.CrsCod,Index)) Lay_ShowErrorAndExit ("Error: next item index not found."); /***** Get next item index (row[0]) *****/ row = mysql_fetch_row (mysql_res); if (row) if (row[0]) - if (sscanf (row[0],"%u",&NextItmInd) != 1) + if (sscanf (row[0],"%u",&NextIndex) != 1) Lay_ShowErrorAndExit ("Error when getting next item index."); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); - return NextItmInd; + return NextIndex; + } + +/*****************************************************************************/ +/************** Get item level from item index in current course *************/ +/*****************************************************************************/ + +static unsigned Prg_GetItemLevelFromIndex (unsigned Index) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned Level = 0; + + /***** Get previous item index in a course from database *****/ + // Although indexes are always continuous... + // ...this implementation works even with non continuous indexes + if (!DB_QuerySELECT (&mysql_res,"can not get item level", + "SELECT Level" // row[0] + " FROM prg_items" + " WHERE CrsCod=%ld AND ItmInd=%u", + Gbl.Hierarchy.Crs.CrsCod,Index)) + Lay_ShowErrorAndExit ("Error: previous item index not found."); + + /***** Get previous item index (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if (row) + if (row[0]) + if (sscanf (row[0],"%u",&Level) != 1) + Lay_ShowErrorAndExit ("Error when getting previous item index."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return Level; + } + +/*****************************************************************************/ +/************** Get next index not children in current course ****************/ +/*****************************************************************************/ +// Return 0 if no item found + +static unsigned Prg_GetNextIndexNotChild (const struct ProgramItem *Item) + { + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned NextIndex = 0; // 0 means no next item found + + /***** Get next item index which is not child of the given item *****/ + // Although indexes are always continuous... + // ...this implementation works even with non continuous indexes + if (!DB_QuerySELECT (&mysql_res,"can not get next item", + "SELECT MIN(ItmInd)" // row[0] + " FROM prg_items" + " WHERE CrsCod=%ld" + " AND ItmInd>%u AND Level<=%u", + Gbl.Hierarchy.Crs.CrsCod, + Item->Index,Item->Level)) + Lay_ShowErrorAndExit ("Error: next item not found."); + + /***** Get next item index (row[0]) *****/ + row = mysql_fetch_row (mysql_res); + if (row) + if (row[0]) + if (sscanf (row[0],"%u",&NextIndex) != 1) + Lay_ShowErrorAndExit ("Error when getting next item."); + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + + return NextIndex; + } + +/*****************************************************************************/ +/******************** Move item and its children to right ********************/ +/*****************************************************************************/ + +static void Prg_MoveItemAndChildrenToRight (unsigned Index,unsigned NextIndex) + { + DB_QueryUPDATE ("can not update items", + "UPDATE prg_items SET Level=Level+1" + " WHERE CrsCod=%ld" + " AND ItmInd>=%u AND ItmInd<%u", + Gbl.Hierarchy.Crs.CrsCod, + Index,NextIndex); } /*****************************************************************************/ /****** Exchange the order of two consecutive items in a course program ******/ /*****************************************************************************/ -static void Prg_ExchangeItems (unsigned ItmIndTop,unsigned ItmIndBottom) +static void Prg_ExchangeItems (unsigned TopIndex,unsigned BottomIndex) { - long ItmCodTop; - long ItmCodBottom; - /***** Lock table to make the move atomic *****/ DB_Query ("can not lock tables to move program item", "LOCK TABLES prg_items WRITE"); Gbl.DB.LockedTables = true; - /***** Get item codes of the items to be moved *****/ - ItmCodTop = Prg_GetItmCodFromItmInd (ItmIndTop); - ItmCodBottom = Prg_GetItmCodFromItmInd (ItmIndBottom); - /***** Exchange indexes of items *****/ /* Example: - ItmIndTop = 1; ItmCodTop = 218 - ItmIndBottom = 2; ItmCodBottom = 220 - +--------+--------+ +--------+--------+ +--------+--------+ - | ItmInd | ItmCod | | ItmInd | ItmCod | | ItmInd | ItmCod | - +--------+--------+ +--------+--------+ +--------+--------+ - | 1 | 218 | -----> | 2 | 218 | = | 1 | 220 | - | 2 | 220 | | 1 | 220 | | 2 | 218 | - | 3 | 232 | | 3 | 232 | | 3 | 232 | - +--------+--------+ +--------+--------+ +--------+--------+ - */ + TopIndex = 1; TopItmCod = 218 + BottomIndex = 2; BottomItmCod = 220 + Step 1 Step 2 Step 3 (Equivalent to) + +------+------+ +------+------+ +------+------+ +------+------+ +------+------+ + |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod| |ItmInd|ItmCod| + +------+------+ +------+------+ +------+------+ +------+------+ +------+------+ + Top: 1| 218| | 1| 218|-->| ->2| 218| | 2| 218|=| 1| 220| +Bottom: 2| 220|-->| ->0| 220| | 0| 220|-->| ->1| 220| | 2| 218| + | 3| 232| | 3| 232| | 3| 232| | 3| 232| | 3| 232| + +------+------+ +------+------+ +------+------+ +------+------+ +------+------+ + */ + /* Step 1: Set temporary bottom index to 0, + necessary to preserve unique index (CrsCod,ItmInd) */ DB_QueryUPDATE ("can not exchange indexes of items", - "UPDATE prg_items SET ItmInd=%u" - " WHERE CrsCod=%ld AND ItmCod=%ld", - ItmIndBottom, - Gbl.Hierarchy.Crs.CrsCod,ItmCodTop); + "UPDATE prg_items SET ItmInd=0" + " WHERE CrsCod=%ld AND ItmInd=%u", + Gbl.Hierarchy.Crs.CrsCod,BottomIndex); + /* Step 2: Set new top index to old bottom index */ DB_QueryUPDATE ("can not exchange indexes of items", "UPDATE prg_items SET ItmInd=%u" - " WHERE CrsCod=%ld AND ItmCod=%ld", - ItmIndTop, - Gbl.Hierarchy.Crs.CrsCod,ItmCodBottom); + " WHERE CrsCod=%ld AND ItmInd=%u", + BottomIndex, + Gbl.Hierarchy.Crs.CrsCod,TopIndex); + + /* Step 3: Set new bottom index to old top index */ + DB_QueryUPDATE ("can not exchange indexes of items", + "UPDATE prg_items SET ItmInd=%u" + " WHERE CrsCod=%ld AND ItmInd=0", + TopIndex, + Gbl.Hierarchy.Crs.CrsCod); /***** Unlock table *****/ Gbl.DB.LockedTables = false; // Set to false before the following unlock... @@ -1209,37 +1406,6 @@ static void Prg_ExchangeItems (unsigned ItmIndTop,unsigned ItmIndBottom) "UNLOCK TABLES"); } -/*****************************************************************************/ -/*************** Get item code given course and index of item ****************/ -/*****************************************************************************/ - -static long Prg_GetItmCodFromItmInd (unsigned ItmInd) - { - MYSQL_RES *mysql_res; - MYSQL_ROW row; - long ItmCod; - - /***** Get item code from item index *****/ - if (!DB_QuerySELECT (&mysql_res,"can not get item code", - "SELECT ItmCod" // row[0] - " FROM prg_items" - " WHERE CrsCod=%ld" - " AND ItmInd=%u", - Gbl.Hierarchy.Crs.CrsCod, - ItmInd)) - Lay_ShowErrorAndExit ("Error: wrong item index."); - - /***** Get item code (row[0]) *****/ - row = mysql_fetch_row (mysql_res); - if ((ItmCod = Str_ConvertStrCodToLongCod (row[0])) <= 0) - Lay_ShowErrorAndExit ("Error: wrong item code."); - - /***** Free structure that stores the query result *****/ - DB_FreeMySQLResult (&mysql_res); - - return ItmCod; - } - /*****************************************************************************/ /*************** Check if the title of a program item exists *****************/ /*****************************************************************************/ @@ -1308,13 +1474,13 @@ void Prg_RequestCreatOrEditPrgItem (void) { Frm_StartForm (ActNewPrgItm); Prg_SetCurrentItmCod (-1L); - Prg_SetCurrentItmInd (0); + Prg_SetCurrentIndex (0); } else { Frm_StartForm (ActChgPrgItm); Prg_SetCurrentItmCod (Item.ItmCod); - Prg_SetCurrentItmInd (Item.ItmInd); + Prg_SetCurrentIndex (Item.Index); } Prg_PutParams (); @@ -1549,7 +1715,7 @@ void Prg_RecFormPrgItem (void) static void Prg_CreatePrgItem (struct ProgramItem *Item,const char *Txt) { - unsigned MaxItmInd; + unsigned MaxIndex; /***** Lock table to create program item *****/ DB_Query ("can not lock tables to create program item", @@ -1557,10 +1723,10 @@ static void Prg_CreatePrgItem (struct ProgramItem *Item,const char *Txt) Gbl.DB.LockedTables = true; /***** Get maximum item index *****/ - MaxItmInd = Prg_GetMaxItemIndex (); + MaxIndex = Prg_GetMaxItemIndex (); /***** Create a new program item *****/ - Item->ItmInd = MaxItmInd + 1; + Item->Index = MaxIndex + 1; Item->ItmCod = DB_QueryINSERTandReturnCode ("can not create new program item", "INSERT INTO prg_items" @@ -1568,7 +1734,7 @@ static void Prg_CreatePrgItem (struct ProgramItem *Item,const char *Txt) " VALUES" " (%u,%ld,%ld,FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld)," "'%s','%s')", - Item->ItmInd, + Item->Index, Gbl.Hierarchy.Crs.CrsCod, Gbl.Usrs.Me.UsrDat.UsrCod, Item->TimeUTC[Dat_START_TIME], @@ -1599,7 +1765,8 @@ static void Prg_UpdatePrgItem (struct ProgramItem *Item,const char *Txt) "StartTime=FROM_UNIXTIME(%ld)," "EndTime=FROM_UNIXTIME(%ld)," "Title='%s',Txt='%s'" - " WHERE ItmCod=%ld AND CrsCod=%ld", + " WHERE ItmCod=%ld" + " AND CrsCod=%ld", // Extra check Item->TimeUTC[Dat_START_TIME], Item->TimeUTC[Dat_END_TIME ], Item->Title, diff --git a/swad_program.h b/swad_program.h index e528f991a..0074eb8d6 100644 --- a/swad_program.h +++ b/swad_program.h @@ -42,7 +42,7 @@ struct ProgramItem { long ItmCod; - unsigned ItmInd; + unsigned Index; unsigned Level; bool Hidden; long UsrCod; diff --git a/swad_syllabus.c b/swad_syllabus.c index 6fb2d0a98..ffd2b6236 100644 --- a/swad_syllabus.c +++ b/swad_syllabus.c @@ -381,7 +381,7 @@ void Syl_LoadListItemsSyllabusIntoMemory (long CrsCod) /* Level of the item */ Syl_LstItemsSyllabus.Lst[0].Level = 1; - /* Code (numeración) of the item */ + /* Code (numeration) of the item */ CodItem[1] = 1; for (N = 1; N <= Syl_MAX_LEVELS_SYLLABUS; @@ -858,7 +858,7 @@ static void Syl_WriteNumItem (char *StrDst,FILE *FileTgt,int Level,int *CodItem) if (StrDst) StrDst[0] = '\0'; - for (N = 1; + for (N = 1; N <= Level; N++) { diff --git a/swad_text.c b/swad_text.c index a52ee7dcd..170c96dbb 100644 --- a/swad_text.c +++ b/swad_text.c @@ -47780,9 +47780,9 @@ const char *Txt_The_properties_of_file_X_have_been_saved = // Warning: it is ver const char *Txt_The_item_has_been_moved_down = #if L==1 // ca - "El ítem ha estat moguda cap avall."; + "L'element s'ha desplaçat cap avall."; #elif L==2 // de - "Der Programmelement wurde nach unten bewegt."; + "Der Programmelement wurde nach unten verschoben."; #elif L==3 // en "The item has been moved down."; #elif L==4 // es @@ -47792,16 +47792,58 @@ const char *Txt_The_item_has_been_moved_down = #elif L==6 // gn "El ítem se ha movido hacia abajo."; // Okoteve traducción #elif L==7 // it - "Il elemento è stato abbattuto."; + "Il elemento è stato spostato verso il basso."; #elif L==8 // pl - "Pozycja zostało przeniesione."; + "Przedmiot został przeniesiony w dół."; #elif L==9 // pt "O item foi movido para baixo."; #endif +const char *Txt_The_item_has_been_moved_to_the_left = +#if L==1 // ca + "L'element s'ha desplaçat a l'esquerra."; +#elif L==2 // de + "Der Programmelement wurde nach links verschoben."; +#elif L==3 // en + "The item has been moved to the left."; +#elif L==4 // es + "El ítem se ha movido hacia la izquierda."; +#elif L==5 // fr + "L'élément a été déplacé vers la gauche."; +#elif L==6 // gn + "El ítem se ha movido hacia la izquierda."; // Okoteve traducción +#elif L==7 // it + "Il elemento è stato spostato a sinistra."; +#elif L==8 // pl + "Przedmiot został przeniesiony w lewo."; +#elif L==9 // pt + "O item foi movido para a esquerda."; +#endif + +const char *Txt_The_item_has_been_moved_to_the_right = +#if L==1 // ca + "L'element s'ha desplaçat a la dreta."; +#elif L==2 // de + "Der Programmelement wurde nach rechts verschoben."; +#elif L==3 // en + "The item has been moved to the right."; +#elif L==4 // es + "El ítem se ha movido hacia la derecha."; +#elif L==5 // fr + "L'élément a été déplacé vers la droite."; +#elif L==6 // gn + "El ítem se ha movido hacia la derecha."; // Okoteve traducción +#elif L==7 // it + "Il elemento è stato spostato a destra."; +#elif L==8 // pl + "Przedmiot został przeniesiony w prawo."; +#elif L==9 // pt + "O item foi movido para a direita."; +#endif + const char *Txt_The_item_has_been_moved_up = #if L==1 // ca - "El ítem ha estat moguda cap amunt."; + "L'element s'ha desplaçat cap amunt."; #elif L==2 // de "Der Programmelement wurde nach oben verschoben."; #elif L==3 // en @@ -47813,9 +47855,9 @@ const char *Txt_The_item_has_been_moved_up = #elif L==6 // gn "El ítem se ha movido hacia arriba."; // Okoteve traducción #elif L==7 // it - "Il elemento è stato spostato."; + "Il elemento è stato spostato verso l'alto."; #elif L==8 // pl - "Pozycja zostało poruszone."; + "Przedmiot został przeniesiony w górę."; #elif L==9 // pt "O item foi movido para cima."; #endif