File indexing completed on 2024-05-05 16:39:05
0001 /* This file is part of the KDE project 0002 Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public 0006 License as published by the Free Software Foundation, version 2. 0007 0008 This program is distributed in the hope that it will be useful, 0009 but WITHOUT ANY WARRANTY; without even the implied warranty of 0010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0011 General Public License for more details. 0012 0013 You should have received a copy of the GNU General Public License 0014 along with this program; see the file COPYING. If not, write to 0015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0016 Boston, MA 02110-1301, USA. 0017 */ 0018 0019 #include "printing.h" 0020 #include <ui_printing_page.h> 0021 0022 #include <KLocalizedString> 0023 0024 #include <QFont> 0025 #include <QFontDatabase> 0026 #include <QFontMetrics> 0027 #include <QImage> 0028 #include <QPainter> 0029 #include <QPrintDialog> 0030 #include <QPrinter> 0031 #include <QScopedPointer> 0032 #include <QTemporaryFile> 0033 #include <QUrl> 0034 0035 #include "filecache.h" 0036 #include "imagewindow.h" 0037 #include "kuickshow_debug.h" 0038 #include "version.h" 0039 0040 0041 bool Printing::printImage( ImageWindow& imageWin, QWidget *parent ) 0042 { 0043 QString imageURL = imageWin.url().toDisplayString(); 0044 QPrinter printer; 0045 printer.setDocName( imageURL ); 0046 printer.setCreator( "KuickShow-" KUICKSHOWVERSION ); 0047 0048 KuickPrintDialogPage* dialogPage = new KuickPrintDialogPage( parent ); 0049 dialogPage->setObjectName(QString::fromLatin1("kuick page")); 0050 QPrintDialog *printDialog = new QPrintDialog(&printer, parent); 0051 printDialog->setOptionTabs(QList<QWidget*>() << dialogPage); 0052 printDialog->setWindowTitle(i18n("Print %1", printer.docName().section('/', -1))); 0053 0054 if (printDialog->exec()) 0055 { 0056 QScopedPointer<QTemporaryFile> tmpFilePtr(FileCache::self()->createTempFile(QStringLiteral(".png"))); 0057 if ( tmpFilePtr->open() ) 0058 { 0059 if ( imageWin.saveImage( QUrl::fromLocalFile(tmpFilePtr->fileName()), true ) ) 0060 { 0061 0062 bool success = printImageWithQt( tmpFilePtr->fileName(), printer, *dialogPage, 0063 imageURL); 0064 delete printDialog; 0065 return success; 0066 } 0067 } 0068 delete printDialog; 0069 return false; 0070 } 0071 delete printDialog; 0072 return true; // user aborted 0073 } 0074 0075 bool Printing::printImageWithQt( const QString& filename, QPrinter& printer, KuickPrintDialogPage& dialogPage, 0076 const QString& originalFileName ) 0077 { 0078 QImage image( filename ); 0079 if ( image.isNull() ) { 0080 qWarning("Can't load image: %s for printing.", qUtf8Printable(filename)); 0081 return false; 0082 } 0083 0084 QPainter p; 0085 p.begin( &printer ); 0086 0087 p.setFont( QFontDatabase::systemFont(QFontDatabase::GeneralFont) ); 0088 QFontMetrics fm = p.fontMetrics(); 0089 0090 int w = printer.width(); 0091 int h = printer.height(); 0092 0093 // Black & white print? 0094 if ( dialogPage.printBlackWhite() ) { 0095 image = image.convertToFormat( QImage::Format_Mono, Qt::MonoOnly | Qt::ThresholdDither | Qt::AvoidDither ); 0096 } 0097 0098 int filenameOffset = 0; 0099 bool printFilename = dialogPage.printFilename(); 0100 if ( printFilename ) { 0101 filenameOffset = fm.lineSpacing() + 14; 0102 h -= filenameOffset; // filename goes into one line! 0103 } 0104 0105 // 0106 // shrink image to pagesize, if necessary 0107 // 0108 bool shrinkToFit = dialogPage.printShrinkToFit(); 0109 QSize imagesize = image.size(); 0110 if ( shrinkToFit && (image.width() > w || image.height() > h) ) { 0111 imagesize.scale( w, h, Qt::KeepAspectRatio ); 0112 } 0113 0114 0115 // 0116 // align image 0117 // 0118 // not currently implemented in print options 0119 //bool ok = false; 0120 //int alignment = printer.option("app-kuickshow-alignment").toInt( &ok ); 0121 //if ( !ok ) 0122 int alignment = Qt::AlignCenter; // default 0123 0124 int x = 0; 0125 int y = 0; 0126 0127 // ### need a GUI for this in KuickPrintDialogPage! 0128 // x - alignment 0129 if ( alignment & Qt::AlignHCenter ) 0130 x = (w - imagesize.width())/2; 0131 else if ( alignment & Qt::AlignLeft ) 0132 x = 0; 0133 else if ( alignment & Qt::AlignRight ) 0134 x = w - imagesize.width(); 0135 0136 // y - alignment 0137 if ( alignment & Qt::AlignVCenter ) 0138 y = (h - imagesize.height())/2; 0139 else if ( alignment & Qt::AlignTop ) 0140 y = 0; 0141 else if ( alignment & Qt::AlignBottom ) 0142 y = h - imagesize.height(); 0143 0144 // 0145 // perform the actual drawing 0146 // 0147 p.drawImage( QRect( x, y, imagesize.width(), imagesize.height()), image ); 0148 0149 if ( printFilename ) 0150 { 0151 QString fname = minimizeString( originalFileName, fm, w ); 0152 if ( !fname.isEmpty() ) 0153 { 0154 int fw = fm.horizontalAdvance(fname); 0155 int x = (w - fw)/2; 0156 int y = printer.height() - filenameOffset/2; 0157 p.drawText( x, y, fname ); 0158 } 0159 } 0160 0161 p.end(); 0162 0163 return true; 0164 } 0165 0166 QString Printing::minimizeString( QString text, const QFontMetrics& 0167 metrics, int maxWidth ) 0168 { 0169 if ( text.length() <= 5 ) 0170 return QString(); // no sense to cut that tiny little string 0171 0172 bool changed = false; 0173 while (metrics.horizontalAdvance(text) > maxWidth) 0174 { 0175 int mid = text.length() / 2; 0176 text.remove( mid, 2 ); // remove 2 characters in the middle 0177 changed = true; 0178 } 0179 0180 if ( changed ) // add "..." in the middle 0181 { 0182 int mid = text.length() / 2; 0183 if ( mid <= 5 ) // sanity check 0184 return QString(); 0185 0186 text.replace( mid - 1, 3, "..." ); 0187 } 0188 0189 return text; 0190 } 0191 0192 0193 /////////////////////////////////////////////////////////////////// 0194 /////////////////////////////////////////////////////////////////// 0195 0196 0197 KuickPrintDialogPage::KuickPrintDialogPage( QWidget *parent ) 0198 : QWidget( parent ) 0199 { 0200 ui = new Ui::KuickPrintDialogPage; 0201 ui->setupUi(this); 0202 0203 connect( ui->scale, SIGNAL( toggled( bool )), SLOT( toggleScaling( bool ))); 0204 } 0205 0206 KuickPrintDialogPage::~KuickPrintDialogPage() 0207 { 0208 delete ui; 0209 } 0210 0211 // ### opts["app-kuickshow-alignment"] = ; 0212 0213 bool KuickPrintDialogPage::printFilename() 0214 { 0215 return ui->addFileName->isChecked(); 0216 } 0217 0218 void KuickPrintDialogPage::setPrintFilename( bool addFilename ) 0219 { 0220 ui->addFileName->setChecked( addFilename ); 0221 } 0222 0223 bool KuickPrintDialogPage::printBlackWhite() 0224 { 0225 return ui->blackwhite->isChecked(); 0226 } 0227 0228 void KuickPrintDialogPage::setPrintBlackWhite( bool blackWhite ) 0229 { 0230 ui->blackwhite->setChecked( blackWhite ); 0231 } 0232 0233 bool KuickPrintDialogPage::printShrinkToFit() 0234 { 0235 return ui->shrinkToFit->isChecked(); 0236 } 0237 0238 void KuickPrintDialogPage::setPrintShrinkToFit( bool shrinkToFit ) 0239 { 0240 toggleScaling( !shrinkToFit ); 0241 } 0242 0243 bool KuickPrintDialogPage::printScale() 0244 { 0245 return ui->scale->isChecked(); 0246 } 0247 0248 void KuickPrintDialogPage::setPrintScale( bool scale ) 0249 { 0250 toggleScaling( scale ); 0251 } 0252 0253 QString KuickPrintDialogPage::printScaleUnit() 0254 { 0255 return ui->units->currentText(); 0256 } 0257 0258 void KuickPrintDialogPage::setPrintScaleUnit( QString scaleUnit ) 0259 { 0260 for(int i = 0, count = ui->units->count(); i < count; i++) { 0261 if(ui->units->itemText(i) == scaleUnit) { 0262 ui->units->setCurrentIndex(i); 0263 return; 0264 } 0265 } 0266 0267 ui->units->setCurrentIndex(-1); 0268 } 0269 0270 int KuickPrintDialogPage::printScaleWidthPixels() 0271 { 0272 return scaleWidth(); 0273 } 0274 0275 void KuickPrintDialogPage::setPrintScaleWidthPixels( int scaleWidth ) 0276 { 0277 setScaleWidth(scaleWidth); 0278 } 0279 0280 int KuickPrintDialogPage::printScaleHeightPixels() 0281 { 0282 return scaleHeight(); 0283 } 0284 0285 void KuickPrintDialogPage::setPrintScaleHeightPixels( int scaleHeight ) 0286 { 0287 setScaleHeight(scaleHeight); 0288 } 0289 0290 void KuickPrintDialogPage::toggleScaling( bool enable ) 0291 { 0292 ui->shrinkToFit->setChecked( !enable ); 0293 ui->scale->setChecked( enable ); 0294 ui->width->setEnabled( enable ); 0295 ui->height->setEnabled( enable ); 0296 ui->units->setEnabled( enable ); 0297 } 0298 0299 int KuickPrintDialogPage::scaleWidth() const 0300 { 0301 return fromUnitToPixels( ui->width->value() ); 0302 } 0303 0304 int KuickPrintDialogPage::scaleHeight() const 0305 { 0306 return fromUnitToPixels( ui->height->value() ); 0307 } 0308 0309 void KuickPrintDialogPage::setScaleWidth( int pixels ) 0310 { 0311 ui->width->setValue( (int) pixelsToUnit( pixels ) ); 0312 } 0313 0314 void KuickPrintDialogPage::setScaleHeight( int pixels ) 0315 { 0316 ui->width->setValue( (int) pixelsToUnit( pixels ) ); 0317 } 0318 0319 int KuickPrintDialogPage::fromUnitToPixels( float /*value*/ ) const 0320 { 0321 return 1; // ### 0322 } 0323 0324 float KuickPrintDialogPage::pixelsToUnit( int /*pixels*/ ) const 0325 { 0326 return 1.0; // ### 0327 }