This modifies the Postscript printer to be able to insert a pipe in between the Postscript generation

and the transport addon. The actual command use as pipe is retrieved from the PPD that can be selected
at printer creation time.

Currently PPD selection is not shown (as the PPD directory is not available) and therefore the pipe
will not be inserted.

This still needs a bit of TLC, so hope to commit the last changes to fully support this later this week.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36173 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ithamar R. Adema 2010-04-11 22:01:13 +00:00
parent 954af58694
commit f7b0c08cae
16 changed files with 807 additions and 81 deletions

View File

@ -20,9 +20,9 @@ class BNode;
class PrinterData {
public:
PrinterData(BNode *node = NULL);
~PrinterData();
void load();
void save();
virtual ~PrinterData();
virtual void load();
virtual void save();
const string &getDriverName() const;
const string &getPrinterName() const;
@ -40,14 +40,13 @@ protected:
PrinterData(const PrinterData &printer_data);
PrinterData &operator = (const PrinterData &printer_data);
BNode *fNode;
private:
string fDriverName;
string fPrinterName;
string fComments;
string fTransport;
int fProtocolClass;
BNode *fNode;
};
inline const string &PrinterData::getDriverName() const

View File

@ -26,6 +26,7 @@ public:
virtual const char* GetCopyright() const = 0;
virtual PrinterCap* InstantiatePrinterCap(PrinterData* printerData) = 0;
virtual PrinterData* InstantiatePrinterData(BNode* node);
virtual GraphicsDriver* InstantiateGraphicsDriver(BMessage* settings, PrinterData* printerData, PrinterCap* printerCap) = 0;
void InitPrinterDataAndCap();

View File

