1/*
2* Copyright 2010, Haiku. All rights reserved.
3* Distributed under the terms of the MIT License.
4*
5* Authors:
6*		Ithamar R. Adema <ithamar.adema@team-embedded.nl>
7*/
8
9
10#include "SelectPPDDlg.h"
11
12#include <GroupLayout.h>
13#include <GroupLayoutBuilder.h>
14
15#include <Button.h>
16#include <Directory.h>
17#include <Entry.h>
18#include <ListView.h>
19#include <Message.h>
20#include <Path.h>
21#include <ScrollBar.h>
22#include <ScrollView.h>
23#include <String.h>
24#include <StringItem.h>
25
26#include "PPDParser.h"
27
28enum {
29	kMsgCancel = 'stop',
30	kMsgOK = 'okok',
31
32	kMsgManuSelected = 'msel',
33	kMsgPrinterSelected = 'psel',
34};
35
36
37class PPDStringItem : public BStringItem {
38public:
39			PPDStringItem(const BString& text, const BString& path)
40			:
41			BStringItem(text.String()),
42			fPPDPath(path)
43			{
44			}
45
46	BString	fPPDPath;
47};
48
49
50SelectPPDDlg::SelectPPDDlg(PSData* data)
51	: DialogWindow(BRect(10, 10, 400, 400),
52		"Select PPD", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
53		B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS
54			| B_CLOSE_ON_ESCAPE),
55		fPSData(data)
56{
57	SetResult(B_ERROR);
58
59	BButton* ok;
60	BButton* cancel;
61
62	ok = new BButton("btn:ok", "OK", new BMessage(kMsgOK));
63	ok->MakeDefault(true);
64	ok->SetEnabled(false);
65	fOKButton = ok;
66
67	cancel = new BButton("btn:cancel", "Cancel", new BMessage(kMsgCancel));
68
69	BScrollView* manuScroller, *printerScroller;
70	fManufacturersListView = new BListView("olv:manufacturers");
71	manuScroller = new BScrollView("scr:manufacturers", fManufacturersListView,
72		0, false, true);
73	fPrintersListView = new BListView("olv:printers");
74	printerScroller = new BScrollView("scr:printers", fPrintersListView, 0,
75		false, true);
76
77	fPrintersListView->SetSelectionMessage(new BMessage(kMsgPrinterSelected));
78	fManufacturersListView->SetSelectionMessage(new BMessage(kMsgManuSelected));
79	PopulateManufacturers(B_SYSTEM_DATA_DIRECTORY);
80
81	// Build the layout
82	SetLayout(new BGroupLayout(B_VERTICAL));
83
84	AddChild(BGroupLayoutBuilder(B_VERTICAL, 10)
85		.AddGroup(B_HORIZONTAL, 5)
86			.Add(manuScroller)
87			.Add(printerScroller)
88		.End()
89		.AddGroup(B_HORIZONTAL, 5)
90			.AddGlue()
91			.Add(cancel)
92			.Add(ok)
93		.End()
94		.SetInsets(10, 10, 10, 10)
95	);
96}
97
98
99void
100SelectPPDDlg::PopulateManufacturers(directory_which data_dir)
101{
102	char name[1024];
103	BDirectory dir;
104	BEntry entry;
105	BPath path;
106
107	if (find_directory(data_dir, &path) == B_OK
108		&& path.Append("ppd") == B_OK
109		&& dir.SetTo(path.Path()) == B_OK) {
110		// Got the directory, now scan it
111		while (dir.GetNextEntry(&entry) == B_OK)
112			if (entry.IsDirectory()
113				&& entry.GetName(name) == B_OK)
114				fManufacturersListView->AddItem(new BStringItem(name));
115	}
116}
117
118
119void
120SelectPPDDlg::PopulatePrinters(directory_which data_dir)
121{
122	int32 idx = fManufacturersListView->CurrentSelection();
123	char name[1024];
124	BDirectory dir;
125	BString manu;
126	BEntry entry;
127	BPath path;
128
129	// Bail out if no manufacturer is selected
130	if (idx < 0)
131		return;
132
133	manu = ((BStringItem*)fManufacturersListView->ItemAt(idx))->Text();
134
135	if (find_directory(data_dir, &path) == B_OK
136		&& path.Append("ppd") == B_OK
137		&& path.Append(manu) == B_OK
138		&& dir.SetTo(path.Path()) == B_OK) {
139		// Found manufacturer PPD directory, now fill our printer list
140		while (dir.GetNextEntry(&entry) == B_OK)
141			if (entry.GetName(name) == B_OK) {
142				PPDParser parser(dir, name);
143				if (parser.InitCheck() == B_OK) {
144					BString modelName = parser.GetParameter("ModelName");
145					BPath ppdPath = path;
146					ppdPath.Append(name);
147					fPrintersListView->AddItem(new PPDStringItem(modelName,
148						ppdPath.Path()));
149				}
150			}
151	}
152}
153
154
155void
156SelectPPDDlg::PrinterSelected()
157{
158	int32 idx = fPrintersListView->CurrentSelection();
159	fOKButton->SetEnabled(idx >= 0);
160}
161
162
163void
164SelectPPDDlg::Save()
165{
166	BString ppdPath;
167	int32 idx;
168
169	idx = fPrintersListView->CurrentSelection();
170	if (idx >= 0)
171		ppdPath = dynamic_cast<PPDStringItem*>
172			(fPrintersListView->ItemAt(idx))->fPPDPath;
173
174	fPSData->fPPD = ppdPath;
175	fPSData->Save();
176}
177
178
179void
180SelectPPDDlg::MessageReceived(BMessage* msg)
181{
182	switch (msg->what) {
183		case kMsgManuSelected:
184			fPrintersListView->MakeEmpty();
185			PopulatePrinters(B_SYSTEM_DATA_DIRECTORY);
186			break;
187		case kMsgPrinterSelected:
188			PrinterSelected();
189			break;
190		case kMsgOK:
191			Save();
192			SetResult(B_NO_ERROR);
193			PostMessage(B_QUIT_REQUESTED);
194			break;
195		case kMsgCancel:
196			PostMessage(B_QUIT_REQUESTED);
197			break;
198		default:
199			DialogWindow::MessageReceived(msg);
200			break;
201	}
202}
203