okular/kdvi_multipage.cpp
Stefan Kebekus f40611db01 properly use ReadWritePart now
svn path=/trunk/KDE/kdegraphics/kviewshell/plugins/dvi/; revision=492081
2005-12-28 18:18:52 +00:00

445 lines
13 KiB
C++

// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; c-brace-offset: 0; -*-
#include <config.h>
#include "kdvi_multipage.h"
#include "dviFile.h"
#include "dviPageCache.h"
#include "dviWidget.h"
#include "kprinterwrapper.h"
#include "kvs_debug.h"
#include "optionDialogFontsWidget.h"
#include "optionDialogSpecialWidget.h"
#include "performanceMeasurement.h"
#include "prefs.h"
#include <kaboutdata.h>
#include <kaction.h>
#include <kconfigdialog.h>
#include <kfiledialog.h>
#include <kglobal.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kparts/genericfactory.h>
#include <kstdaction.h>
#include <ktip.h>
#include <QLabel>
#include <QTemporaryFile>
#include <QTimer>
//#define KDVI_MULTIPAGE_DEBUG
#ifdef PERFORMANCE_MEASUREMENT
// These objects are explained in the file "performanceMeasurement.h"
QTime performanceTimer;
int performanceFlag = 0;
#endif
typedef KParts::GenericFactory<KDVIMultiPage> KDVIMultiPageFactory;
K_EXPORT_COMPONENT_FACTORY(kdvipart, KDVIMultiPageFactory)
KDVIMultiPage::KDVIMultiPage(QWidget *parentWidget, const char *widgetName, QObject *parent,
const char *name, const QStringList& args)
: KMultiPage(parentWidget, widgetName, parent, name), DVIRenderer(parentWidget)
{
Q_UNUSED(args);
#ifdef PERFORMANCE_MEASUREMENT
performanceTimer.start();
#endif
searchUsed = false;
setInstance(KDVIMultiPageFactory::instance());
// Points to the same object as renderer to avoid downcasting.
// FIXME: Remove when the API of the Renderer-class is finished.
DVIRenderer.setName("DVI renderer");
setRenderer(&DVIRenderer);
docInfoAction = new KAction(i18n("Document &Info"), "info", 0, &DVIRenderer, SLOT(showInfo()), actionCollection(), "info_dvi");
embedPSAction = new KAction(i18n("Embed External PostScript Files..."), 0, this, SLOT(slotEmbedPostScript()), actionCollection(), "embed_postscript");
new KAction(i18n("Enable All Warnings && Messages"), 0, this, SLOT(doEnableWarnings()), actionCollection(), "enable_msgs");
exportPSAction = new KAction(i18n("PostScript..."), 0, &DVIRenderer, SLOT(exportPS()), actionCollection(), "export_postscript");
exportPDFAction = new KAction(i18n("PDF..."), 0, &DVIRenderer, SLOT(exportPDF()), actionCollection(), "export_pdf");
KStdAction::tipOfDay(this, SLOT(showTip()), actionCollection(), "help_tipofday");
setXMLFile("kdvi_part.rc");
preferencesChanged();
enableActions(false);
// Show tip of the day, when the first main window is shown.
QTimer::singleShot(0,this,SLOT(showTipOnStart()));
}
KDVIMultiPage::~KDVIMultiPage()
{
delete docInfoAction;
delete embedPSAction;
delete exportPSAction;
delete exportPDFAction;
Prefs::writeConfig();
}
KAboutData* KDVIMultiPage::createAboutData()
{
KAboutData* about = new KAboutData("kdvi", I18N_NOOP("KDVI"), "1.3",
I18N_NOOP("A previewer for Device Independent files (DVI files) produced by the TeX typesetting system."),
KAboutData::License_GPL,
"Markku Hinhala, Stephan Kebekus",
I18N_NOOP("This program displays Device Independent (DVI) files which are produced by the TeX typesetting system.\n"
"KDVI 1.3 is based on original code from KDVI version 0.43 and xdvik."));
about->addAuthor ("Stefan Kebekus",
I18N_NOOP("Current Maintainer."),
"kebekus@kde.org",
"http://www.mi.uni-koeln.de/~kebekus");
about->addAuthor ("Markku Hinhala", I18N_NOOP("Author of kdvi 0.4.3"));
about->addAuthor ("Nicolai Langfeldt", I18N_NOOP("Maintainer of xdvik"));
about->addAuthor ("Paul Vojta", I18N_NOOP("Author of xdvi"));
about->addCredit ("Philipp Lehmann", I18N_NOOP("Testing and bug reporting."));
about->addCredit ("Wilfried Huss", I18N_NOOP("Re-organisation of source code."));
return about;
}
void KDVIMultiPage::slotEmbedPostScript()
{
DVIRenderer.embedPostScript();
if (DVIRenderer.isModified())
emit(documentIsModified());
setEmbedPostScriptAction();
}
void KDVIMultiPage::setEmbedPostScriptAction()
{
if ((DVIRenderer.dviFile == 0) || (DVIRenderer.dviFile->numberOfExternalPSFiles == 0))
embedPSAction->setEnabled(false);
else
embedPSAction->setEnabled(true);
}
bool KDVIMultiPage::slotSave(const QString &fileName)
{
// Paranoid safety checks
if (DVIRenderer.dviFile == 0)
return false;
if (DVIRenderer.dviFile->dvi_Data() == 0)
return false;
if (fileName.isEmpty())
return false;
bool r = DVIRenderer.dviFile->saveAs(fileName);
if (r == false)
KMessageBox::error(parentWdg, i18n("<qt>Error saving the document to the file <strong>%1</strong>. The document is <strong>not</strong> saved.</qt>").arg(fileName),
i18n("Error saving document"));
return r;
}
void KDVIMultiPage::setFile(bool r)
{
enableActions(r);
}
QStringList KDVIMultiPage::fileFormats() const
{
QStringList r;
r << i18n("*.dvi *.DVI|TeX Device Independent Files (*.dvi)");
return r;
}
void KDVIMultiPage::addConfigDialogs(KConfigDialog* configDialog)
{
static optionDialogFontsWidget* fontConfigWidget = 0;
fontConfigWidget = new optionDialogFontsWidget(pageView());
optionDialogSpecialWidget* specialConfigWidget = new optionDialogSpecialWidget(pageView());
configDialog->addPage(fontConfigWidget, Prefs::self(), i18n("TeX Fonts"), "fonts");
configDialog->addPage(specialConfigWidget, Prefs::self(), i18n("DVI Specials"), "dvi");
configDialog->setHelp("preferences", "kdvi");
}
void KDVIMultiPage::preferencesChanged()
{
// Call method from parent class
KMultiPage::preferencesChanged();
#ifdef KDVI_MULTIPAGE_DEBUG
kdDebug(kvs::dvi) << "preferencesChanged" << endl;
#endif
bool showPS = Prefs::showPS();
bool useFontHints = Prefs::useFontHints();
DVIRenderer.setPrefs( showPS, Prefs::editorCommand(), useFontHints);
}
void KDVIMultiPage::print()
{
// Obtain a fully initialized KPrinter structure, and disable all
// entries in the "Page Size & Placement" tab of the printer dialog.
KPrinter *printer = getPrinter(false);
// Abort with an error message if no KPrinter could be initialized
if (printer == 0) {
kdError(kvs::dvi) << "KPrinter not available" << endl;
return;
}
// Show the printer options dialog. Return immediately if the user
// aborts.
if (!printer->setup(parentWdg, i18n("Print %1").arg(m_file.section('/', -1)) ))
return;
// This funny method call is necessary for the KPrinter to return
// proper results in printer->orientation() below. It seems that
// KPrinter does some options parsing in that method.
((KDVIPrinterWrapper *)printer)->doPreparePrinting();
if (printer->pageList().isEmpty()) {
KMessageBox::error( pageView(),
i18n("The list of pages you selected was empty.\n"
"Maybe you made an error in selecting the pages, "
"e.g. by giving an invalid range like '7-2'.") );
return;
}
// Turn the results of the options requestor into a list arguments
// which are used by dvips.
QString dvips_options = QString::null;
// Print in reverse order.
if ( printer->pageOrder() == KPrinter::LastPageFirst )
dvips_options += "-r ";
// Print only odd pages.
if ( printer->pageSet() == KPrinter::OddPages )
dvips_options += "-A ";
// Print only even pages.
if ( printer->pageSet() == KPrinter::EvenPages )
dvips_options += "-B ";
// We use the printer->pageSize() method to find the printer page
// size, and pass that information on to dvips. Unfortunately, dvips
// does not understand all of these; what exactly dvips understands,
// depends on its configuration files. Consequence: expect problems
// with unusual paper sizes.
switch( printer->pageSize() ) {
case KPrinter::A4:
dvips_options += "-t a4 ";
break;
case KPrinter::B5:
dvips_options += "-t b5 ";
break;
case KPrinter::Letter:
dvips_options += "-t letter ";
break;
case KPrinter::Legal:
dvips_options += "-t legal ";
break;
case KPrinter::Executive:
dvips_options += "-t executive ";
break;
case KPrinter::A0:
dvips_options += "-t a0 ";
break;
case KPrinter::A1:
dvips_options += "-t a1 ";
break;
case KPrinter::A2:
dvips_options += "-t a2 ";
break;
case KPrinter::A3:
dvips_options += "-t a3 ";
break;
case KPrinter::A5:
dvips_options += "-t a5 ";
break;
case KPrinter::A6:
dvips_options += "-t a6 ";
break;
case KPrinter::A7:
dvips_options += "-t a7 ";
break;
case KPrinter::A8:
dvips_options += "-t a8 ";
break;
case KPrinter::A9:
dvips_options += "-t a9 ";
break;
case KPrinter::B0:
dvips_options += "-t b0 ";
break;
case KPrinter::B1:
dvips_options += "-t b1 ";
break;
case KPrinter::B10:
dvips_options += "-t b10 ";
break;
case KPrinter::B2:
dvips_options += "-t b2 ";
break;
case KPrinter::B3:
dvips_options += "-t b3 ";
break;
case KPrinter::B4:
dvips_options += "-t b4 ";
break;
case KPrinter::B6:
dvips_options += "-t b6 ";
break;
case KPrinter::B7:
dvips_options += "-t b7 ";
break;
case KPrinter::B8:
dvips_options += "-t b8 ";
break;
case KPrinter::B9:
dvips_options += "-t b9 ";
break;
case KPrinter::C5E:
dvips_options += "-t c5e ";
break;
case KPrinter::Comm10E:
dvips_options += "-t comm10e ";
break;
case KPrinter::DLE:
dvips_options += "-t dle ";
break;
case KPrinter::Folio:
dvips_options += "-t folio ";
break;
case KPrinter::Ledger:
dvips_options += "-t ledger ";
break;
case KPrinter::Tabloid:
dvips_options += "-t tabloid ";
break;
default:
break;
}
// Orientation
if ( printer->orientation() == KPrinter::Landscape )
dvips_options += "-t landscape ";
// List of pages to print.
QList<int> pageList = printer->pageList();
dvips_options += "-pp ";
int commaflag = 0;
for( QList<int>::ConstIterator it = pageList.begin(); it != pageList.end(); ++it ) {
if (commaflag == 1)
dvips_options += QString(",");
else
commaflag = 1;
dvips_options += QString("%1").arg(*it);
}
// Now print. For that, export the DVI-File to PostScript. Note that
// dvips will run concurrently to keep the GUI responsive, keep log
// of dvips and allow abort. Giving a non-zero printer argument
// means that the dvi-widget will print the file when dvips
// terminates, and then delete the output file.
QTemporaryFile tf;
// Must open the QTemporaryFile to access the file name.
tf.setAutoRemove(false);
tf.open();
DVIRenderer.exportPS(tf.fileName(), dvips_options, printer);
// "True" may be a bit euphemistic. However, since dvips runs
// concurrently, there is no way of telling the result of the
// printing command at this stage.
return;
}
void KDVIMultiPage::enableActions(bool b)
{
KMultiPage::enableActions(b);
docInfoAction->setEnabled(b);
exportPSAction->setEnabled(b);
exportPDFAction->setEnabled(b);
setEmbedPostScriptAction();
}
void KDVIMultiPage::doEnableWarnings()
{
KMessageBox::information (pageView(), i18n("All messages and warnings will now be shown."));
KMessageBox::enableAllMessages();
KTipDialog::setShowOnStart(true);
}
void KDVIMultiPage::showTip()
{
KTipDialog::showTip(pageView(), "kdvi/tips", true);
}
void KDVIMultiPage::showTipOnStart()
{
KTipDialog::showTip(pageView(), "kdvi/tips");
}
DocumentWidget* KDVIMultiPage::createDocumentWidget()
{
DVIWidget* documentWidget = new DVIWidget(pageView(), pageCache, "singlePageWidget");
// Handle source links
connect(documentWidget, SIGNAL(SRCLink(const QString&, const QPoint&, DocumentWidget*)), getRenderer(),
SLOT(handleSRCLink(const QString& , const QPoint&, DocumentWidget*)));
return documentWidget;
}
void KDVIMultiPage::initializePageCache()
{
pageCache = new DVIPageCache();
}
void KDVIMultiPage::showFindTextDialog()
{
if ((getRenderer().isNull()) || (getRenderer()->supportsTextSearch() == false))
return;
if (!searchUsed)
{
// WARNING: This text appears several times in the code. Change
// everywhere, or nowhere!
if (KMessageBox::warningContinueCancel( pageView(),
i18n("<qt>This function searches the DVI file for plain text. Unfortunately, this version of "
"KDVI treats only plain ASCII characters properly. Symbols, ligatures, mathematical "
"formulae, accented characters, and non-English text, such as Russian or Korean, will "
"most likely be messed up completely. Continue anyway?</qt>"),
i18n("Function May Not Work as Expected"),
KStdGuiItem::cont(),
"warning_search_text_may_not_work") == KMessageBox::Cancel)
return;
// Remember that we don't need to show the warning message again.
searchUsed = true;
}
// Now really show the search widget
KMultiPage::showFindTextDialog();
}
#include "kdvi_multipage.moc"