kprintpreview.cpp

00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
00004  *
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License version 2 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Library General Public License
00016  *  along with this library; see the file COPYING.LIB.  If not, write to
00017  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  *  Boston, MA 02110-1301, USA.
00019  **/
00020 
00021 #include "kprintpreview.h"
00022 #include "kmfactory.h"
00023 
00024 #include <qfile.h>
00025 #include <qlayout.h>
00026 #include <qvbox.h>
00027 
00028 #include <kparts/part.h>
00029 #include <kaccel.h>
00030 #include <kaction.h>
00031 #include <klibloader.h>
00032 #include <ktrader.h>
00033 #include <kuserprofile.h>
00034 #include <krun.h>
00035 #include <kapplication.h>
00036 #include <kstandarddirs.h>
00037 #include <klocale.h>
00038 #include <kmessagebox.h>
00039 #include <kdebug.h>
00040 #include <kconfig.h>
00041 #include <ktoolbar.h>
00042 #include <kmimetype.h>
00043 
00044 KPreviewProc::KPreviewProc()
00045 : KProcess()
00046 {
00047     m_bOk = false;
00048     connect(this, SIGNAL(processExited(KProcess*)), SLOT(slotProcessExited(KProcess*)));
00049 }
00050 
00051 KPreviewProc::~KPreviewProc()
00052 {
00053 }
00054 
00055 bool KPreviewProc::startPreview()
00056 {
00057     if (start())
00058     {
00059         kapp->enter_loop();
00060         return m_bOk;
00061     }
00062     else
00063         return false;
00064 }
00065 
00066 void KPreviewProc::slotProcessExited(KProcess* proc)
00067 {
00068     kapp->exit_loop();
00069     if ( proc->normalExit() && proc->exitStatus() == 0 )
00070         m_bOk = true;
00071     else
00072         kdDebug(500) << "KPreviewProc::slotProcessExited: normalExit=" << proc->normalExit()
00073             << " exitStatus=" << proc->exitStatus() << endl;
00074 }
00075 
00076 //*******************************************************************************************
00077 
00078 class KPrintPreview::KPrintPreviewPrivate
00079 {
00080 public:
00081     KPrintPreviewPrivate(KPrintPreview *dlg) : gvpart_(0)
00082     {
00083         mainwidget_ = new QWidget(dlg, "MainWidget");
00084         toolbar_ = new KToolBar(mainwidget_, "PreviewToolBar", true);
00085         actions_ = new KActionCollection(dlg);
00086         accel_ = new KAccel(dlg);
00087         previewonly_ = false;
00088     }
00089     ~KPrintPreviewPrivate()
00090     {
00091         if (gvpart_) delete gvpart_;
00092     }
00093     void plugAction(KAction *act)
00094     {
00095         act->plug(toolbar_);
00096         act->plugAccel(accel_);
00097     }
00098 
00099     KParts::ReadOnlyPart    *gvpart_;
00100     KToolBar        *toolbar_;
00101     KActionCollection   *actions_;
00102     QWidget         *mainwidget_;
00103     KAccel          *accel_;
00104     bool            previewonly_;
00105 };
00106 
00107 static KLibFactory* componentFactory()
00108 {
00109     kdDebug(500) << "kdeprint: querying trader for 'application/postscript' service" << endl;
00110     KLibFactory *factory(0);
00111     factory = KLibLoader::self()->factory("libkghostviewpart");
00112         if( factory )
00113             return factory;
00114     KTrader::OfferList  offers = KTrader::self()->query(QString::fromLatin1("application/postscript"), QString::fromLatin1("KParts/ReadOnlyPart"), QString::null, QString::null);
00115     for (KTrader::OfferList::ConstIterator it = offers.begin(); it != offers.end(); ++it)
00116     {
00117         KService::Ptr   service = *it;
00118         factory = KLibLoader::self()->factory(QFile::encodeName(service->library()));
00119         if (factory)
00120             break;
00121     }
00122     if (!factory)
00123     {
00124         // nothing has been found, try to load directly the KGhostview part
00125         factory = KLibLoader::self()->factory("libkghostviewpart");
00126     }
00127     return factory;
00128 }
00129 
00130 static bool continuePrint(const QString& msg_, QWidget *parent, bool previewOnly)
00131 {
00132     QString msg(msg_);
00133     if (previewOnly)
00134     {
00135         KMessageBox::error(parent, msg);
00136         return false;
00137     }
00138     else
00139     {
00140         msg.append(" ").append(i18n("Do you want to continue printing anyway?"));
00141         return (KMessageBox::warningContinueCancel(parent, msg, QString::null, KGuiItem(i18n("Print"),"fileprint")) == KMessageBox::Continue);
00142     }
00143 }
00144 
00145 //*******************************************************************************************
00146 
00147 KPrintPreview::KPrintPreview(QWidget *parent, bool previewOnly)
00148 : KDialogBase(parent, "PreviewDlg", true, i18n("Print Preview"), 0)
00149 {
00150     kdDebug(500) << "kdeprint: creating preview dialog" << endl;
00151     d = new KPrintPreviewPrivate(this);
00152     d->previewonly_ = previewOnly;
00153 
00154     // create main view and actions
00155     setMainWidget(d->mainwidget_);
00156     if (previewOnly)
00157         KStdAction::close(this, SLOT(reject()), d->actions_, "close_print");
00158     else
00159     {
00160         new KAction(i18n("Print"), "fileprint", Qt::Key_Return, this, SLOT(accept()), d->actions_, "continue_print");
00161         new KAction(i18n("Cancel"), "stop", Qt::Key_Escape, this, SLOT(reject()), d->actions_, "stop_print");
00162     }
00163 
00164 }
00165 
00166 KPrintPreview::~KPrintPreview()
00167 {
00168     delete d;
00169 }
00170 
00171 void KPrintPreview::initView(KLibFactory *factory)
00172 {
00173     // load the component
00174     d->gvpart_ = (KParts::ReadOnlyPart*)factory->create(d->mainwidget_, "gvpart", "KParts::ReadOnlyPart");
00175 
00176     // populate the toolbar
00177     if (d->previewonly_)
00178         d->plugAction(d->actions_->action("close_print"));
00179     else
00180     {
00181         d->plugAction(d->actions_->action("continue_print"));
00182         d->plugAction(d->actions_->action("stop_print"));
00183     }
00184     if (d->gvpart_)
00185     {
00186         QDomNodeList l = d->gvpart_->domDocument().elementsByTagName( "ToolBar" );
00187         if ( l.length() > 0 )
00188         {
00189             d->toolbar_->insertLineSeparator();
00190             QDomNodeList acts = l.item( 0 ).toElement().elementsByTagName( "Action" );
00191             for ( uint i=0; i<acts.length(); i++ )
00192             {
00193                 QDomElement a = acts.item( i ).toElement();
00194                 if ( a.attribute( "name" ) == "goToPage" )
00195                     continue;
00196                 KAction *act = d->gvpart_->action( a );
00197                 if ( act != 0 )
00198                     d->plugAction( act );
00199             }
00200         }
00201         /*
00202         KAction *act;
00203         d->toolbar_->insertLineSeparator();
00204         if ((act = d->gvpart_->action("zoomIn")) != 0)
00205             d->plugAction(act);
00206         if ((act = d->gvpart_->action("zoomOut")) != 0)
00207             d->plugAction(act);
00208         d->toolbar_->insertSeparator();
00209         if ((act = d->gvpart_->action("prevPage")) != 0)
00210             d->plugAction(act);
00211         if ((act = d->gvpart_->action("nextPage")) != 0)
00212             d->plugAction(act);
00213             */
00214     }
00215     d->toolbar_->setIconText(KToolBar::IconTextRight);
00216     d->toolbar_->setBarPos(KToolBar::Top);
00217     d->toolbar_->setMovingEnabled(false);
00218     //d->adjustSize();
00219 
00220     // construct the layout
00221     QVBoxLayout *l0 = new QVBoxLayout(d->mainwidget_, 0, 0);
00222     l0->addWidget(d->toolbar_, AlignTop);
00223     if (d->gvpart_)
00224         l0->addWidget(d->gvpart_->widget());
00225 
00226     resize(855, 500);
00227     setCaption(i18n("Print Preview"));
00228 }
00229 
00230 void KPrintPreview::openFile(const QString& file)
00231 {
00232     d->gvpart_->openURL(KURL(file));
00233 }
00234 
00235 bool KPrintPreview::isValid() const
00236 {
00237     return (d->gvpart_ != 0);
00238 }
00239 
00240 bool KPrintPreview::preview(const QString& file, bool previewOnly, WId parentId)
00241 {
00242     KMimeType::Ptr mime = KMimeType::findByPath( file );
00243     bool isPS = ( mime->name() == "application/postscript" );
00244     if ( !isPS )
00245         kdDebug( 500 ) << "Previewing a non PostScript file, built-in preview disabled" << endl;
00246 
00247     KConfig *conf = KMFactory::self()->printConfig();
00248     conf->setGroup("General");
00249     KLibFactory *factory(0);
00250     bool    externalPreview = conf->readBoolEntry("ExternalPreview", false);
00251     QWidget *parentW = QWidget::find(parentId);
00252     QString exe;
00253     if (!externalPreview && isPS && (factory = componentFactory()) != 0)
00254     {
00255         KPrintPreview   dlg(parentW, previewOnly);
00256         dlg.initView(factory);
00257 
00258         if (dlg.isValid())
00259         {
00260             dlg.openFile(file);
00261             return dlg.exec();
00262         }
00263         else 
00264         {
00265             // do nothing at that point: try to use the other way around by
00266             // using an external PS viewer if possible
00267         }
00268     }
00269 
00270     // Either the PS viewer component was not found, or an external
00271     // preview program has been specified
00272     KPreviewProc    proc;
00273     if (externalPreview && isPS )
00274     {
00275         exe = conf->readPathEntry("PreviewCommand", "gv");
00276         if (KStandardDirs::findExe(exe).isEmpty())
00277         {
00278             QString msg = i18n("The preview program %1 cannot be found. "
00279                                "Check that the program is correctly installed and "
00280                                "located in a directory included in your PATH "
00281                                "environment variable.").arg(exe);
00282             return continuePrint(msg, parentW, previewOnly);
00283         }
00284         proc << exe << file;
00285     }
00286     else
00287     {
00288         KService::Ptr serv = KServiceTypeProfile::preferredService( mime->name(), QString::null );
00289         if ( serv )
00290         {
00291             KURL url;
00292             url.setPath( file );
00293             QStringList args = KRun::processDesktopExec( *serv, url, false );
00294             proc << args;
00295             exe = serv->name();
00296         }
00297         else
00298         {
00299             // in that case, the PS viewer component could not be loaded and no service
00300             // could be found to view PS
00301             QString msg;
00302             if ( isPS )
00303                 msg = i18n("Preview failed: neither the internal KDE PostScript "
00304                            "viewer (KGhostView) nor any other external PostScript "
00305                            "viewer could be found.");
00306             else
00307                 msg = i18n( "Preview failed: KDE could not find any application "
00308                             "to preview files of type %1." ).arg( mime->name() );
00309 
00310             return continuePrint(msg, parentW, previewOnly);
00311         }
00312     }
00313 
00314     // start the preview process
00315     if (!proc.startPreview())
00316     {
00317         QString msg = i18n("Preview failed: unable to start program %1.").arg(exe);
00318         return continuePrint(msg, parentW, previewOnly);
00319     }
00320     else if (!previewOnly)
00321     {
00322         return (KMessageBox::questionYesNo(parentW, i18n("Do you want to continue printing?"), QString::null, KGuiItem(i18n("Print"),"fileprint"), KStdGuiItem::cancel(), "continuePrinting") == KMessageBox::Yes);
00323     }
00324     else
00325         return false;
00326 }
00327 
00328 #include "kprintpreview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys