View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0011818 | Scribus | User Interface | public | 2013-10-28 16:55 | 2015-12-04 10:33 |
Reporter | JLuc | Assigned To | |||
Priority | normal | Severity | minor | Reproducibility | have not tried |
Status | new | Resolution | open | ||
Product Version | 1.5.0svn | ||||
Summary | 0011818: [PATCH] No page range check in PDF export dialog | ||||
Description | In the PDF export dialog, when the "pages" input specifies a too large page number or an interval out of the range of the existing pages, then no warning is issued and a PDF including only the last page of the PDF is created. For ex, in a 10 page document, input "20-30" will lead to a one page doc with the 10th page. Scribus should detect that and issue an error. | ||||
Additional Information | It's easy to do such a mistake when a page number offset has been specified in the document section, because the screen shows biger page number than there are pages actualy in the document. In such a case, its difficult to understand why there is only one page in the PDF. | ||||
Tags | #easyhack | ||||
Patch | Yes | ||||
|
There is no warning neither when the page range is totally invalid, like 'sdfsfsd' : it creates an empty PDF. |
|
imo, no warning needed on overflow: just do something meaningful (like printing up to the first/last page). for invalid input: do nothing (with warning) or print all (no warning?) |
|
I have made changes in two files: 1. /scribus/ui/pdfopts.cpp 2. /scribus/ui/pdfopts.h Acceptable inputs are:(as scribus says when hovering on text input box) Insert a comma separated list of tokens where a token can be * for all the pages, 1-5 for a range of pages or a single page number. Invalid inputs are: 1. single page number out of range 2. range of pages out of range 3. string containing characters other than white space, tab, numeric characters, '-','.'. 4. string containing characters white space, tab, numeric characters, '-','.' but in unacceptable form On invalid input warning message box will pop up saying: "invalid pagerangestring". user needs to press "OK" pushbutton in order to proceed further |
|
I tested the patch and it works as said. |
|
I found a little bug : the test also triggers an error in case "Export all pages" is checked. In such a case, the test should not be run at all. + also please correct your patch so as to follow scribus coding standards : http://wiki.scribus.net/canvas/Official:Coding_Standards These are readability rules. Mostly, you ought to use spaces everywhere required, and linebreaks before opening braces... Thanks ! |
|
fix.diff (6,718 bytes)
Index: scribus/ui/pdfopts.cpp =================================================================== --- scribus/ui/pdfopts.cpp (revision 18743) +++ scribus/ui/pdfopts.cpp (working copy) @@ -151,6 +151,24 @@ void PDFExportDialog::DoExport() { + //starts here: checking validity of pagerangestring + if(Options->AllPages->isChecked()==0) + { + QString pageRangeStringtoCheck=Options->PageNr->text(); + + bool invalidPageRangeString=checkPageRangeStringValidity(pageRangeStringtoCheck,m_doc->Pages->count()); + if (invalidPageRangeString )//showing warning box if invalid pagerangestring + { + + QMessageBox::warning(this, + CommonStrings::trWarning, + tr("Invalid pagerangeString: \n"), + CommonStrings::tr_OK); + return; + } + } + //ends here: checking validity of pagerangestring + bool createPath = false; QString fn = QDir::fromNativeSeparators(fileNameLineEdit->text()); // Checking if the path exists @@ -198,13 +216,149 @@ m_presEffects[Options->PgSel].Di = Options->EDirection_2_2->currentIndex(); m_opts.LPISettings[Options->SelLPIcolor].Frequency = Options->LPIfreq->value(); m_opts.LPISettings[Options->SelLPIcolor].Angle = Options->LPIangle->value(); - m_opts.LPISettings[Options->SelLPIcolor].SpotFunc = Options->LPIfunc->currentIndex(); - accept(); + m_opts.LPISettings[Options->SelLPIcolor].SpotFunc = Options->LPIfunc->currentIndex(); + accept(); } - else + else{ return; + } } +bool PDFExportDialog::checkPageRangeStringValidity(QString pagerangestringtocheck,int sourcePageCount ){ + QString tmp(pagerangestringtocheck); + QString token; + int from, to, pageNr; + do + { + if (tmp.indexOf(",") == -1) + { + + token = tmp; + tmp = ""; + } + else + { + token = tmp.left(tmp.indexOf(",")); + tmp = tmp.right(tmp.length() - tmp.indexOf(",") - 1); + } + + token = token.trimmed(); + //start: + if(token.isEmpty()){ + //error + return true;//for null string + } + //end: + if (token == "*") // Import all source doc pages + { + + } + else if (token.indexOf("-") != -1) // import a range of source doc pages + { + //start: + //here strings 'from' and 'to' can only contain numeric characters and single dot + //also they must be in rage 1 to max doc pages + QString fromstring=QString(token.left(token.indexOf("-"))); + fromstring=fromstring.trimmed(); + QString tostring=QString(token.right(token.length() - token.indexOf("-") - 1)); + tostring=tostring.trimmed(); + int k; + int dotcount=0; + if(fromstring.isEmpty()){ + //error + return true; + } + for(k=0;k<fromstring.size();k++){ + if(fromstring.at(k)=='.'){ + dotcount++; + } + else if((48<=fromstring.at(k))&&(fromstring.at(k)<=57)){ + //fine + + } + else + return true;//error + + } + if(dotcount>1){ + return true;//error + } + dotcount=0; + if(tostring.isEmpty()){ + //error + return true; + } + for(k=0;k<tostring.size();k++){ + if(tostring.at(k)=='.'){ + dotcount++; + } + else if((48<=tostring.at(k))&&(tostring.at(k)<=57)){ + //fine + + } + else + return true;//error + + } + if(dotcount>1){ + return true;//error + } + //end: + from = QString(token.left(token.indexOf("-"))).toInt(); + to = QString(token.right(token.length() - token.indexOf("-") - 1)).toInt(); + //also they must be in rage 1 to max doc pages + //start : comparing with pages doc contain + if((from<=sourcePageCount)&&(1<=from)){ + + //input page number is within range + } + else{ + + return true; //out of range option + } + if((to<=sourcePageCount)&&(1<=to)){ + + //input page number is within range + } + else{ + + return true; //out of range option + } + //end : comparing with pages doc contain + } + else // import single source doc page + { + //start: + QString pageNrString=token; + int k; + int dotcount=0; + for(k=0;k<pageNrString.size();k++){ + if(pageNrString.at(k)=='.'){ + dotcount++; + } + else if((48<=pageNrString.at(k))&&(pageNrString.at(k)<=57)){ + //fine + + } + else + return true;//error + + } + if(dotcount>1){ + return true;//error + } + //end: + pageNr = token.toInt(); + if ((pageNr > 0) && (pageNr <= sourcePageCount)){ + + } + else{ + return true;//error + } + } + } while (!tmp.isEmpty()); + return false; +} void PDFExportDialog::ChangeFile() { QString fn; @@ -231,6 +385,8 @@ fileNameLineEdit->setText( QDir::toNativeSeparators(fileName) ); } + + void PDFExportDialog::updateDocOptions() { m_opts.fileName = QDir::fromNativeSeparators(fileNameLineEdit->text()); Index: scribus/ui/pdfopts.h =================================================================== --- scribus/ui/pdfopts.h (revision 18743) +++ scribus/ui/pdfopts.h (working copy) @@ -60,6 +60,7 @@ void fileNameChanged(); void enableSave(); void disableSave(); + bool checkPageRangeStringValidity(QString pagerangestringtocheck,int sourcePageCount); protected: // Widgets |
|
Now the test do not get triggered in case "Export all pages" is checked. |
|
Thanks for the fix vajra. Note to whom it might concern : String analysis code is adapted from the parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount) function code in util.cpp - I wonder if some core parsing function could not be called instead by both of these functions. |
|
I think parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount) function in util.cpp is core parsing function. It requires similar modifications like I made. But in that case it's behavior will need to be tested in all import and export cases. |
|
My feeling is that i's possible to change code so that - util.cpp:ParsePageString returns exactly the same returns as now (its called in various part of code) - your checking-correctness function does the same as now too, - none of them duplicates the parsing code inline - they both call a common PageStringGeneralParser function to do the parsing part That new function could probably either an array of pages numbers, when ok, or a detailed error string in case of an error. Does a core dev feel this is relevant / or irrelevant ? |
|
I've let jluc know my thoughts here.. so lets see v2 of the patch once thats communicated. |
|
Hello Vajra We have talked about your patch, and here are the outcomes of this dicussion, as i can write them down. - instead of using constants like 48 or 57 you should use more semantic code : calling a function to get ascii code of '0' and '9'. - we have discovered you do a special case for dots. We thought it might be related to accepting 3..10 pages. But I tested this morning and it doesnt seem to work. Why did you introduce that special dot case ? I think MrB liked that '..' idea quite but as for me i think its better and simpler not to introduce a new special syntax. - the util.cpp:ParsePageString and validity check function should accept and understand the sames strings. It doesnt anymore, now that you have introduced that dot case : this is a very example of why duplicating code should be avoided. So as to avoid duplicating code, here is what we thought would be best : As for now, util.cpp:ParsePageString is a procedure : it doesnt return anything as a function. 1- Include validity checks code INTO that method, 2- Change it into a boolean function that return true/false depending on the validity check result. 3- Doing so, be carefull to not change the NPages * arg that is used by other calls of this method. 4- Use the newly returned result of this function in the PDF dialog validity check. MrB gave a hint for the 2nd step : << from = QString(token.left(token.indexOf("-"))).toInt(); becomes from = QString(token.left(token.indexOf("-"))).toInt(&ok); where ok is a bool If any of those return a false, then the function should bail out and return false >> We also discussed the display error way and thought of avoiding the popup message and testing 'live' as the user types a key in the pagerange input box. I allready told you of this ability (inspired by the Style Edit rename behaviour, in case user types an allready existing style name) but I feel this is not a priority as for now. Other comment : <<good first attempt.. learning experience>> ! |
|
I've uploaded a 'jl_pagerangecheck.diff' patch that implements the required checks. It changes the function allready in util.cpp so as to use it : it now returns 2 error messages depending on the mistake, or none when everything is fine. |
|
jl_pagerangecheck_2.diff (3,668 bytes)
Index: scribus/util.cpp =================================================================== --- scribus/util.cpp (révision 18833) +++ scribus/util.cpp (copie de travail) @@ -699,25 +699,29 @@ } //CB Moved from scribus.cpp -void parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount) +const QString parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount) { - QString tmp(pages); QString token; + const QString msgMax(QObject::tr("Page number is too high : there is only %1 page(s) in the document").arg(sourcePageCount)); + const QString msgFormat(QObject::tr("Use the '...' button or select a set of page numbers.<br>For example : '1,3,5-8' will select pages 1, 3 and 5 to 8.")); + int from, to, pageNr; do { - if (tmp.indexOf(",") == -1) + if (pages.indexOf(",") == -1) { - token = tmp; - tmp = ""; + token = pages; + pages = ""; } else { - token = tmp.left(tmp.indexOf(",")); - tmp = tmp.right(tmp.length() - tmp.indexOf(",") - 1); + token = pages.left(pages.indexOf(",")); + pages = pages.right(pages.length() - pages.indexOf(",") - 1); } token = token.trimmed(); + pages = pages.trimmed(); + if (token == "*") // Import all source doc pages { for (int i = 1; i <= sourcePageCount; ++i) @@ -730,9 +734,9 @@ if ((from != 0) && (to != 0)) { if (from > sourcePageCount) - from = sourcePageCount; + return msgMax; if (to > sourcePageCount) - to = sourcePageCount; + return msgMax; if (from == to) pageNs->push_back(to); else if (from < to) @@ -746,14 +750,21 @@ pageNs->push_back(i); } } + else + return msgFormat; } else // import single source doc page { pageNr = token.toInt(); if ((pageNr > 0) && (pageNr <= sourcePageCount)) pageNs->push_back(pageNr); + else if (!pageNr) + return msgFormat; + else + return msgMax; } - } while (!tmp.isEmpty()); + } while (!pages.isEmpty()); + return pageNs->empty() ? msgFormat : ""; } void tDebug(QString message) Index: scribus/ui/pdfopts.cpp =================================================================== --- scribus/ui/pdfopts.cpp (révision 18833) +++ scribus/ui/pdfopts.cpp (copie de travail) @@ -151,6 +151,21 @@ void PDFExportDialog::DoExport() { + if(Options->AllPages->isChecked() == 0) + { // checking validity of pagerangestring + const QString pageRangeStringtoCheck=Options->PageNr->text(); + std::vector<int> pageNs; + const QString ParseError = parsePagesString(pageRangeStringtoCheck, &pageNs, m_doc->Pages->count()); + if (!ParseError.isEmpty()) //showing warning box if invalid pagerangestring + { + QMessageBox::warning(this, + CommonStrings::trWarning, + ParseError, + CommonStrings::tr_OK); + return; + } + } + bool createPath = false; QString fn = QDir::fromNativeSeparators(fileNameLineEdit->text()); // Checking if the path exists Index: scribus/util.h =================================================================== --- scribus/util.h (révision 18833) +++ scribus/util.h (copie de travail) @@ -157,7 +157,7 @@ const QString SCRIBUS_API getStringFromSequence(NumFormat type, uint position, QString asterix="*"); const QString SCRIBUS_API arabicToRoman(uint i); const QString SCRIBUS_API numberToLetterSequence(uint i); -void SCRIBUS_API parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount); +const QString SCRIBUS_API parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount); /*! \brief performance measurements. It prints given message with it current timestamp. |
|
I've uploaded new version of the patch. It should not change anymore now. Please have a look and merge when possible. |
|
Not possible to merge patch for 3 reasons: - the parsing code should be able to run without a GUI like it used to - tmp was used as a modifiable string, pages shouldnt be modified - the strings shouldnt be constant anyway as they will need to be modified by the languageChanged events |
|
Some answers and questions : -1 since the parse function is called in multiple places, these various places might potentially want to display error message too. That's why i included the error message computation into the parse function. In case the parse function doesnt compute the error message and returns a simple error code, then the message computation will have to be done in all places. We could then create a function or method for this. I will do that. -2 Why should pages variable not be modified ? BTW it was not declared as const. -3 The strings are const but not statics so their computation will lead to different results if language changes. - As for the following code change : if (from > sourcePageCount) - from = sourcePageCount; + return msgMax; it will change the behaviour of the parse function in case it was called with too big pageNumbers. That is the desired behaviour for Pages > Import. And a first look at other calling point shows that this is also the desired behaviour for them (better warn of input mistake rather than treat "too big number" as "last page number" as if it was ok). |
|
The pagerange parsing is also used in various other places that should also call the check validity function - PDF open dialog - ... |
|
comment by mrb : "we want to be able to parse page string data without the GUI.. ie, re-use the function elsewhere perhaps so it should return an error code rather than throwing up a message let code in the GUI handle the error then that can throw up a message" that is in scribus/ui folder |
|
modified title of issue to prominently indicate it is a patch |
|
Vajra, any comment or follow-up on Jluc's comment 0011818:0032394 ? Thanks |
|
Kunda : Vajra is not there anymore. I created the last version of the patch and probably should bring the strings out to some separate file so as to fit scribus policy. |
|
Jluc, thanks for the update. Hopefully the changes you make are not too time-consuming. Thanks for stepping in :) |
|
Page range check addded for 0013451 see http://bugs.scribus.net/view.php?id=13451#c36838 |
|
Jluc, did jean use your patch ? |
|
No. He used an allready existing function. Feature is not same neither : - "my" old patch checks input and triggers an error when there is an issue. - Jean's patch deletes the not existing pages off the requsted list of pages, and only triggers an error when there is no page left at all after this. |
|
jluc, do you want to talk to jean about this to sort out differences and see if the rest of your patch can be integrated ? |
|
Jean used an allready function that does much of what my patch does. Rather then my long new code, it would probably be better to tweak that existing function so it returns an error code when it receives some not valid pages, beside returning the set of corrected pages. |
|
jluc, please advise about the future of this ticket |
|
Warning or error checking is still missing - when user request can not be fullfilled as requested = when scribus has to change the input so as to create some pdf = when user inputs invalid pages Best would be when this range check is done before submiting the dialog : when input is checked each time a key is pressed, the submit button can be greyed out and inactive as long as there is an error (= as long as valid page range is different from input check range). |
|
i really don't understand why you want so many warnings. only the case where scribus cannot fulfill the request should issue a warning. if you type 1 to 99 and you have only three pages, there is no warning needed: just create a pdf with the three existing pages. i would only issue a warning if no page can be printed. please have a look to the way libreoffice is managing the printing. it looks sane to me. |
|
"if you type 1 to 99 and you have only three pages," : that's what i call "not fullfilling the request". Same as when you ask for white wine and you got red wine : better to warn before opening the bottle. |
|
ale, can you illustrate what LO does that is more 'sane' ? |
|
LO allows the max page to be above the number of pages in the doc, that makes no sense at all |
|
afaik, allowing the page number to overflow is a standard behavior in many if not most programs. if the pdf can be created: just do it. out of range errors are in my experience very rare. what is more likely is that one writes a wrong but valid range (or list of pages). so why bother with the corner cases, if we cannot catch the main issues? |
|
When using sections page offset, its very common to make such errors, and its important to be warned (related : 0012550 "Display printed page number too wherever internal page number is displayed"). For example, when writing on the 7th SLA file part of a 200 page book, pages number offset start at 120. All pages number in the layouted pages are displaed as 120, 121, 122... and it's a very likely error to use these page numbers to request some PDF, instead of using the 'internal page numbers'. It's the same for smaller offsets or errors that lead to only parts of the requested pdf. It should not be 'if the pdf can be created, do it', it should be 'when the requested pdf can be created, do it. When it's not possible to create the requested pdf, dont do it and warn'. |
|
Warning doesnt have to be a popup ; some event ONCHANGE of the pages input can test whether it leads to a valid or not empty result, and grey out inactive or re-activate the "do it" button (as has been done for the search dialog when requested values are not valid see 0013225). |
|
as said, it's much more likely that the page numbers you're entering are wrong but valid. i give up. ps.: your case about physical and logical page numbers is (as often) a real case, but in my eyes you're (as often) tunneling towards warning about it instead of looking for a solution to the issue. |
Date Modified | Username | Field | Change |
---|---|---|---|
2013-10-28 16:55 | JLuc | New Issue | |
2014-01-10 17:46 | JLuc | Note Added: 0031020 | |
2014-01-10 17:47 | JLuc | Tag Attached: easyhack | |
2014-01-22 05:57 | ale | Note Added: 0031171 | |
2014-01-22 15:28 | vajra | File Added: fix.diff | |
2014-01-22 15:42 | vajra | Note Added: 0031172 | |
2014-01-22 15:45 | vajra | Note Edited: 0031172 | |
2014-01-22 16:21 | vajra | File Deleted: fix.diff | |
2014-01-22 16:21 | vajra | File Added: fix.diff | |
2014-01-23 00:08 | JLuc | Note Added: 0031176 | |
2014-01-27 19:00 | JLuc | Note Added: 0031210 | |
2014-01-27 19:48 | vajra | File Deleted: fix.diff | |
2014-01-27 19:49 | vajra | File Added: fix.diff | |
2014-01-27 19:54 | vajra | Note Added: 0031211 | |
2014-01-27 19:55 | vajra | Note Edited: 0031211 | |
2014-01-27 20:19 | JLuc | Note Added: 0031212 | |
2014-01-29 19:54 | vajra | Note Added: 0031218 | |
2014-01-29 20:18 | JLuc | Note Added: 0031219 | |
2014-01-29 23:02 | cbradney | Note Added: 0031220 | |
2014-01-30 10:19 | JLuc | Note Added: 0031225 | |
2014-01-30 13:31 | JLuc | Note Edited: 0031225 | |
2014-02-24 00:33 | JLuc | File Added: jl_pagerangecheck.diff | |
2014-02-24 00:38 | JLuc | Note Added: 0031378 | |
2014-02-24 14:15 | JLuc | File Deleted: jl_pagerangecheck.diff | |
2014-02-24 14:15 | JLuc | File Added: jl_pagerangecheck_2.diff | |
2014-02-24 14:18 | JLuc | Note Added: 0031379 | |
2014-02-25 21:38 | cbradney | Note Added: 0031400 | |
2014-02-26 10:17 | JLuc | Note Added: 0031406 | |
2014-02-26 10:18 | JLuc | Note Edited: 0031406 | |
2014-02-28 08:56 | JLuc | Note Edited: 0031406 | |
2014-03-11 08:27 | JLuc | Note Added: 0031496 | |
2014-07-01 19:28 | JLuc | Note Added: 0032394 | |
2014-07-13 12:18 | Kunda | Note Added: 0032714 | |
2014-07-13 12:18 | Kunda | Status | new => feedback |
2014-07-13 12:18 | Kunda | Summary | No page range check in PDF export dialog => [PATCH] No page range check in PDF export dialog |
2014-08-31 04:46 | Kunda | Note Added: 0033386 | |
2014-08-31 04:52 | Kunda | Note Edited: 0033386 | |
2014-09-01 22:25 | JLuc | Note Added: 0033446 | |
2014-09-01 22:25 | JLuc | Status | feedback => new |
2014-09-02 12:30 | Kunda | Note Added: 0033456 | |
2014-10-15 17:07 | Kunda | Tag Renamed | easyhack => #easyhack |
2014-10-24 22:57 | Kunda | Patch | => Yes |
2015-10-22 15:59 | JLuc | Relationship added | related to 0013451 |
2015-10-22 17:55 | JLuc | Note Added: 0036839 | |
2015-10-22 18:05 | Kunda | Note Added: 0036840 | |
2015-10-22 19:08 | JLuc | Note Added: 0036844 | |
2015-10-25 13:08 | Kunda | Note Added: 0036911 | |
2015-10-25 13:33 | JLuc | Note Added: 0036912 | |
2015-11-27 14:14 | Kunda | Note Added: 0037701 | |
2015-11-30 08:05 | JLuc | Note Added: 0037735 | |
2015-11-30 15:29 | ale | Note Added: 0037740 | |
2015-11-30 19:53 | JLuc | Note Added: 0037743 | |
2015-11-30 21:20 | Kunda | Note Added: 0037751 | |
2015-11-30 22:25 | cbradney | Note Added: 0037756 | |
2015-12-01 12:12 | ale | Note Added: 0037772 | |
2015-12-02 09:41 | JLuc | Note Added: 0037783 | |
2015-12-02 09:45 | JLuc | Note Added: 0037784 | |
2015-12-02 09:46 | JLuc | Relationship added | related to 0013225 |
2015-12-02 09:47 | JLuc | Relationship added | related to 0012550 |
2015-12-02 09:51 | JLuc | Note Edited: 0037783 | |
2015-12-04 10:33 | ale | Note Added: 0037814 |