xref: /haiku/src/preferences/repositories/RepositoriesWindow.cpp (revision b31cb92f29fe89eaca84d173d0f70d38bf0c6a3d)
1 /*
2  * Copyright 2017 Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Brian Hill
7  */
8 
9 
10 #include "RepositoriesWindow.h"
11 
12 #include <Alert.h>
13 #include <Application.h>
14 #include <Catalog.h>
15 #include <FindDirectory.h>
16 #include <LayoutBuilder.h>
17 #include <NodeMonitor.h>
18 #include <Region.h>
19 #include <Screen.h>
20 
21 #include "AddRepoWindow.h"
22 #include "constants.h"
23 
24 
25 #undef B_TRANSLATION_CONTEXT
26 #define B_TRANSLATION_CONTEXT "RepositoriesWindow"
27 
28 
29 RepositoriesWindow::RepositoriesWindow()
30 	:
31 	BWindow(BRect(50, 50, 500, 400), B_TRANSLATE_SYSTEM_NAME("Repositories"),
32 		B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS
33 			| B_AUTO_UPDATE_SIZE_LIMITS),
34 	fAddWindow(NULL),
35 	fPackageNodeStatus(B_ERROR)
36 {
37 	fView = new RepositoriesView();
38 	BLayoutBuilder::Group<>(this, B_VERTICAL).Add(fView).End();
39 
40 	// Size and location on screen
41 	BRect frame = fSettings.GetFrame();
42 	ResizeTo(frame.Width(), frame.Height());
43 	BScreen screen;
44 	BRect screenFrame = screen.Frame();
45 	if (screenFrame.right < frame.right || screenFrame.left > frame.left
46 		|| screenFrame.top > frame.top || screenFrame.bottom < frame.bottom) {
47 		CenterOnScreen();
48 	}
49 	else
50 		MoveTo(frame.left, frame.top);
51 	Show();
52 
53 	fMessenger.SetTo(this);
54 
55 	// Find the pkgman settings or cache directory
56 	BPath packagePath;
57 	// /boot/system/settings/package-repositories
58 	status_t status = find_directory(B_SYSTEM_SETTINGS_DIRECTORY,
59 		&packagePath);
60 	if (status == B_OK)
61 		status = packagePath.Append("package-repositories");
62 	else {
63 		// /boot/system/cache/package-repositories
64 		status = find_directory(B_SYSTEM_CACHE_DIRECTORY, &packagePath);
65 		if (status == B_OK)
66 			status = packagePath.Append("package-repositories");
67 	}
68 	if (status == B_OK) {
69 		BNode packageNode(packagePath.Path());
70 		if (packageNode.InitCheck()==B_OK && packageNode.IsDirectory())
71 			fPackageNodeStatus = packageNode.GetNodeRef(&fPackageNodeRef);
72 	}
73 
74 	// watch the pkgman settings or cache directory for changes
75 	_StartWatching();
76 }
77 
78 
79 RepositoriesWindow::~RepositoriesWindow()
80 {
81 	_StopWatching();
82 }
83 
84 
85 void
86 RepositoriesWindow::_StartWatching()
87 {
88 	if (fPackageNodeStatus == B_OK) {
89 		status_t result = watch_node(&fPackageNodeRef, B_WATCH_DIRECTORY, this);
90 		fWatchingPackageNode = (result == B_OK);
91 	}
92 }
93 
94 
95 void
96 RepositoriesWindow::_StopWatching()
97 {
98 	if (fPackageNodeStatus == B_OK && fWatchingPackageNode) {
99 		watch_node(&fPackageNodeRef, B_STOP_WATCHING, this);
100 		fWatchingPackageNode = false;
101 	}
102 }
103 
104 
105 bool
106 RepositoriesWindow::QuitRequested()
107 {
108 	if (fView->IsTaskRunning()) {
109 		BAlert *alert = new BAlert("tasks",
110 			B_TRANSLATE_COMMENT("Some tasks are still running. Stop these "
111 				"tasks and quit?", "Application quit alert message"),
112 			B_TRANSLATE_COMMENT("Stop and quit", "Button label"),
113 			kCancelLabel, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
114 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
115 		int32 result = alert->Go();
116 		if (result != 0)
117 			return false;
118 	}
119 	fSettings.SetFrame(Frame());
120 	be_app->PostMessage(B_QUIT_REQUESTED);
121 	return BWindow::QuitRequested();
122 }
123 
124 
125 void
126 RepositoriesWindow::MessageReceived(BMessage* message)
127 {
128 	switch (message->what)
129 	{
130 		case ADD_REPO_WINDOW:
131 		{
132 			BRect frame = Frame();
133 			fAddWindow = new AddRepoWindow(frame, fMessenger);
134 			break;
135 		}
136 
137 		case ADD_REPO_URL:
138 		{
139 			BString url;
140 			status_t result = message->FindString(key_url, &url);
141 			if (result == B_OK)
142 				fView->AddManualRepository(url);
143 			break;
144 		}
145 
146 		case ADD_WINDOW_CLOSED:
147 		{
148 			fAddWindow = NULL;
149 			break;
150 		}
151 
152 		case DELETE_KEY_PRESSED:
153 		{
154 			BMessage message(REMOVE_REPOS);
155 			fView->MessageReceived(&message);
156 			break;
157 		}
158 
159 		// captures pkgman changes while the Repositories application is running
160 		case B_NODE_MONITOR:
161 		{
162 			// This preflet is making the changes, so ignore this message
163 			if (fView->IsTaskRunning())
164 				break;
165 
166 			int32 opcode;
167 			if (message->FindInt32("opcode", &opcode) == B_OK) {
168 				switch (opcode)
169 				{
170 					case B_ATTR_CHANGED:
171 					case B_ENTRY_CREATED:
172 					case B_ENTRY_REMOVED:
173 					{
174 						PostMessage(UPDATE_LIST, fView);
175 						break;
176 					}
177 				}
178 			}
179 			break;
180 		}
181 
182 		default:
183 			BWindow::MessageReceived(message);
184 	}
185 }
186