1/*
2 * Copyright 2008, Haiku.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 *		Michael Pfeiffer <laplace@users.sourceforge.net>
7 */
8
9#include "PrinterSelection.h"
10#include "PPDParser.h"
11#include "StatementListVisitor.h"
12#include "UIUtils.h"
13
14#include <Directory.h>
15#include <Entry.h>
16#include <Path.h>
17
18#include <ScrollView.h>
19#include <StringView.h>
20
21// margin
22const float kLeftMargin = 3.0;
23const float kRightMargin = 3.0;
24const float kTopMargin = 3.0;
25const float kBottomMargin = 3.0;
26
27// space between views
28const float kHorizontalSpace = 8.0;
29const float kVerticalSpace = 8.0;
30
31#include <stdio.h>
32
33PrinterSelectionView::PrinterSelectionView(BRect bounds, const char *name, uint32 resizeMask, uint32 flags)
34	: BView(bounds, name, resizeMask, flags)
35{
36	// add vendor list view
37	bounds.OffsetTo(0, 0);
38	BRect listBounds(bounds.left + kLeftMargin, bounds.top + kTopMargin,
39		bounds.right / 3.0 - kHorizontalSpace / 2, bounds.bottom - kBottomMargin);
40	listBounds.right -= B_V_SCROLL_BAR_WIDTH;
41	listBounds.bottom -= B_H_SCROLL_BAR_HEIGHT;
42
43	BStringView* label = new BStringView(listBounds, "vendors-label", "Vendors:");
44	AddChild(label);
45	label->ResizeToPreferred();
46
47	listBounds.top += label->Bounds().bottom + 5;
48
49	fVendors = new BListView(listBounds, "vendors", B_SINGLE_SELECTION_LIST,
50		B_FOLLOW_ALL);
51	FillVendors();
52
53	BScrollView* scrollView = new BScrollView("vendors-scroll-view",
54		fVendors, B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, 0, true, true);
55
56	AddChild(scrollView);
57
58	// add details view
59	BRect printerBounds(listBounds);
60	printerBounds.left = B_V_SCROLL_BAR_WIDTH + printerBounds.right + kHorizontalSpace;
61	printerBounds.right = bounds.right - kRightMargin - B_V_SCROLL_BAR_WIDTH;
62	printerBounds.top = bounds.top + kTopMargin;
63	label = new BStringView(printerBounds, "printers-label", "Printers:");
64	AddChild(label);
65	label->ResizeToPreferred();
66
67	BRect detailBounds(listBounds);
68	detailBounds.left = B_V_SCROLL_BAR_WIDTH + detailBounds.right + kHorizontalSpace;
69	detailBounds.right = bounds.right - kRightMargin - B_V_SCROLL_BAR_WIDTH;
70	fPrinters = new BListView(detailBounds, "printers", B_SINGLE_SELECTION_LIST,
71		B_FOLLOW_ALL);
72
73	scrollView = new BScrollView("printers-scroll-view",
74		fPrinters, B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, 0, true, true);
75
76	AddChild(scrollView);
77}
78
79void PrinterSelectionView::AttachedToWindow()
80{
81	fVendors->SetSelectionMessage(new BMessage('sel'));
82	fVendors->SetTarget(this);
83
84	fPrinters->SetSelectionMessage(new BMessage('prnt'));
85	fPrinters->SetTarget(this);
86}
87
88
89void PrinterSelectionView::FillVendors()
90{
91	BDirectory directory("/boot/beos/etc/ppd");
92	BEntry entry;
93	while (directory.GetNextEntry(&entry) == B_OK) {
94		char name[B_FILE_NAME_LENGTH];
95		entry.GetName(name);
96		BPath path;
97		entry.GetPath(&path);
98		fVendors->AddItem(new FileItem(name, path.Path()));
99	}
100}
101
102void PrinterSelectionView::FillPrinters(const char* vendor)
103{
104	MakeEmpty(fPrinters);
105
106	BList printers;
107	BDirectory directory(vendor);
108	BEntry entry;
109	while (directory.GetNextEntry(&entry) == B_OK) {
110		char name[B_FILE_NAME_LENGTH];
111		entry.GetName(name);
112		BPath path;
113		entry.GetPath(&path);
114
115		PPDParser parser(path.Path());
116		PPD* ppd = parser.ParseHeader();
117		if (parser.HasWarning()) {
118			fprintf(stderr, "Warning(s): %s", parser.GetWarningMessage());
119		}
120
121		if (ppd != NULL) {
122
123			BString label;
124			const char* s;
125			s = ppd->GetValue("ModelName");
126			if (s != NULL) {
127				label << s;
128			}
129			s = ppd->GetValue("PCFileName");
130			if (s != NULL) {
131				label << " [" << s << "]";
132			}
133			s = ppd->GetValue("Manufacturer");
134			if (s != NULL) {
135				label << " (" << s << ")";
136			}
137			printers.AddItem(new FileItem(label.String(), path.Path()));
138			delete ppd;
139		} else {
140			fprintf(stderr, "Parsing error (%s)\n%s\n", path.Path(),
141				parser.GetErrorMessage());
142		}
143	}
144
145	fPrinters->AddList(&printers);
146}
147
148void PrinterSelectionView::MessageReceived(BMessage* msg)
149{
150	int32 index;
151	switch (msg->what) {
152		case 'sel':
153			if (msg->FindInt32("index", &index) == B_OK) {
154				FileItem* file = (FileItem*)fVendors->ItemAt(index);
155				if (file != NULL) {
156					FillPrinters(file->GetFile());
157				}
158			}
159			break;
160		case 'prnt':
161			if (msg->FindInt32("index", &index) == B_OK) {
162				FileItem* file = (FileItem*)fPrinters->ItemAt(index);
163				if (file != NULL) {
164					BMessage copy(*Message());
165					copy.AddString("file", file->GetFile());
166					InvokeNotify(&copy);
167				}
168			}
169			break;
170	}
171	BView::MessageReceived(msg);
172}
173