@ -0,0 +1,131 @@
/*
* Copyright 2010, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
*/
#include "FilterIO.h"
#include <String.h>
#include <image.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
FilterIO::FilterIO(const BString& cmdline)
: BDataIO()
{
BString cmd(cmdline);
const char *argv[4];
argv[0] = strdup("/bin/sh");
argv[1] = strdup("-c");
argv[2] = strdup(cmd.String());
argv[3] = NULL;
InitData(3,argv);
free((void*)argv[0]);
free((void*)argv[1]);
free((void*)argv[2]);
}
FilterIO::FilterIO(int argc, const char **argv, const char **envp)
: BDataIO()
{
InitData(argc,argv,envp);
}
status_t
FilterIO::InitData(int argc, const char **argv, const char **envp)
{
fStdIn =
fStdOut =
fStdErr = -1;
fInitErr = B_OK;
fThreadId = PipeCommand(argc, argv, fStdIn, fStdOut, fStdErr, envp);
if (fThreadId < 0)
fInitErr = fThreadId;
// lower the command priority since it is a background task.
set_thread_priority(fThreadId, B_LOW_PRIORITY);
resume_thread(fThreadId);
return fInitErr;
}
FilterIO::~FilterIO()
{
::close(fStdIn);
::close(fStdOut);
::close(fStdErr);
}
ssize_t
FilterIO::Read(void *buffer, size_t size)
{
return ::read(fStdOut, buffer, size);
}
ssize_t
FilterIO::Write(const void *buffer, size_t size)
{
return ::write(fStdIn, buffer, size);
}
thread_id
FilterIO::PipeCommand(int argc, const char **argv, int &in, int &out, int &err, const char **envp)
{
// This function written by Peter Folk <pfolk@uni.uiuc.edu>
// and published in the BeDevTalk FAQ
// http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
if (!envp)
envp = (const char**)environ;
// Save current FDs
int old_in = dup(0);
int old_out = dup(1);
int old_err = dup(2);
int filedes[2];
/* Create new pipe FDs as stdin, stdout, stderr */
pipe(filedes); dup2(filedes[0], 0); close(filedes[0]);
in = filedes[1]; // Write to in, appears on cmd's stdin
pipe(filedes); dup2(filedes[1], 1); close(filedes[1]);
out = filedes[0]; // Read from out, taken from cmd's stdout
pipe(filedes); dup2(filedes[1], 2); close(filedes[1]);
err = filedes[0]; // Read from err, taken from cmd's stderr
// "load" command.
thread_id ret = load_image(argc, argv, envp);
if (ret < B_OK)
goto cleanup;
// thread ret is now suspended.
setpgid(ret, ret);
cleanup:
// Restore old FDs
close(0); dup(old_in); close(old_in);
close(1); dup(old_out); close(old_out);
close(2); dup(old_err); close(old_err);
/* Theoretically I should do loads of error checking, but
the calls aren't very likely to fail, and that would
muddy up the example quite a bit. YMMV. */
return ret;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2010, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
*/
#ifndef FILTERIO_H
#define FILTERIO_H
#include <DataIO.h>
#include <OS.h>
class BString;
class FilterIO : public BDataIO
{
public:
FilterIO(int argc, const char **argv, const char **envp = NULL);
FilterIO(const BString& cmdline);
~FilterIO();
status_t InitCheck() const
{
return fInitErr;
}
ssize_t Read(void *buffer, size_t size);
ssize_t Write(const void *buffer, size_t size);
private:
int fStdIn, fStdOut, fStdErr;
thread_id fThreadId;
status_t fInitErr;
status_t InitData(int argc, const char **argv, const char **envp = NULL);
thread_id PipeCommand(int argc, const char **argv, int &in, int &out, int &err, const char **envp = NULL);
};
#endif /* FILTERIO_H */

View File

@ -10,6 +10,10 @@ Addon PS\ Compatible :
PSEntry.cpp
PS.cpp
PSCap.cpp
PSData.cpp
SelectPPDDlg.cpp
PPDParser.cpp
FilterIO.cpp
: be libprint.a $(TARGET_LIBSTDC++)
;

View File

@ -0,0 +1,93 @@
/*
* Copyright 2010, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
*/
#include "PPDParser.h"
#include <Path.h>
#include <File.h>
PPDParser::PPDParser(BFile& file)
{
InitData(file);
}
PPDParser::PPDParser(const BDirectory& dir, const char *fname)
{
BFile file(&dir,fname, B_READ_ONLY);
InitData(file);
}
PPDParser::PPDParser(const BPath& path)
{
BFile file(path.Path(), B_READ_ONLY);
InitData(file);
}
status_t
PPDParser::InitData(BFile& file)
{
// Check if file exists...
if ((fInitErr=file.InitCheck()) != B_OK)
return fInitErr;
// Read entire file into BString
ssize_t len;
char buffer[1025];
while ((len=file.Read(buffer,sizeof(buffer)-1)) > 0) {
buffer[len] = '\0';
fContent << buffer;
}
// Convert DOS/Windows newlines to UNIX ones
fContent.ReplaceAll("\r\n", "\n");
// Handle line continuation
fContent.ReplaceAll("&&\n", "");
// Make sure file ends with newline
fContent << '\n';
return B_OK;
}
BString
PPDParser::GetParameter(const BString& param)
{
BString result, line;
int32 pos = 0, next;
BString pattern;
pattern << "*" << param << ":";
while ((next=fContent.FindFirst('\n', pos)) > 0) {
// Grab line (without newline)
fContent.CopyInto(line, pos, next-pos);
// Found our parameter?
if (line.Compare(pattern,pattern.Length()) == 0) {
// Copy result
line.CopyInto(result, pattern.Length(), line.Length() - pattern.Length()).Trim();
// If result is quoted, remove quotes
if (result[0] == '"') {
result.Truncate(result.Length() -1);
result.Remove(0,1);
}
break;
}
pos = next +1;
}
return result;
}
PPDParser::~PPDParser()
{
}

View File

@ -0,0 +1,31 @@
#ifndef PPDPARSER_H
#define PPDPARSER_H
#include <String.h>
class BPath;
class BFile;
class BDirectory;
class PPDParser
{
public:
PPDParser(const BDirectory& dir, const char *fname);
PPDParser(const BPath& path);
PPDParser(BFile& file);
~PPDParser();
status_t InitCheck() const
{
return fInitErr;
}
BString GetParameter(const BString& param);
private:
status_t InitData(BFile& file);
BString fContent;
status_t fInitErr;
};
#endif /* PPDPARSER_H */

View File

@ -2,13 +2,16 @@
* PS.cpp
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
* Copyright 2003 Michael Pfeiffer.
* Copyright 2010 Ithamar Adema.
*/
#include <Alert.h>
#include <Bitmap.h>
#include <File.h>
#include <Path.h>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include "PS.h"
#include "UIDriver.h"
#include "JobData.h"
@ -18,6 +21,9 @@
#include "Halftone.h"
#include "ValidRect.h"
#include "DbgMsg.h"
#include "PSData.h"
#include "FilterIO.h"
#include "PPDParser.h"
#if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
@ -26,16 +32,86 @@ using namespace std;
#define std
#endif
PSDriver::PSDriver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap)
: GraphicsDriver(msg, printer_data, printer_cap)
{
fPrintedPages = 0;
fHalftone = NULL;
fFilterIO = NULL;
}
bool PSDriver::startDoc()
void
PSDriver::StartFilterIfNeeded()
{
const PSData *data = dynamic_cast<const PSData*>(getPrinterData());
PPDParser parser(BPath(data->fPPD.String()));
if (parser.InitCheck() == B_OK) {
BString param = parser.GetParameter("FoomaticRIPCommandLine");
char str[3] = "%?";
// for now, we don't have any extra substitutions to do...
// (will be added once we support configuration options from the PPD)
for (str[1] = 'A'; str[1] <= 'Z'; str[1]++)
param.ReplaceAll(str, "");
if (param.Length())
fFilterIO = new FilterIO(param);
if (!fFilterIO || fFilterIO->InitCheck() != B_OK) {
delete fFilterIO;
fFilterIO = NULL;
}
}
}
void
PSDriver::FlushFilterIfNeeded()
{
if (fFilterIO) {
char buffer[1024];
ssize_t len;
while ((len = fFilterIO->Read(buffer,sizeof(buffer))) > 0)
writeSpoolData(buffer, len);
}
}
void
PSDriver::writePSString(const char *format, ...)
{
char str[256];
va_list ap;
va_start(ap, format);
vsprintf(str, format, ap);
if (fFilterIO)
fFilterIO->Write(str, strlen(str));
else
writeSpoolData(str, strlen(str));
va_end(ap);
}
void
PSDriver::writePSData(const void *data, size_t size)
{
if (fFilterIO)
fFilterIO->Write(data, size);
else
writeSpoolData(data,size);
}
bool
PSDriver::startDoc()
{
try {
StartFilterIfNeeded();
jobStart();
fHalftone = new Halftone(getJobData()->getSurfaceType(), getJobData()->getGamma(), getJobData()->getInkDensity(), getJobData()->getDitherType());
return true;
@ -45,21 +121,28 @@ bool PSDriver::startDoc()
}
}
bool PSDriver::startPage(int page)
bool
PSDriver::startPage(int page)
{
page ++;
writeSpoolString("%%%%Page: %d %d\n", page, page);
writeSpoolString("gsave\n");
writePSString("%%%%Page: %d %d\n", page, page);
writePSString("gsave\n");
setupCTM();
return true;
}
bool PSDriver::endPage(int)
bool
PSDriver::endPage(int)
{
try {
fPrintedPages ++;
writeSpoolString("grestore\n");
writeSpoolString("showpage\n");
writePSString("grestore\n");
writePSString("showpage\n");
FlushFilterIfNeeded();
return true;
}
catch (TransportException &err) {
@ -67,26 +150,31 @@ bool PSDriver::endPage(int)
}
}
void PSDriver::setupCTM() {
void
PSDriver::setupCTM()
{
const float leftMargin = getJobData()->getPrintableRect().left;
const float topMargin = getJobData()->getPrintableRect().top;
if (getJobData()->getOrientation() == JobData::kPortrait) {
// move origin from bottom left to top left
// and set margin
writeSpoolString("%f %f translate\n", leftMargin, getJobData()->getPaperRect().Height()-topMargin);
writePSString("%f %f translate\n", leftMargin, getJobData()->getPaperRect().Height()-topMargin);
} else {
// landscape:
// move origin from bottom left to margin top and left
// and rotate page contents
writeSpoolString("%f %f translate\n", topMargin, leftMargin);
writeSpoolString("90 rotate\n");
writePSString("%f %f translate\n", topMargin, leftMargin);
writePSString("90 rotate\n");
}
// y values increase from top to bottom
// units of measure is dpi
writeSpoolString("72 %d div 72 -%d div scale\n", getJobData()->getXres(), getJobData()->getYres());
writePSString("72 %d div 72 -%d div scale\n", getJobData()->getXres(), getJobData()->getYres());
}
bool PSDriver::endDoc(bool)
bool
PSDriver::endDoc(bool)
{
try {
if (fHalftone) {
@ -100,13 +188,17 @@ bool PSDriver::endDoc(bool)
}
}
inline uchar hex_digit(uchar value)
inline uchar
hex_digit(uchar value)
{
if (value <= 9) return '0'+value;
else return 'a'+(value-10);
}
bool PSDriver::nextBand(BBitmap *bitmap, BPoint *offset)
bool
PSDriver::nextBand(BBitmap *bitmap, BPoint *offset)
{
DBGMSG(("> nextBand\n"));
@ -243,52 +335,60 @@ bool PSDriver::nextBand(BBitmap *bitmap, BPoint *offset)
}
}
void PSDriver::jobStart()
void
PSDriver::jobStart()
{
// PostScript header
writeSpoolString("%%!PS-Adobe-3.0\n");
writeSpoolString("%%%%LanguageLevel: 1\n");
writeSpoolString("%%%%Title: %s\n", getSpoolMetaData()->getDescription().c_str());
writeSpoolString("%%%%Creator: %s\n", getSpoolMetaData()->getMimeType().c_str());
writeSpoolString("%%%%CreationDate: %s", getSpoolMetaData()->getCreationTime().c_str());
writeSpoolString("%%%%DocumentMedia: Plain %d %d white 0 ( )\n", getJobData()->getPaperRect().IntegerWidth(), getJobData()->getPaperRect().IntegerHeight());
writeSpoolString("%%%%Pages: (atend)\n");
writeSpoolString("%%%%EndComments\n");
writePSString("%%!PS-Adobe-3.0\n");
writePSString("%%%%LanguageLevel: 1\n");
writePSString("%%%%Title: %s\n", getSpoolMetaData()->getDescription().c_str());
writePSString("%%%%Creator: %s\n", getSpoolMetaData()->getMimeType().c_str());
writePSString("%%%%CreationDate: %s", getSpoolMetaData()->getCreationTime().c_str());
writePSString("%%%%DocumentMedia: Plain %d %d white 0 ( )\n", getJobData()->getPaperRect().IntegerWidth(), getJobData()->getPaperRect().IntegerHeight());
writePSString("%%%%Pages: (atend)\n");
writePSString("%%%%EndComments\n");
writeSpoolString("%%%%BeginDefaults\n");
writeSpoolString("%%%%PageMedia: Plain\n");
writeSpoolString("%%%%EndDefaults\n");
writePSString("%%%%BeginDefaults\n");
writePSString("%%%%PageMedia: Plain\n");
writePSString("%%%%EndDefaults\n");
}
void PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte)
void
PSDriver::startRasterGraphics(int x, int y, int width, int height, int widthByte)
{
bool color = getJobData()->getColor() == JobData::kColor;
fCompressionMethod = -1;
writeSpoolString("gsave\n");
writeSpoolString("/s %d string def\n", widthByte);
writeSpoolString("%d %d translate\n", x, y);
writeSpoolString("%d %d scale\n", width, height);
writePSString("gsave\n");
writePSString("/s %d string def\n", widthByte);
writePSString("%d %d translate\n", x, y);
writePSString("%d %d scale\n", width, height);
if (color) {
writeSpoolString("%d %d 8\n", width, height); // 8 bpp
writePSString("%d %d 8\n", width, height); // 8 bpp
} else {
writeSpoolString("%d %d 1\n", width, height); // 1 bpp
writePSString("%d %d 1\n", width, height); // 1 bpp
}
writeSpoolString("[%d 0 0 %d 0 0]\n", width, height);
writeSpoolString("{ currentfile s readhexstring pop }\n");
writePSString("[%d 0 0 %d 0 0]\n", width, height);
writePSString("{ currentfile s readhexstring pop }\n");
if (color) {
writeSpoolString("false 3\n"); // single data source, 3 color components
writeSpoolString("colorimage\n");
writePSString("false 3\n"); // single data source, 3 color components
writePSString("colorimage\n");
} else {
writeSpoolString("image\n\n");
writePSString("image\n\n");
}
}
void PSDriver::endRasterGraphics()
void
PSDriver::endRasterGraphics()
{
writeSpoolString("grestore\n");
writePSString("grestore\n");
}
void PSDriver::rasterGraphics(
void
PSDriver::rasterGraphics(
int compression_method,
const uchar *buffer,
int size)
@ -296,12 +396,16 @@ void PSDriver::rasterGraphics(
if (fCompressionMethod != compression_method) {
fCompressionMethod = compression_method;
}
writeSpoolData(buffer, size);
writeSpoolString("\n");
writePSData(buffer, size);
writePSString("\n");
}
void PSDriver::jobEnd()
void
PSDriver::jobEnd()
{
writeSpoolString("%%%%Pages: %d\n", fPrintedPages);
writeSpoolString("%%%%EOF\n");
writePSString("%%%%Pages: %d\n", fPrintedPages);
writePSString("%%%%EOF\n");
FlushFilterIfNeeded();
}

View File

@ -8,8 +8,11 @@
#include "GraphicsDriver.h"
class FilterIO;
class Halftone;
class PSDriver : public GraphicsDriver {
public:
PSDriver(BMessage *msg, PrinterData *printer_data, const PrinterCap *printer_cap);
@ -32,9 +35,15 @@ private:
int size);
void jobEnd();
void StartFilterIfNeeded();
void FlushFilterIfNeeded();
void writePSString(const char *format, ...);
void writePSData(const void *data, size_t size);
int fPrintedPages;
int fCompressionMethod;
Halftone *fHalftone;
FilterIO *fFilterIO;
};
#endif /* __PS_H */

