diff --git a/sql/swad.sql b/sql/swad.sql index d6bb1e9a4..f5eed37fc 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -1087,7 +1087,8 @@ CREATE TABLE IF NOT EXISTS tst_answers ( AnsInd TINYINT NOT NULL, Answer TEXT NOT NULL, Feedback TEXT NOT NULL, - Image VARCHAR(43) NOT NULL, + ImageName VARCHAR(43) NOT NULL, + ImageTitle TEXT NOT NULL, Correct ENUM('N','Y') NOT NULL, INDEX(QstCod)); -- @@ -1145,7 +1146,8 @@ CREATE TABLE IF NOT EXISTS tst_questions ( Shuffle ENUM('N','Y') NOT NULL, Stem TEXT NOT NULL, Feedback TEXT NOT NULL, - Image VARCHAR(43) NOT NULL, + ImageName VARCHAR(43) NOT NULL, + ImageTitle TEXT NOT NULL, NumHits INT NOT NULL DEFAULT 0, NumHitsNotBlank INT NOT NULL DEFAULT 0, Score DOUBLE PRECISION NOT NULL DEFAULT 0, diff --git a/swad_changelog.h b/swad_changelog.h index 34eff70c7..41cd704f6 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -131,13 +131,20 @@ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 15.181 (2016-04-05)" +#define Log_PLATFORM_VERSION "SWAD 15.182 (2016-04-06)" #define CSS_FILE "swad15.178.2.css" #define JS_FILE "swad15.178.2.js" // Number of lines (includes comments but not blank lines) has been got with the following command: // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1 /* + Version 15.182: Apr 06, 2016 Get fields title/attribution of images from form. (198610 lines) + 4 changes necessary in database: +ALTER TABLE tst_questions CHANGE COLUMN Image ImageName VARCHAR(43) NOT NULL; +ALTER TABLE tst_questions ADD COLUMN ImageTitle TEXT NOT NULL AFTER ImageName; +ALTER TABLE tst_answers CHANGE COLUMN Image ImageName VARCHAR(43) NOT NULL; +ALTER TABLE tst_answers ADD COLUMN ImageTitle TEXT NOT NULL AFTER ImageName; + Version 15.181: Apr 05, 2016 New fields in test questions with the title/attribution of images. (198515 lines) Version 15.180.7: Apr 05, 2016 Changes in layout of editor of question. (198473 lines) Version 15.180.6: Apr 05, 2016 Changes in layout of editor of question. (198490 lines) diff --git a/swad_database.c b/swad_database.c index 542581b65..8ec59a999 100644 --- a/swad_database.c +++ b/swad_database.c @@ -2290,24 +2290,26 @@ mysql> DESCRIBE timetable_tut; /***** Table tst_answers *****/ /* mysql> DESCRIBE tst_answers; -+----------+---------------+------+-----+---------+-------+ -| Field | Type | Null | Key | Default | Extra | -+----------+---------------+------+-----+---------+-------+ -| QstCod | int(11) | NO | MUL | NULL | | -| AnsInd | tinyint(4) | NO | | NULL | | -| Answer | text | NO | | NULL | | -| Feedback | text | NO | | NULL | | -| Image | varchar(43) | NO | | NULL | | -| Correct | enum('N','Y') | NO | | NULL | | -+----------+---------------+------+-----+---------+-------+ -6 rows in set (0.00 sec) ++------------+---------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++------------+---------------+------+-----+---------+-------+ +| QstCod | int(11) | NO | MUL | NULL | | +| AnsInd | tinyint(4) | NO | | NULL | | +| Answer | text | NO | | NULL | | +| Feedback | text | NO | | NULL | | +| ImageName | varchar(43) | NO | | NULL | | +| ImageTitle | text | NO | | NULL | | +| Correct | enum('N','Y') | NO | | NULL | | ++------------+---------------+------+-----+---------+-------+ +7 rows in set (0.00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_answers (" "QstCod INT NOT NULL," "AnsInd TINYINT NOT NULL," "Answer TEXT NOT NULL," "Feedback TEXT NOT NULL," - "Image VARCHAR(43) NOT NULL," + "ImageName VARCHAR(43) NOT NULL," + "ImageTitle TEXT NOT NULL," "Correct ENUM('N','Y') NOT NULL," "INDEX(QstCod))"); @@ -2421,12 +2423,13 @@ mysql> DESCRIBE tst_questions; | Shuffle | enum('N','Y') | NO | | NULL | | | Stem | text | NO | | NULL | | | Feedback | text | NO | | NULL | | -| Image | varchar(43) | NO | | NULL | | +| ImageName | varchar(43) | NO | | NULL | | +| ImageTitle | text | NO | | NULL | | | NumHits | int(11) | NO | | 0 | | | NumHitsNotBlank | int(11) | NO | | 0 | | | Score | double | NO | | 0 | | +-----------------+---------------------------------------------------------------------------+------+-----+---------+----------------+ -11 rows in set (0.00 sec) +12 rows in set (0.00 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS tst_questions (" "QstCod INT NOT NULL AUTO_INCREMENT," @@ -2436,7 +2439,8 @@ mysql> DESCRIBE tst_questions; "Shuffle ENUM('N','Y') NOT NULL," "Stem TEXT NOT NULL," "Feedback TEXT NOT NULL," - "Image VARCHAR(43) NOT NULL," + "ImageName VARCHAR(43) NOT NULL," + "ImageTitle TEXT NOT NULL," "NumHits INT NOT NULL DEFAULT 0," "NumHitsNotBlank INT NOT NULL DEFAULT 0," "Score DOUBLE PRECISION NOT NULL DEFAULT 0," diff --git a/swad_image.c b/swad_image.c index 27866985a..1b93be5c4 100644 --- a/swad_image.c +++ b/swad_image.c @@ -67,13 +67,54 @@ static void Img_ProcessImage (const char *FileNameImgOriginal, const char *FileNameImgProcessed, unsigned Width,unsigned Height,unsigned Quality); +/*****************************************************************************/ +/*************************** Reset image title *******************************/ +/*****************************************************************************/ + +void Img_ResetImageTitle (struct Image *Image) + { + if (Image->Title) + free ((void *) Image->Title); + Image->Title = NULL; + } + +/*****************************************************************************/ +/************ Get image title from a string and copy to struct ***************/ +/*****************************************************************************/ + +void Img_GetImageNameTitle (const char *Name,const char *Title, + struct Image *Image) + { + size_t Length; + + Img_ResetImageTitle (Image); + + if (Name[0]) + { + strncpy (Image->Name,Name,Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64); + Image->Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64] = '\0'; + + if (Image->Name[0]) // There is an image + if (Title[0]) + { + Length = strlen (Title); + if ((Image->Title = (char *) malloc (Length+1)) == NULL) + Lay_ShowErrorAndExit ("Error allocating memory for image title."); + strncpy (Image->Title,Title,Length); + Image->Title[Length] = '\0'; + } + } + else // No image in this question + Image->Name[0] = '\0'; + } + /*****************************************************************************/ /***************************** Get image from form ***************************/ /*****************************************************************************/ void Img_GetImageFromForm (unsigned NumOpt,struct Image *Image, - void (*GetImageName) (unsigned NumOpt,char *ImageName), - const char *ParamAction,const char *ParamFile, + void (*GetImageNameFromDB) (unsigned NumOpt,struct Image *Image), + const char *ParamAction,const char *ParamFile,const char *ParamTitle, unsigned Width,unsigned Height,unsigned Quality) { Image->Action = Img_GetImageActionFromForm (ParamAction); @@ -83,30 +124,34 @@ void Img_GetImageFromForm (unsigned NumOpt,struct Image *Image, case Img_ACTION_NO_IMAGE: // Do not use image (remove current image if exists) /***** Reset image name *****/ Image->Name[0] = '\0'; + Img_ResetImageTitle (Image); break; case Img_ACTION_KEEP_IMAGE: // Keep current image unchanged /***** Get image name *****/ - GetImageName (NumOpt,Image->Name); + GetImageNameFromDB (NumOpt,Image); if (Image->Name[0]) Image->Status = Img_NAME_STORED_IN_DB; break; case Img_ACTION_NEW_IMAGE: // Upload new image /***** Get new image (if present ==> process and create temporary file) *****/ - Img_GetAndProcessImageFileFromForm (Image,ParamFile,Width,Height,Quality); + Img_GetAndProcessImageFileFromForm (Image,ParamFile,ParamTitle, + Width,Height,Quality); if (Image->Status != Img_FILE_PROCESSED) // No new image received-processed successfully { /* Reset image name */ - Image->Name[0] = '\0'; Image->Status = Img_FILE_NONE; + Image->Name[0] = '\0'; + Img_ResetImageTitle (Image); } break; case Img_ACTION_CHANGE_IMAGE: // Replace old image by new image /***** Get new image (if present ==> process and create temporary file) *****/ - Img_GetAndProcessImageFileFromForm (Image,ParamFile,Width,Height,Quality); + Img_GetAndProcessImageFileFromForm (Image,ParamFile,ParamTitle, + Width,Height,Quality); if (Image->Status != Img_FILE_PROCESSED) // No new image received-processed successfully { /* Get image name */ - GetImageName (NumOpt,Image->Name); + GetImageNameFromDB (NumOpt,Image); Image->Status = (Image->Name[0] ? Img_NAME_STORED_IN_DB : Img_FILE_NONE); } @@ -137,7 +182,7 @@ Img_Action_t Img_GetImageActionFromForm (const char *ParamAction) // Return true if image is created void Img_GetAndProcessImageFileFromForm (struct Image *Image, - const char *ParamFile, + const char *ParamFile,const char *ParamTitle, unsigned Width,unsigned Height, unsigned Quality) { @@ -150,6 +195,8 @@ void Img_GetAndProcessImageFileFromForm (struct Image *Image, char FileNameImgOrig[PATH_MAX+1]; // Full name of original uploaded file char FileNameImgTmp[PATH_MAX+1]; // Full name of temporary processed file bool WrongType = false; + char Title[Cns_MAX_BYTES_TEXT+1]; + size_t Length; /***** Rest image file status *****/ Image->Status = Img_FILE_NONE; @@ -214,6 +261,17 @@ void Img_GetAndProcessImageFileFromForm (struct Image *Image, /***** Remove temporary original file *****/ unlink (FileNameImgOrig); + + /***** Get image title from form *****/ + Par_GetParToHTML (ParamTitle,Title,Cns_MAX_BYTES_TEXT); // TODO: Create a function to get only the length of a parameter + Length = strlen (Title); + if (Length > 0) + { + if ((Image->Title = (char *) malloc (Length+1)) == NULL) + Lay_ShowErrorAndExit ("Error allocating memory for image title."); + strncpy (Image->Title,Title,Length); + Image->Title[Length] = '\0'; + } } } diff --git a/swad_image.h b/swad_image.h index 68559f982..a2667d969 100644 --- a/swad_image.h +++ b/swad_image.h @@ -85,19 +85,24 @@ struct Image Img_Action_t Action; Img_FileStatus_t Status; char Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64+1]; + char *Title; // Title/attribution }; /*****************************************************************************/ /***************************** Public prototypes *****************************/ /*****************************************************************************/ +void Img_ResetImageTitle (struct Image *Image); +void Img_GetImageNameTitle (const char *Name,const char *Title, + struct Image *Image); + void Img_GetImageFromForm (unsigned NumOpt,struct Image *Image, - void (*GetImageName) (unsigned NumOpt,char *ImageName), - const char *ParamAction,const char *ParamFile, + void (*GetImageNameFromDB) (unsigned NumOpt,struct Image *Image), + const char *ParamAction,const char *ParamFile,const char *ParamTitle, unsigned Width,unsigned Height,unsigned Quality); Img_Action_t Img_GetImageActionFromForm (const char *ParamAction); void Img_GetAndProcessImageFileFromForm (struct Image *Image, - const char *ParamFile, + const char *ParamFile,const char *ParamTitle, unsigned Width,unsigned Height, unsigned Quality); diff --git a/swad_test.c b/swad_test.c index 73b1acd7e..706a350f8 100644 --- a/swad_test.c +++ b/swad_test.c @@ -220,9 +220,10 @@ static int Tst_CountNumAnswerTypesInList (void); static void Tst_PutFormEditOneQst (char *Stem,char *Feedback); static void Tst_InitImagesOfQuestion (void); +static void Tst_FreeImagesOfQuestion (void); static void Tst_GetQstDataFromDB (char *Stem,char *Feedback); -static void Tst_GetImageNameFromDB (unsigned NumOpt,char *ImageName); +static void Tst_GetImageFromDB (unsigned NumOpt,struct Image *Image); static Tst_AnswerType_t Tst_ConvertFromUnsignedStrToAnsTyp (const char *UnsignedStr); static void Tst_GetQstFromForm (char *Stem,char *Feedback); @@ -902,16 +903,17 @@ static void Tst_ShowTstResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank, /***** Get row of the result of the query *****/ row = mysql_fetch_row (mysql_res); /* - row[0] QstCod - row[1] UNIX_TIMESTAMP(EditTime) - row[2] AnsType - row[3] Shuffle - row[4] Stem - row[5] Image - row[6] Feedback - row[7] NumHits - row[8] NumHitsNotBlank - row[9] Score + row[ 0] QstCod + row[ 1] UNIX_TIMESTAMP(EditTime) + row[ 2] AnsType + row[ 3] Shuffle + row[ 4] Stem + row[ 5] Feedback + row[ 6] ImageName + row[ 7] ImageTitle + row[ 8] NumHits + row[ 9] NumHitsNotBlank + row[10] Score */ /***** Get the code of question (row[0]) *****/ @@ -966,16 +968,17 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row, { extern const char *Txt_TST_STR_ANSWER_TYPES[Tst_NUM_ANS_TYPES]; /* - row[0] QstCod - row[1] UNIX_TIMESTAMP(EditTime) - row[2] AnsType - row[3] Shuffle - row[4] Stem - row[5] Image - row[6] Feedback - row[7] NumHits - row[8] NumHitsNotBlank - row[9] Score + row[ 0] QstCod + row[ 1] UNIX_TIMESTAMP(EditTime) + row[ 2] AnsType + row[ 3] Shuffle + row[ 4] Stem + row[ 5] Feedback + row[ 6] ImageName + row[ 7] ImageTitle + row[ 8] NumHits + row[ 9] NumHitsNotBlank + row[10] Score */ /***** Write number of question *****/ @@ -991,15 +994,15 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row, "", Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); - /***** Write stem (row[4]), answers depending on shuffle (row[3]) and feedback (row[6]) *****/ + /***** Write stem (row[4]), image (row[6], row[7]), + answers depending on shuffle (row[3]) and feedback (row[5]) *****/ fprintf (Gbl.F.Out,"