CUPS: Enable printing arbitrary pages and page ranges

Task-number: QTBUG-1311
Change-Id: I8e09def0e0d8c1404d3ee86845d98a30c23b6485
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
bb10
Albert Astals Cid 2017-12-28 11:22:32 +01:00
parent bf59032d70
commit 608301d4c8
4 changed files with 188 additions and 14 deletions

View File

@ -493,6 +493,9 @@ void QPrintDialogPrivate::init()
options.pageSetCombo->addItem(tr("All Pages"), QVariant::fromValue(QCUPSSupport::AllPages));
options.pageSetCombo->addItem(tr("Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages));
options.pageSetCombo->addItem(tr("Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages));
#else
for (int i = options.pagesLayout->count() - 1; i >= 0; --i)
delete options.pagesLayout->itemAt(i)->widget();
#endif
top->d->setOptionsPane(this);
@ -565,6 +568,87 @@ void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputForma
options.pageSetCombo->setEnabled(true);
}
#if QT_CONFIG(cups)
static std::vector<std::pair<int, int>> pageRangesFromString(const QString &pagesString) Q_DECL_NOTHROW
{
std::vector<std::pair<int, int>> result;
const QStringList items = pagesString.split(',');
for (const QString item : items) {
if (item.isEmpty())
return {};
if (item.contains(QLatin1Char('-'))) {
const QStringList rangeItems = item.split('-');
if (rangeItems.count() != 2)
return {};
bool ok;
const int number1 = rangeItems[0].toInt(&ok);
if (!ok)
return {};
const int number2 = rangeItems[1].toInt(&ok);
if (!ok)
return {};
if (number1 < 1 || number2 < 1 || number2 < number1)
return {};
result.push_back(std::make_pair(number1, number2));
} else {
bool ok;
const int number = item.toInt(&ok);
if (!ok)
return {};
if (number < 1)
return {};
result.push_back(std::make_pair(number, number));
}
}
// check no range intersects with the next
std::sort(result.begin(), result.end(), [](auto it1, auto it2) { return it1.first < it2.first; });
int previousSecond = -1;
for (auto pair : result) {
if (pair.first <= previousSecond)
return {};
previousSecond = pair.second;
}
return result;
}
static QString stringFromPageRanges(const std::vector<std::pair<int, int>> &pageRanges) Q_DECL_NOTHROW
{
QString result;
for (auto pair : pageRanges) {
if (!result.isEmpty())
result += QLatin1Char(',');
if (pair.first == pair.second)
result += QString::number(pair.first);
else
result += QStringLiteral("%1-%2").arg(pair.first).arg(pair.second);
}
return result;
}
static bool isValidPagesString(const QString &pagesString) Q_DECL_NOTHROW
{
if (pagesString.isEmpty())
return false;
auto pagesRanges = pageRangesFromString(pagesString);
return !pagesRanges.empty();
}
#endif
void QPrintDialogPrivate::setupPrinter()
{
// First setup the requested OutputFormat, Printer and Page Size first
@ -609,6 +693,16 @@ void QPrintDialogPrivate::setupPrinter()
}
#if QT_CONFIG(cups)
if (options.pagesRadioButton->isChecked()) {
auto pageRanges = pageRangesFromString(options.pagesLineEdit->text());
p->setPrintRange(QPrinter::AllPages);
p->setFromTo(0, 0);
// server-side page filtering
QCUPSSupport::setPageRange(p, stringFromPageRanges(pageRanges));
}
// page set
if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {
//If the application is selecting pages and the first page number is even then need to adjust the odd-even accordingly
@ -805,6 +899,16 @@ int QPrintDialog::exec()
void QPrintDialog::accept()
{
Q_D(QPrintDialog);
#if QT_CONFIG(cups)
if (d->options.pagesRadioButton->isChecked() && !isValidPagesString(d->options.pagesLineEdit->text())) {
QMessageBox::critical(this, tr("Invalid pages definition"),
tr("%1 does not follow the correct syntax. Please use ',' to separate "
"ranges and pages, '-' to define ranges and make sure ranges do "
"not intersect with each other.").arg(d->options.pagesLineEdit->text()),
QMessageBox::Ok, QMessageBox::Ok);
return;
}
#endif
d->setupPrinter();
QDialog::accept();
}

View File

@ -6,15 +6,24 @@
<rect>
<x>0</x>
<y>0</y>
<width>426</width>
<height>187</height>
<width>432</width>
<height>251</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -42,7 +51,16 @@
<property name="spacing">
<number>4</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
@ -60,7 +78,16 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -118,6 +145,27 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="pagesLayout">
<item>
<widget class="QRadioButton" name="pagesRadioButton">
<property name="text">
<string>Pages</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="pagesLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Specify pages or ranges separated by commas. Ranges are specified by two numbers separated by a hyphen. E.g: 3,5-7,9 prints pages 3, 5, 6, 7 and 9.</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="printCurrentPage">
<property name="text">
@ -361,12 +409,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>76</x>
<y>59</y>
<x>89</x>
<y>113</y>
</hint>
<hint type="destinationlabel">
<x>122</x>
<y>57</y>
<x>182</x>
<y>113</y>
</hint>
</hints>
</connection>
@ -377,12 +425,28 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>69</x>
<y>67</y>
<x>82</x>
<y>113</y>
</hint>
<hint type="destinationlabel">
<x>215</x>
<y>67</y>
<x>267</x>
<y>113</y>
</hint>
</hints>
</connection>
<connection>
<sender>pagesRadioButton</sender>
<signal>toggled(bool)</signal>
<receiver>pagesLineEdit</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>58</x>
<y>132</y>
</hint>
<hint type="destinationlabel">
<x>163</x>
<y>128</y>
</hint>
</hints>
</connection>

View File

@ -253,9 +253,14 @@ void QCUPSSupport::setPagesPerSheetLayout(QPrinter *printer, const PagesPerShee
}
void QCUPSSupport::setPageRange(QPrinter *printer, int pageFrom, int pageTo)
{
setPageRange(printer, QStringLiteral("%1-%2").arg(pageFrom).arg(pageTo));
}
void QCUPSSupport::setPageRange(QPrinter *printer, const QString &pageRange)
{
QStringList cupsOptions = cupsOptionsList(printer);
setCupsOption(cupsOptions, QStringLiteral("page-ranges"), QStringLiteral("%1-%2").arg(pageFrom).arg(pageTo));
setCupsOption(cupsOptions, QStringLiteral("page-ranges"), pageRange);
setCupsOptions(printer, cupsOptions);
}

View File

@ -142,6 +142,7 @@ public:
static void setPagesPerSheetLayout(QPrinter *printer, const PagesPerSheet pagesPerSheet,
const PagesPerSheetLayout pagesPerSheetLayout);
static void setPageRange(QPrinter *printer, int pageFrom, int pageTo);
static void setPageRange(QPrinter *printer, const QString &pageRange);
struct JobSheets
{