View File

@ -0,0 +1,27 @@
/*
* Copyright 2010, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
*/
#include "PSData.h"
#include <Node.h>
#define PD_PPD_PATH "ps:ppd_path"
void
PSData::load()
{
PrinterData::load();
fNode->ReadAttrString(PD_PPD_PATH, &fPPD);
}
void
PSData::save()
{
PrinterData::save();
fNode->WriteAttrString(PD_PPD_PATH, &fPPD);
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2010, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
*/
#ifndef PSDATA_H
#define PSDATA_H
#include "PrinterData.h"
#include <String.h>
class BNode;
class PSData : public PrinterData {
public:
PSData(BNode *node) : PrinterData(node) {}
// PrinterData overrides
virtual void load();
virtual void save();
BString fPPD;
};
#endif /* PSDATA_H */

View File

@ -2,49 +2,75 @@
* PSEntry.cpp
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
* Copyright 2003 Michael Pfeiffer.
* Copyright 2010 Ithamar Adema.
*/
#include "PS.h"
#include "PSCap.h"
#include "PSData.h"
#include "PrinterDriver.h"
#include "SelectPPDDlg.h"
class PSPrinterDriver : public PrinterDriver
{
#include <Entry.h>
#include <Path.h>
class PSPrinterDriver : public PrinterDriver {
public:
PSPrinterDriver(BNode* printerFolder) : PrinterDriver(printerFolder) {}
const char* GetSignature() const
PSPrinterDriver(BNode *printerFolder) : PrinterDriver(printerFolder) {}
const char *GetSignature() const
{
return "application/x-vnd.PS-compatible";
}
const char* GetDriverName() const
{
return "PS compatible";
}
const char* GetVersion() const
{
return "0.1";
}
const char* GetCopyright() const
{
return "PS driver Copyright © 2003,04 Michael Pfeiffer.\n";
return "application/x-vnd.PS-compatible";
}
PrinterCap* InstantiatePrinterCap(PrinterData* printerData)
const char *GetDriverName() const
{
return "PS compatible";
}
const char *GetVersion() const
{
return "0.1";
}
const char *GetCopyright() const
{
return "PS driver Copyright © 2003,04 Michael Pfeiffer.\n";
}
char *AddPrinter(char *printerName)
{
BPath path;
if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) == B_OK
&& path.Append("ppd") == B_OK
&& BEntry(path.Path()).Exists()) {
SelectPPDDlg *dialog = new SelectPPDDlg(dynamic_cast<PSData*>(GetPrinterData()));
if (dialog->Go() != B_OK)
return NULL;
}
return printerName;
}
PrinterData *InstantiatePrinterData(BNode *node)
{
return new PSData(node);
}
PrinterCap *InstantiatePrinterCap(PrinterData *printerData)
{
return new PSCap(printerData);
}
GraphicsDriver* InstantiateGraphicsDriver(BMessage* settings, PrinterData* printerData, PrinterCap* printerCap)
GraphicsDriver *InstantiateGraphicsDriver(BMessage *settings, PrinterData *printerData, PrinterCap *printerCap)
{
return new PSDriver(settings, printerData, printerCap);
}
};
PrinterDriver* instantiate_printer_driver(BNode* printerFolder)
PrinterDriver *
instantiate_printer_driver(BNode *printerFolder)
{
return new PSPrinterDriver(printerFolder);
}

