1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All rights reserved.
33*/
34
35//	DesktopPoseView adds support for displaying integrated desktops
36//	from multiple volumes to BPoseView
37//
38//	Used by the Desktop window and by the root view in file panels
39
40#include "DesktopPoseView.h"
41
42#include <NodeMonitor.h>
43#include <Path.h>
44#include <Volume.h>
45#include <VolumeRoster.h>
46
47#include "Commands.h"
48#include "FSUtils.h"
49#include "PoseList.h"
50#include "Tracker.h"
51#include "TrackerSettings.h"
52#include "TrackerString.h"
53
54
55//	#pragma mark -
56
57
58DesktopPoseView::DesktopPoseView(Model* model, BRect frame, uint32 viewMode,
59	uint32 resizeMask)
60	:
61	BPoseView(model, frame, viewMode, resizeMask)
62{
63	SetFlags(Flags() | B_DRAW_ON_CHILDREN);
64}
65
66
67EntryListBase*
68DesktopPoseView::InitDesktopDirentIterator(BPoseView* nodeMonitoringTarget,
69	const entry_ref* ref)
70{
71	// the desktop dirent iterator knows how to iterate over all the volumes,
72	// integrated onto the desktop
73
74	Model sourceModel(ref, false, true);
75	if (sourceModel.InitCheck() != B_OK)
76		return NULL;
77
78	CachedEntryIteratorList* result = new CachedEntryIteratorList();
79
80	ASSERT(!sourceModel.IsQuery());
81	ASSERT(sourceModel.Node());
82	BDirectory* sourceDirectory
83		= dynamic_cast<BDirectory*>(sourceModel.Node());
84
85	ASSERT(sourceDirectory);
86
87	// build an iterator list, start with boot
88	EntryListBase* perDesktopIterator
89		= new CachedDirectoryEntryList(*sourceDirectory);
90
91	result->AddItem(perDesktopIterator);
92	if (nodeMonitoringTarget) {
93		TTracker::WatchNode(sourceModel.NodeRef(),
94			B_WATCH_DIRECTORY | B_WATCH_NAME | B_WATCH_STAT | B_WATCH_ATTR,
95			nodeMonitoringTarget);
96	}
97
98	if (result->Rewind() != B_OK) {
99		delete result;
100		if (nodeMonitoringTarget)
101			nodeMonitoringTarget->HideBarberPole();
102
103		return NULL;
104	}
105
106	return result;
107}
108
109
110EntryListBase*
111DesktopPoseView::InitDirentIterator(const entry_ref* ref)
112{
113	return InitDesktopDirentIterator(this, ref);
114}
115
116
117bool
118DesktopPoseView::FSNotification(const BMessage* message)
119{
120	switch (message->FindInt32("opcode")) {
121		case B_DEVICE_MOUNTED:
122		{
123			dev_t device;
124			if (message->FindInt32("new device", &device) != B_OK)
125				break;
126
127			ASSERT(TargetModel());
128			TrackerSettings settings;
129
130			BVolume volume(device);
131			if (volume.InitCheck() != B_OK)
132				break;
133
134			if (settings.MountVolumesOntoDesktop()
135				&& (!volume.IsShared()
136					|| settings.MountSharedVolumesOntoDesktop())) {
137				// place an icon for the volume onto the desktop
138				CreateVolumePose(&volume, true);
139			}
140		}
141		break;
142	}
143
144	return _inherited::FSNotification(message);
145}
146
147
148bool
149DesktopPoseView::AddPosesThreadValid(const entry_ref*) const
150{
151	return true;
152}
153
154
155void
156DesktopPoseView::AddPosesCompleted()
157{
158	_inherited::AddPosesCompleted();
159	CreateTrashPose();
160}
161
162
163bool
164DesktopPoseView::Represents(const node_ref* ref) const
165{
166	// When the Tracker is set up to integrate non-boot beos volumes,
167	// it represents the home/Desktop folders of all beos volumes
168
169	return _inherited::Represents(ref);
170}
171
172
173bool
174DesktopPoseView::Represents(const entry_ref* ref) const
175{
176	BEntry entry(ref);
177	node_ref nref;
178	entry.GetNodeRef(&nref);
179	return Represents(&nref);
180}
181
182
183void
184DesktopPoseView::ShowVolumes(bool visible, bool showShared)
185{
186	if (LockLooper()) {
187		SavePoseLocations();
188		if (!visible)
189			RemoveRootPoses();
190		else
191			AddRootPoses(true, showShared);
192		UnlockLooper();
193	}
194}
195
196
197void
198DesktopPoseView::StartSettingsWatch()
199{
200	be_app->LockLooper();
201	be_app->StartWatching(this, kShowDisksIconChanged);
202	be_app->StartWatching(this, kVolumesOnDesktopChanged);
203	be_app->StartWatching(this, kDesktopIntegrationChanged);
204	be_app->UnlockLooper();
205}
206
207
208void
209DesktopPoseView::StopSettingsWatch()
210{
211	be_app->LockLooper();
212	be_app->StopWatching(this, kShowDisksIconChanged);
213	be_app->StopWatching(this, kVolumesOnDesktopChanged);
214	be_app->StopWatching(this, kDesktopIntegrationChanged);
215	be_app->UnlockLooper();
216}
217
218
219void
220DesktopPoseView::AdaptToVolumeChange(BMessage* message)
221{
222	TTracker* tracker = dynamic_cast<TTracker*>(be_app);
223	if (!tracker)
224		return;
225
226	bool showDisksIcon = false;
227	bool mountVolumesOnDesktop = true;
228	bool mountSharedVolumesOntoDesktop = false;
229
230	message->FindBool("ShowDisksIcon", &showDisksIcon);
231	message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop);
232	message->FindBool("MountSharedVolumesOntoDesktop",
233		&mountSharedVolumesOntoDesktop);
234
235	BEntry entry("/");
236	Model model(&entry);
237	if (model.InitCheck() == B_OK) {
238		BMessage entryMessage;
239		entryMessage.what = B_NODE_MONITOR;
240
241		if (showDisksIcon)
242			entryMessage.AddInt32("opcode", B_ENTRY_CREATED);
243		else {
244			entryMessage.AddInt32("opcode", B_ENTRY_REMOVED);
245			entry_ref ref;
246			if (entry.GetRef(&ref) == B_OK) {
247				BContainerWindow* disksWindow
248					= tracker->FindContainerWindow(&ref);
249				if (disksWindow) {
250					disksWindow->Lock();
251					disksWindow->Close();
252				}
253			}
254		}
255		entryMessage.AddInt32("device", model.NodeRef()->device);
256		entryMessage.AddInt64("node", model.NodeRef()->node);
257		entryMessage.AddInt64("directory", model.EntryRef()->directory);
258		entryMessage.AddString("name", model.EntryRef()->name);
259		BContainerWindow* deskWindow
260			= dynamic_cast<BContainerWindow*>(Window());
261		if (deskWindow)
262			deskWindow->PostMessage(&entryMessage, deskWindow->PoseView());
263	}
264
265	ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop);
266}
267
268
269void
270DesktopPoseView::AdaptToDesktopIntegrationChange(BMessage* message)
271{
272	bool mountVolumesOnDesktop = true;
273	bool mountSharedVolumesOntoDesktop = true;
274
275	message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop);
276	message->FindBool("MountSharedVolumesOntoDesktop",
277		&mountSharedVolumesOntoDesktop);
278
279	ShowVolumes(false, mountSharedVolumesOntoDesktop);
280	ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop);
281}
282