/*
* Copyright 2017 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Brian Hill
*/
#include "RepositoriesWindow.h"
#include <Alert.h>
#include <Application.h>
#include <Catalog.h>
#include <FindDirectory.h>
#include <LayoutBuilder.h>
#include <NodeMonitor.h>
#include <Region.h>
#include <Screen.h>
#include "AddRepoWindow.h"
#include "constants.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "RepositoriesWindow"
RepositoriesWindow::RepositoriesWindow()
:
BWindow(BRect(50, 50, 500, 400), B_TRANSLATE_SYSTEM_NAME("Repositories"),
B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS
| B_AUTO_UPDATE_SIZE_LIMITS),
fAddWindow(NULL),
fPackageNodeStatus(B_ERROR)
{
fView = new RepositoriesView();
BLayoutBuilder::Group<>(this, B_VERTICAL).Add(fView).End();
// Size and location on screen
BRect frame = fSettings.GetFrame();
ResizeTo(frame.Width(), frame.Height());
BScreen screen;
BRect screenFrame = screen.Frame();
if (screenFrame.right < frame.right || screenFrame.left > frame.left
|| screenFrame.top > frame.top || screenFrame.bottom < frame.bottom) {
CenterOnScreen();
}
else
MoveTo(frame.left, frame.top);
Show();
fMessenger.SetTo(this);
// Find the pkgman settings or cache directory
BPath packagePath;
// /boot/system/settings/package-repositories
status_t status = find_directory(B_SYSTEM_SETTINGS_DIRECTORY,
&packagePath);
if (status == B_OK)
status = packagePath.Append("package-repositories");
else {
// /boot/system/cache/package-repositories
status = find_directory(B_SYSTEM_CACHE_DIRECTORY, &packagePath);
if (status == B_OK)
status = packagePath.Append("package-repositories");
}
if (status == B_OK) {
BNode packageNode(packagePath.Path());
if (packageNode.InitCheck()==B_OK && packageNode.IsDirectory())
fPackageNodeStatus = packageNode.GetNodeRef(&fPackageNodeRef);
}
// watch the pkgman settings or cache directory for changes
_StartWatching();
}
RepositoriesWindow::~RepositoriesWindow()
{
_StopWatching();
}
void
RepositoriesWindow::_StartWatching()
{
if (fPackageNodeStatus == B_OK) {
status_t result = watch_node(&fPackageNodeRef, B_WATCH_DIRECTORY, this);
fWatchingPackageNode = (result == B_OK);
}
}
void
RepositoriesWindow::_StopWatching()
{
if (fPackageNodeStatus == B_OK && fWatchingPackageNode) {
watch_node(&fPackageNodeRef, B_STOP_WATCHING, this);
fWatchingPackageNode = false;
}
}
bool
RepositoriesWindow::QuitRequested()
{
if (fView->IsTaskRunning()) {
BAlert *alert = new BAlert("tasks",
B_TRANSLATE_COMMENT("Some tasks are still running. Stop these "
"tasks and quit?", "Application quit alert message"),
B_TRANSLATE_COMMENT("Stop and quit", "Button label"),
kCancelLabel, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
int32 result = alert->Go();
if (result != 0)
return false;
}
fSettings.SetFrame(Frame());
be_app->PostMessage(B_QUIT_REQUESTED);
return BWindow::QuitRequested();
}
void
RepositoriesWindow::MessageReceived(BMessage* message)
{
switch (message->what)
{
case ADD_REPO_WINDOW:
{
BRect frame = Frame();
fAddWindow = new AddRepoWindow(frame, fMessenger);
break;
}
case ADD_REPO_URL:
{
BString url;
status_t result = message->FindString(key_url, &url);
if (result == B_OK)
fView->AddManualRepository(url);
break;
}
case ADD_WINDOW_CLOSED:
{
fAddWindow = NULL;
break;
}
case DELETE_KEY_PRESSED:
{
BMessage message(REMOVE_REPOS);
fView->MessageReceived(&message);
break;
}
// captures pkgman changes while the Repositories application is running
case B_NODE_MONITOR:
{
// This preflet is making the changes, so ignore this message
if (fView->IsTaskRunning())
break;
int32 opcode;
if (message->FindInt32("opcode", &opcode) == B_OK) {
switch (opcode)
{
case B_ATTR_CHANGED:
case B_ENTRY_CREATED:
case B_ENTRY_REMOVED:
{
PostMessage(UPDATE_LIST, fView);
break;
}
}
}
break;
}
default:
BWindow::MessageReceived(message);
}
}
↑ V773 The function was exited without releasing the 'alert' pointer. A memory leak is possible.