View File

@ -0,0 +1,190 @@
/*
* Copyright 2010, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema <ithamar.adema@team-embedded.nl>
*/
#include "SelectPPDDlg.h"
#include "PPDParser.h"
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <Button.h>
#include <Message.h>
#include <ListView.h>
#include <ScrollView.h>
#include <ScrollBar.h>
#include <StringItem.h>
#include <Directory.h>
#include <String.h>
#include <Entry.h>
#include <Path.h>
enum {
kMsgCancel = 'stop',
kMsgOK = 'okok',
kMsgManuSelected = 'msel',
kMsgPrinterSelected = 'psel',
};
class PPDStringItem : public BStringItem {
public:
PPDStringItem(const BString& text, const BString& path)
: BStringItem(text.String()),
fPPDPath(path) {}
BString fPPDPath;
};
SelectPPDDlg::SelectPPDDlg(PSData *data)
: DialogWindow(BRect(10, 10, 400, 400),
"Select PPD", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS),
fPSData(data)
{
SetResult(B_ERROR);
BButton *ok, *cancel;
ok = new BButton("btn:ok", "OK", new BMessage(kMsgOK));
ok->MakeDefault(true);
ok->SetEnabled(false);
fOKButton = ok;
cancel = new BButton("btn:cancel", "Cancel", new BMessage(kMsgCancel));
BScrollView *manuScroller, *printerScroller;
fManufacturersListView = new BListView("olv:manufacturers");
manuScroller=new BScrollView("scr:manufacturers", fManufacturersListView, 0, false, true);
fPrintersListView = new BListView("olv:printers");
printerScroller=new BScrollView("scr:printers", fPrintersListView, 0, false, true);
fPrintersListView->SetSelectionMessage(new BMessage(kMsgPrinterSelected));
fManufacturersListView->SetSelectionMessage(new BMessage(kMsgManuSelected));
PopulateManufacturers(B_SYSTEM_DATA_DIRECTORY);
// Build the layout
SetLayout(new BGroupLayout(B_VERTICAL));
AddChild(BGroupLayoutBuilder(B_VERTICAL, 10)
.AddGroup(B_HORIZONTAL, 5)
.Add(manuScroller)
.Add(printerScroller)
.End()
.AddGroup(B_HORIZONTAL, 5)
.AddGlue()
.Add(cancel)
.Add(ok)
.End()
.SetInsets(10, 10, 10, 10)
);
}
void
SelectPPDDlg::PopulateManufacturers(directory_which data_dir)
{
char name[1024];
BDirectory dir;
BEntry entry;
BPath path;
if (find_directory(data_dir, &path) == B_OK
&& path.Append("ppd") == B_OK
&& dir.SetTo(path.Path()) == B_OK) {
// Got the directory, now scan it
while(dir.GetNextEntry(&entry) == B_OK)
if (entry.IsDirectory()
&& entry.GetName(name) == B_OK)
fManufacturersListView->AddItem(new BStringItem(name));
}
}
void
SelectPPDDlg::PopulatePrinters(directory_which data_dir)
{
int32 idx = fManufacturersListView->CurrentSelection();
char name[1024];
BDirectory dir;
BString manu;
BEntry entry;
BPath path;
// Bail out if no manufacturer is selected
if (idx < 0)
return;
manu = ((BStringItem*)fManufacturersListView->ItemAt(idx))->Text();
if (find_directory(data_dir, &path) == B_OK
&& path.Append("ppd") == B_OK
&& path.Append(manu) == B_OK
&& dir.SetTo(path.Path()) == B_OK) {
// Found manufacturer PPD directory, now fill our printer list
while(dir.GetNextEntry(&entry) == B_OK)
if (entry.GetName(name) == B_OK) {
PPDParser parser(dir,name);
if (parser.InitCheck() == B_OK) {
BString modelName = parser.GetParameter("ModelName");
BPath ppdPath = path;
ppdPath.Append(name);
fPrintersListView->AddItem(new PPDStringItem(modelName, ppdPath.Path()));
}
}
}
}
void
SelectPPDDlg::PrinterSelected()
{
int32 idx = fPrintersListView->CurrentSelection();
fOKButton->SetEnabled(idx >= 0);
}
void
SelectPPDDlg::Save()
{
BString ppdPath;
int32 idx;
idx = fPrintersListView->CurrentSelection();
if (idx >= 0)
ppdPath = dynamic_cast<PPDStringItem*>(fPrintersListView->ItemAt(idx))->fPPDPath;
fPSData->fPPD = ppdPath;
fPSData->save();
}
void
SelectPPDDlg::MessageReceived(BMessage *msg)
{
switch (msg->what) {
case kMsgManuSelected:
fPrintersListView->MakeEmpty();
PopulatePrinters(B_SYSTEM_DATA_DIRECTORY);
break;
case kMsgPrinterSelected:
PrinterSelected();
break;
case kMsgOK:
Save();
SetResult(B_NO_ERROR);
PostMessage(B_QUIT_REQUESTED);
break;
case kMsgCancel:
PostMessage(B_QUIT_REQUESTED);
break;
default:
DialogWindow::MessageReceived(msg);
break;
}
}

