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