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
41#include "DesktopPoseView.h"
42
43#include <NodeMonitor.h>
44#include <Path.h>
45#include <Volume.h>
46#include <VolumeRoster.h>
47
48#include "Commands.h"
49#include "FSUtils.h"
50#include "PoseList.h"
51#include "Tracker.h"
52#include "TrackerSettings.h"
53#include "TrackerString.h"
54
55
56//	#pragma mark - DesktopPoseView
57
58
59DesktopPoseView::DesktopPoseView(Model* model, uint32 viewMode)
60	:
61	BPoseView(model, viewMode)
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.IsVirtualDirectory());
82	ASSERT(sourceModel.Node() != NULL);
83
84	BDirectory* sourceDirectory = dynamic_cast<BDirectory*>(sourceModel.Node());
85	ThrowOnAssert(sourceDirectory != NULL);
86
87	// build an iterator list, start with boot
88	EntryListBase* perDesktopIterator
89		= new CachedDirectoryEntryList(*sourceDirectory);
90
91	result->AddItem(perDesktopIterator);
92	if (nodeMonitoringTarget != NULL) {
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 != NULL)
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
193		UnlockLooper();
194	}
195}
196
197
198void
199DesktopPoseView::StartSettingsWatch()
200{
201	if (be_app->LockLooper()) {
202		be_app->StartWatching(this, kShowDisksIconChanged);
203		be_app->StartWatching(this, kVolumesOnDesktopChanged);
204		be_app->StartWatching(this, kDesktopIntegrationChanged);
205		be_app->UnlockLooper();
206	}
207}
208
209
210void
211DesktopPoseView::StopSettingsWatch()
212{
213	if (be_app->LockLooper()) {
214		be_app->StopWatching(this, kShowDisksIconChanged);
215		be_app->StopWatching(this, kVolumesOnDesktopChanged);
216		be_app->StopWatching(this, kDesktopIntegrationChanged);
217		be_app->UnlockLooper();
218	}
219}
220
221
222void
223DesktopPoseView::AdaptToVolumeChange(BMessage* message)
224{
225	TTracker* tracker = dynamic_cast<TTracker*>(be_app);
226	ThrowOnAssert(tracker != NULL);
227
228	bool showDisksIcon = false;
229	bool mountVolumesOnDesktop = true;
230	bool mountSharedVolumesOntoDesktop = false;
231
232	message->FindBool("ShowDisksIcon", &showDisksIcon);
233	message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop);
234	message->FindBool("MountSharedVolumesOntoDesktop",
235		&mountSharedVolumesOntoDesktop);
236
237	BEntry entry("/");
238	Model model(&entry);
239	if (model.InitCheck() == B_OK) {
240		BMessage entryMessage;
241		entryMessage.what = B_NODE_MONITOR;
242
243		if (showDisksIcon)
244			entryMessage.AddInt32("opcode", B_ENTRY_CREATED);
245		else {
246			entryMessage.AddInt32("opcode", B_ENTRY_REMOVED);
247			entry_ref ref;
248			if (entry.GetRef(&ref) == B_OK) {
249				BContainerWindow* disksWindow
250					= tracker->FindContainerWindow(&ref);
251				if (disksWindow != NULL) {
252					disksWindow->Lock();
253					disksWindow->Close();
254				}
255			}
256		}
257		entryMessage.AddInt32("device", model.NodeRef()->device);
258		entryMessage.AddInt64("node", model.NodeRef()->node);
259		entryMessage.AddInt64("directory", model.EntryRef()->directory);
260		entryMessage.AddString("name", model.EntryRef()->name);
261		BContainerWindow* deskWindow
262			= dynamic_cast<BContainerWindow*>(Window());
263		if (deskWindow != NULL)
264			deskWindow->PostMessage(&entryMessage, deskWindow->PoseView());
265	}
266
267	ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop);
268}
269
270
271void
272DesktopPoseView::AdaptToDesktopIntegrationChange(BMessage* message)
273{
274	bool mountVolumesOnDesktop = true;
275	bool mountSharedVolumesOntoDesktop = true;
276
277	message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop);
278	message->FindBool("MountSharedVolumesOntoDesktop",
279		&mountSharedVolumesOntoDesktop);
280
281	ShowVolumes(false, mountSharedVolumesOntoDesktop);
282	ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop);
283}
284