View File

@ -0,0 +1,30 @@
#ifndef SELECTPPDDLG_H
#define SELECTPPDDLG_H
#include "DialogWindow.h"
#include "PSData.h"
#include <storage/FindDirectory.h>
class BListView;
class BButton;
class PSData;
class SelectPPDDlg : public DialogWindow {
public:
SelectPPDDlg(PSData *data);
void MessageReceived(BMessage *msg);
private:
void PopulateManufacturers(directory_which data_dir);
void PopulatePrinters(directory_which data_dir);
void PrinterSelected();
void Save();
BListView *fManufacturersListView;
BListView *fPrintersListView;
BButton *fOKButton;
PSData *fPSData;
};
#endif /* SELECTPPDDLG_H */

View File

@ -17,10 +17,9 @@ const char *PD_TRANSPORT = "transport";
const char *PD_PROTOCOL_CLASS = "libprint:protocolClass";
PrinterData::PrinterData(BNode *node)
: fProtocolClass(0)
, fNode(node)
: fNode(node),
fProtocolClass(0)
{
load();
}
PrinterData::~PrinterData()

View File

@ -49,9 +49,20 @@ PrinterDriver::~PrinterDriver()
fPrinterData = NULL;
}
PrinterData*
PrinterDriver::InstantiatePrinterData(BNode* node)
{
return new PrinterData(node);
}
void
PrinterDriver::InitPrinterDataAndCap() {
fPrinterData = new PrinterData(fSpoolFolder);
fPrinterData = InstantiatePrinterData(fSpoolFolder);
fPrinterData->load();
// NOTE: moved the load above from the constructor of PrinterData as
// we're inheriting from PrinterData and want our overridden versions
// of load to be called
fPrinterCap = InstantiatePrinterCap(fPrinterData);
}