xref: /haiku/src/preferences/repositories/RepositoriesView.cpp (revision 3e967b3fb4dc0f27038754cd092b2803af35bbef)
15bf2b6ebSBrian Hill /*
25bf2b6ebSBrian Hill  * Copyright 2017 Haiku Inc. All rights reserved.
35bf2b6ebSBrian Hill  * Distributed under the terms of the MIT License.
45bf2b6ebSBrian Hill  *
55bf2b6ebSBrian Hill  * Authors:
65bf2b6ebSBrian Hill  *		Brian Hill
75bf2b6ebSBrian Hill  */
85bf2b6ebSBrian Hill 
95bf2b6ebSBrian Hill 
105bf2b6ebSBrian Hill #include "RepositoriesView.h"
115bf2b6ebSBrian Hill 
125bf2b6ebSBrian Hill #include <stdlib.h>
135bf2b6ebSBrian Hill #include <Alert.h>
145bf2b6ebSBrian Hill #include <Button.h>
155bf2b6ebSBrian Hill #include <Catalog.h>
165bf2b6ebSBrian Hill #include <ColumnTypes.h>
175bf2b6ebSBrian Hill #include <LayoutBuilder.h>
185bf2b6ebSBrian Hill #include <MessageRunner.h>
195bf2b6ebSBrian Hill #include <ScrollBar.h>
205bf2b6ebSBrian Hill #include <SeparatorView.h>
21856ecc7bSBrian Hill #include <Url.h>
225bf2b6ebSBrian Hill #include <package/PackageRoster.h>
235bf2b6ebSBrian Hill #include <package/RepositoryConfig.h>
245bf2b6ebSBrian Hill 
255bf2b6ebSBrian Hill #include "constants.h"
265bf2b6ebSBrian Hill 
275bf2b6ebSBrian Hill #undef B_TRANSLATION_CONTEXT
285bf2b6ebSBrian Hill #define B_TRANSLATION_CONTEXT "RepositoriesView"
295bf2b6ebSBrian Hill 
305bf2b6ebSBrian Hill 
315bf2b6ebSBrian Hill static const BString kTitleEnabled =
3269478e07SBrian Hill 	B_TRANSLATE_COMMENT("Status", "Column title");
335bf2b6ebSBrian Hill static const BString kTitleName = B_TRANSLATE_COMMENT("Name", "Column title");
345bf2b6ebSBrian Hill static const BString kTitleUrl = B_TRANSLATE_COMMENT("URL", "Column title");
355bf2b6ebSBrian Hill static const BString kLabelRemove =
365bf2b6ebSBrian Hill 	B_TRANSLATE_COMMENT("Remove", "Button label");
375bf2b6ebSBrian Hill static const BString kLabelRemoveAll =
385bf2b6ebSBrian Hill 	B_TRANSLATE_COMMENT("Remove All", "Button label");
395bf2b6ebSBrian Hill static const BString kLabelEnable =
405bf2b6ebSBrian Hill 	B_TRANSLATE_COMMENT("Enable", "Button label");
415bf2b6ebSBrian Hill static const BString kLabelEnableAll =
425bf2b6ebSBrian Hill 	B_TRANSLATE_COMMENT("Enable All", "Button label");
435bf2b6ebSBrian Hill static const BString kLabelDisable =
445bf2b6ebSBrian Hill 	B_TRANSLATE_COMMENT("Disable", "Button label");
455bf2b6ebSBrian Hill static const BString kLabelDisableAll =
465bf2b6ebSBrian Hill 	B_TRANSLATE_COMMENT("Disable All", "Button label");
475bf2b6ebSBrian Hill static const BString kStatusViewText =
485bf2b6ebSBrian Hill 	B_TRANSLATE_COMMENT("Changes pending:", "Status view text");
495bf2b6ebSBrian Hill static const BString kStatusCompletedText =
505bf2b6ebSBrian Hill 	B_TRANSLATE_COMMENT("Changes completed", "Status view text");
515bf2b6ebSBrian Hill 
525bf2b6ebSBrian Hill 
535bf2b6ebSBrian Hill RepositoriesListView::RepositoriesListView(const char* name)
545bf2b6ebSBrian Hill 	:
555bf2b6ebSBrian Hill 	BColumnListView(name, B_NAVIGABLE, B_PLAIN_BORDER)
565bf2b6ebSBrian Hill {
575bf2b6ebSBrian Hill }
585bf2b6ebSBrian Hill 
595bf2b6ebSBrian Hill 
605bf2b6ebSBrian Hill void
615bf2b6ebSBrian Hill RepositoriesListView::KeyDown(const char* bytes, int32 numBytes)
625bf2b6ebSBrian Hill {
635bf2b6ebSBrian Hill 	switch (bytes[0]) {
645bf2b6ebSBrian Hill 		case B_DELETE:
655bf2b6ebSBrian Hill 			Window()->PostMessage(DELETE_KEY_PRESSED);
665bf2b6ebSBrian Hill 			break;
675bf2b6ebSBrian Hill 
685bf2b6ebSBrian Hill 		default:
695bf2b6ebSBrian Hill 			BColumnListView::KeyDown(bytes, numBytes);
705bf2b6ebSBrian Hill 	}
715bf2b6ebSBrian Hill }
725bf2b6ebSBrian Hill 
735bf2b6ebSBrian Hill 
745bf2b6ebSBrian Hill RepositoriesView::RepositoriesView()
755bf2b6ebSBrian Hill 	:
765bf2b6ebSBrian Hill 	BGroupView("RepositoriesView"),
775bf2b6ebSBrian Hill 	fTaskLooper(NULL),
785bf2b6ebSBrian Hill 	fShowCompletedStatus(false),
795bf2b6ebSBrian Hill 	fRunningTaskCount(0),
805bf2b6ebSBrian Hill 	fLastCompletedTimerId(0)
815bf2b6ebSBrian Hill {
825bf2b6ebSBrian Hill 	// Column list view with 3 columns
835bf2b6ebSBrian Hill 	fListView = new RepositoriesListView("list");
845bf2b6ebSBrian Hill 	fListView->SetSelectionMessage(new BMessage(LIST_SELECTION_CHANGED));
855bf2b6ebSBrian Hill 	float col0width = be_plain_font->StringWidth(kTitleEnabled) + 15;
865bf2b6ebSBrian Hill 	float col1width = be_plain_font->StringWidth(kTitleName) + 15;
875bf2b6ebSBrian Hill 	float col2width = be_plain_font->StringWidth(kTitleUrl) + 15;
885bf2b6ebSBrian Hill 	fListView->AddColumn(new BStringColumn(kTitleEnabled, col0width, col0width,
8969478e07SBrian Hill 		2 * col0width, B_TRUNCATE_END), kEnabledColumn);
905bf2b6ebSBrian Hill 	fListView->AddColumn(new BStringColumn(kTitleName, 90, col1width, 300,
915bf2b6ebSBrian Hill 		B_TRUNCATE_END), kNameColumn);
925bf2b6ebSBrian Hill 	fListView->AddColumn(new BStringColumn(kTitleUrl, 500, col2width, 5000,
935bf2b6ebSBrian Hill 		B_TRUNCATE_END), kUrlColumn);
945bf2b6ebSBrian Hill 	fListView->SetInvocationMessage(new BMessage(ITEM_INVOKED));
955bf2b6ebSBrian Hill 
965bf2b6ebSBrian Hill 	// Repository list status view
975bf2b6ebSBrian Hill 	fStatusContainerView = new BView("status", B_SUPPORTS_LAYOUT);
985bf2b6ebSBrian Hill 	BString templateText(kStatusViewText);
995bf2b6ebSBrian Hill 	templateText.Append(" 88");
1005bf2b6ebSBrian Hill 		// Simulate a status text with two digit queue count
1015bf2b6ebSBrian Hill 	fListStatusView = new BStringView("status", templateText);
1025bf2b6ebSBrian Hill 
1035bf2b6ebSBrian Hill 	// Set a smaller fixed font size and slightly lighten text color
1045bf2b6ebSBrian Hill 	BFont font(be_plain_font);
1055bf2b6ebSBrian Hill 	font.SetSize(10.0f);
1065bf2b6ebSBrian Hill 	fListStatusView->SetFont(&font, B_FONT_SIZE);
1075bf2b6ebSBrian Hill 	fListStatusView->SetHighUIColor(fListStatusView->HighUIColor(), .9f);
1085bf2b6ebSBrian Hill 
1095bf2b6ebSBrian Hill 	// Set appropriate explicit view sizes
1101aacfd69SAugustin Cavalier 	float viewWidth = std::max(fListStatusView->StringWidth(templateText),
1115bf2b6ebSBrian Hill 		fListStatusView->StringWidth(kStatusCompletedText));
1125bf2b6ebSBrian Hill 	BSize statusViewSize(viewWidth + 3, B_H_SCROLL_BAR_HEIGHT - 2);
1135bf2b6ebSBrian Hill 	fListStatusView->SetExplicitSize(statusViewSize);
1145bf2b6ebSBrian Hill 	statusViewSize.height += 1;
1155bf2b6ebSBrian Hill 	fStatusContainerView->SetExplicitSize(statusViewSize);
1165bf2b6ebSBrian Hill 	BLayoutBuilder::Group<>(fStatusContainerView, B_HORIZONTAL, 0)
1175bf2b6ebSBrian Hill 		.Add(new BSeparatorView(B_VERTICAL))
1185bf2b6ebSBrian Hill 		.AddGroup(B_VERTICAL, 0)
1195bf2b6ebSBrian Hill 			.AddGlue()
1205bf2b6ebSBrian Hill 			.AddGroup(B_HORIZONTAL, 0)
1215bf2b6ebSBrian Hill 				.SetInsets(2, 0, 0, 0)
1225bf2b6ebSBrian Hill 				.Add(fListStatusView)
1235bf2b6ebSBrian Hill 				.AddGlue()
1245bf2b6ebSBrian Hill 			.End()
1255bf2b6ebSBrian Hill 			.Add(new BSeparatorView(B_HORIZONTAL))
1265bf2b6ebSBrian Hill 		.End()
1275bf2b6ebSBrian Hill 	.End();
1285bf2b6ebSBrian Hill 	fListView->AddStatusView(fStatusContainerView);
1295bf2b6ebSBrian Hill 
1305bf2b6ebSBrian Hill 	// Standard buttons
1315bf2b6ebSBrian Hill 	fEnableButton = new BButton(kLabelEnable,
1325bf2b6ebSBrian Hill 		new BMessage(ENABLE_BUTTON_PRESSED));
1335bf2b6ebSBrian Hill 	fDisableButton = new BButton(kLabelDisable,
1345bf2b6ebSBrian Hill 		new BMessage(DISABLE_BUTTON_PRESSED));
1355bf2b6ebSBrian Hill 
1365bf2b6ebSBrian Hill 	// Create buttons with fixed size
1375bf2b6ebSBrian Hill 	font_height fontHeight;
1385bf2b6ebSBrian Hill 	GetFontHeight(&fontHeight);
1395bf2b6ebSBrian Hill 	int16 buttonHeight = int16(fontHeight.ascent + fontHeight.descent + 12);
1405bf2b6ebSBrian Hill 		// button size determined by font size
1415bf2b6ebSBrian Hill 	BSize btnSize(buttonHeight, buttonHeight);
1425bf2b6ebSBrian Hill 
1435bf2b6ebSBrian Hill 	fAddButton = new BButton("plus", "+", new BMessage(ADD_REPO_WINDOW));
1445bf2b6ebSBrian Hill 	fAddButton->SetExplicitSize(btnSize);
1455bf2b6ebSBrian Hill 	fRemoveButton = new BButton("minus", "-", new BMessage(REMOVE_REPOS));
1465bf2b6ebSBrian Hill 	fRemoveButton->SetExplicitSize(btnSize);
1475bf2b6ebSBrian Hill 
1485bf2b6ebSBrian Hill 	// Layout
1495bf2b6ebSBrian Hill 	int16 buttonSpacing = 1;
1505bf2b6ebSBrian Hill 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
1515bf2b6ebSBrian Hill 		.SetInsets(B_USE_WINDOW_SPACING)
1525bf2b6ebSBrian Hill 		.AddGroup(B_HORIZONTAL, 0, 0.0)
1535f020e71SAnirudh M 			.Add(new BStringView("instruction", B_TRANSLATE_COMMENT("Enable"
1545f020e71SAnirudh M 				" repositories to use with package management:",
1555bf2b6ebSBrian Hill 				"Label text")), 0.0)
1565bf2b6ebSBrian Hill 			.AddGlue()
1575bf2b6ebSBrian Hill 		.End()
1585bf2b6ebSBrian Hill 		.AddStrut(B_USE_DEFAULT_SPACING)
1595bf2b6ebSBrian Hill 		.Add(fListView, 1)
1605bf2b6ebSBrian Hill 		.AddGroup(B_HORIZONTAL, 0, 0.0)
1615bf2b6ebSBrian Hill 			// Add and Remove buttons
1625bf2b6ebSBrian Hill 			.AddGroup(B_VERTICAL, 0, 0.0)
1635bf2b6ebSBrian Hill 				.AddGroup(B_HORIZONTAL, 0, 0.0)
1645bf2b6ebSBrian Hill 					.Add(new BSeparatorView(B_VERTICAL))
1655bf2b6ebSBrian Hill 					.AddGroup(B_VERTICAL, 0, 0.0)
1665bf2b6ebSBrian Hill 						.AddGroup(B_HORIZONTAL, buttonSpacing, 0.0)
1675bf2b6ebSBrian Hill 							.SetInsets(buttonSpacing)
1685bf2b6ebSBrian Hill 							.Add(fAddButton)
1695bf2b6ebSBrian Hill 							.Add(fRemoveButton)
1705bf2b6ebSBrian Hill 						.End()
1715bf2b6ebSBrian Hill 						.Add(new BSeparatorView(B_HORIZONTAL))
1725bf2b6ebSBrian Hill 					.End()
1735bf2b6ebSBrian Hill 					.Add(new BSeparatorView(B_VERTICAL))
1745bf2b6ebSBrian Hill 				.End()
1755bf2b6ebSBrian Hill 				.AddGlue()
1765bf2b6ebSBrian Hill 			.End()
1775bf2b6ebSBrian Hill 			// Enable and Disable buttons
1785bf2b6ebSBrian Hill 			.AddGroup(B_HORIZONTAL)
1795bf2b6ebSBrian Hill 				.SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
1805bf2b6ebSBrian Hill 					B_USE_DEFAULT_SPACING, 0)
1815bf2b6ebSBrian Hill 				.AddGlue()
1825bf2b6ebSBrian Hill 				.Add(fEnableButton)
1835bf2b6ebSBrian Hill 				.Add(fDisableButton)
1845bf2b6ebSBrian Hill 			.End()
1855bf2b6ebSBrian Hill 		.End()
1865bf2b6ebSBrian Hill 	.End();
1875bf2b6ebSBrian Hill }
1885bf2b6ebSBrian Hill 
1895bf2b6ebSBrian Hill 
1905bf2b6ebSBrian Hill RepositoriesView::~RepositoriesView()
1915bf2b6ebSBrian Hill {
1925bf2b6ebSBrian Hill 	if (fTaskLooper) {
1935bf2b6ebSBrian Hill 		fTaskLooper->Lock();
1945bf2b6ebSBrian Hill 		fTaskLooper->Quit();
1955bf2b6ebSBrian Hill 	}
1965bf2b6ebSBrian Hill 	_EmptyList();
1975bf2b6ebSBrian Hill }
1985bf2b6ebSBrian Hill 
1995bf2b6ebSBrian Hill 
2005bf2b6ebSBrian Hill void
2015bf2b6ebSBrian Hill RepositoriesView::AllAttached()
2025bf2b6ebSBrian Hill {
2035bf2b6ebSBrian Hill 	BView::AllAttached();
2045bf2b6ebSBrian Hill 	fRemoveButton->SetTarget(this);
2055bf2b6ebSBrian Hill 	fEnableButton->SetTarget(this);
2065bf2b6ebSBrian Hill 	fDisableButton->SetTarget(this);
2075bf2b6ebSBrian Hill 	fListView->SetTarget(this);
2085bf2b6ebSBrian Hill 	fRemoveButton->SetEnabled(false);
2095bf2b6ebSBrian Hill 	fEnableButton->SetEnabled(false);
2105bf2b6ebSBrian Hill 	fDisableButton->SetEnabled(false);
2115bf2b6ebSBrian Hill 	_UpdateStatusView();
2125bf2b6ebSBrian Hill 	_InitList();
2135bf2b6ebSBrian Hill }
2145bf2b6ebSBrian Hill 
2155bf2b6ebSBrian Hill 
2165bf2b6ebSBrian Hill void
2175bf2b6ebSBrian Hill RepositoriesView::AttachedToWindow()
2185bf2b6ebSBrian Hill {
2195bf2b6ebSBrian Hill 	fTaskLooper = new TaskLooper(BMessenger(this));
2205bf2b6ebSBrian Hill }
2215bf2b6ebSBrian Hill 
2225bf2b6ebSBrian Hill 
2235bf2b6ebSBrian Hill void
2245bf2b6ebSBrian Hill RepositoriesView::MessageReceived(BMessage* message)
2255bf2b6ebSBrian Hill {
2265bf2b6ebSBrian Hill 	switch (message->what)
2275bf2b6ebSBrian Hill 	{
228856ecc7bSBrian Hill 		case REMOVE_REPOS:
229856ecc7bSBrian Hill 		{
2305bf2b6ebSBrian Hill 			RepoRow* rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection());
2315bf2b6ebSBrian Hill 			if (!rowItem || !fRemoveButton->IsEnabled())
2325bf2b6ebSBrian Hill 				break;
2335bf2b6ebSBrian Hill 
2345bf2b6ebSBrian Hill 			BString text;
2355bf2b6ebSBrian Hill 			// More than one selected row
2365bf2b6ebSBrian Hill 			if (fListView->CurrentSelection(rowItem)) {
2375bf2b6ebSBrian Hill 				text.SetTo(B_TRANSLATE_COMMENT("Remove these repositories?",
2385bf2b6ebSBrian Hill 					"Removal alert confirmation message"));
2395bf2b6ebSBrian Hill 				text.Append("\n");
2405bf2b6ebSBrian Hill 			}
2415bf2b6ebSBrian Hill 			// Only one selected row
2425bf2b6ebSBrian Hill 			else {
2435bf2b6ebSBrian Hill 				text.SetTo(B_TRANSLATE_COMMENT("Remove this repository?",
2445bf2b6ebSBrian Hill 					"Removal alert confirmation message"));
2455bf2b6ebSBrian Hill 				text.Append("\n");
2465bf2b6ebSBrian Hill 			}
2475bf2b6ebSBrian Hill 			float minWidth = 0;
2485bf2b6ebSBrian Hill 			while (rowItem) {
2495bf2b6ebSBrian Hill 				BString repoText;
2505bf2b6ebSBrian Hill 				repoText.Append("\n").Append(rowItem->Name())
2515bf2b6ebSBrian Hill 					.Append(" (").Append(rowItem->Url()).Append(")");
2521aacfd69SAugustin Cavalier 				minWidth = std::max(minWidth, StringWidth(repoText.String()));
2535bf2b6ebSBrian Hill 				text.Append(repoText);
2545bf2b6ebSBrian Hill 				rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection(rowItem));
2555bf2b6ebSBrian Hill 			}
2561aacfd69SAugustin Cavalier 			minWidth = std::min(minWidth, Frame().Width());
2575bf2b6ebSBrian Hill 				// Ensure alert window isn't much larger than the main window
2585bf2b6ebSBrian Hill 			BAlert* alert = new BAlert("confirm", text, kRemoveLabel,
2595bf2b6ebSBrian Hill 				kCancelLabel, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
2605bf2b6ebSBrian Hill 			alert->TextView()->SetExplicitMinSize(BSize(minWidth, B_SIZE_UNSET));
2615bf2b6ebSBrian Hill 			alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
2625bf2b6ebSBrian Hill 			int32 answer = alert->Go();
2635bf2b6ebSBrian Hill 			// User presses Cancel button
2645bf2b6ebSBrian Hill 			if (answer)
2655bf2b6ebSBrian Hill 				break;
2665bf2b6ebSBrian Hill 
2675bf2b6ebSBrian Hill 			rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection());
2685bf2b6ebSBrian Hill 			while (rowItem) {
2695bf2b6ebSBrian Hill 				RepoRow* oldRow = rowItem;
2705bf2b6ebSBrian Hill 				rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection(rowItem));
2715bf2b6ebSBrian Hill 				fListView->RemoveRow(oldRow);
2725bf2b6ebSBrian Hill 				delete oldRow;
2735bf2b6ebSBrian Hill 			}
2745bf2b6ebSBrian Hill 			_SaveList();
2755bf2b6ebSBrian Hill 			break;
2765bf2b6ebSBrian Hill 		}
277856ecc7bSBrian Hill 
2785bf2b6ebSBrian Hill 		case LIST_SELECTION_CHANGED:
2795bf2b6ebSBrian Hill 			_UpdateButtons();
2805bf2b6ebSBrian Hill 			break;
2815bf2b6ebSBrian Hill 
282856ecc7bSBrian Hill 		case ITEM_INVOKED:
283856ecc7bSBrian Hill 		{
2845bf2b6ebSBrian Hill 			// Simulates pressing whichever is the enabled button
2855bf2b6ebSBrian Hill 			if (fEnableButton->IsEnabled()) {
2865bf2b6ebSBrian Hill 				BMessage invokeMessage(ENABLE_BUTTON_PRESSED);
2875bf2b6ebSBrian Hill 				MessageReceived(&invokeMessage);
2885bf2b6ebSBrian Hill 			} else if (fDisableButton->IsEnabled()) {
2895bf2b6ebSBrian Hill 				BMessage invokeMessage(DISABLE_BUTTON_PRESSED);
2905bf2b6ebSBrian Hill 				MessageReceived(&invokeMessage);
2915bf2b6ebSBrian Hill 			}
2925bf2b6ebSBrian Hill 			break;
2935bf2b6ebSBrian Hill 		}
294856ecc7bSBrian Hill 
295856ecc7bSBrian Hill 		case ENABLE_BUTTON_PRESSED:
296856ecc7bSBrian Hill 		{
2975bf2b6ebSBrian Hill 			BStringList names;
2985bf2b6ebSBrian Hill 			bool paramsOK = true;
2995bf2b6ebSBrian Hill 			// Check if there are multiple selections of the same repository,
3005bf2b6ebSBrian Hill 			// pkgman won't like that
3015bf2b6ebSBrian Hill 			RepoRow* rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection());
3025bf2b6ebSBrian Hill 			while (rowItem) {
3035bf2b6ebSBrian Hill 				if (names.HasString(rowItem->Name())
3045bf2b6ebSBrian Hill 					&& kNewRepoDefaultName.Compare(rowItem->Name()) != 0) {
3055bf2b6ebSBrian Hill 					(new BAlert("duplicate",
3065bf2b6ebSBrian Hill 						B_TRANSLATE_COMMENT("Only one URL for each repository can "
3075bf2b6ebSBrian Hill 							"be enabled.  Please change your selections.",
3085bf2b6ebSBrian Hill 							"Error message"),
3095bf2b6ebSBrian Hill 						kOKLabel, NULL, NULL,
3105bf2b6ebSBrian Hill 						B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go(NULL);
3115bf2b6ebSBrian Hill 					paramsOK = false;
3125bf2b6ebSBrian Hill 					break;
3135bf2b6ebSBrian Hill 				} else
3145bf2b6ebSBrian Hill 					names.Add(rowItem->Name());
3155bf2b6ebSBrian Hill 				rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection(rowItem));
3165bf2b6ebSBrian Hill 			}
3175bf2b6ebSBrian Hill 			if (paramsOK) {
3185bf2b6ebSBrian Hill 				_AddSelectedRowsToQueue();
3195bf2b6ebSBrian Hill 				_UpdateButtons();
3205bf2b6ebSBrian Hill 			}
3215bf2b6ebSBrian Hill 			break;
3225bf2b6ebSBrian Hill 		}
323856ecc7bSBrian Hill 
3245bf2b6ebSBrian Hill 		case DISABLE_BUTTON_PRESSED:
3255bf2b6ebSBrian Hill 			_AddSelectedRowsToQueue();
3265bf2b6ebSBrian Hill 			_UpdateButtons();
3275bf2b6ebSBrian Hill 			break;
3285bf2b6ebSBrian Hill 
329856ecc7bSBrian Hill 		case TASK_STARTED:
330856ecc7bSBrian Hill 		{
3315bf2b6ebSBrian Hill 			int16 count;
3325bf2b6ebSBrian Hill 			status_t result1 = message->FindInt16(key_count, &count);
3335bf2b6ebSBrian Hill 			RepoRow* rowItem;
3345bf2b6ebSBrian Hill 			status_t result2 = message->FindPointer(key_rowptr, (void**)&rowItem);
3355bf2b6ebSBrian Hill 			if (result1 == B_OK && result2 == B_OK)
3365bf2b6ebSBrian Hill 				_TaskStarted(rowItem, count);
3375bf2b6ebSBrian Hill 			break;
3385bf2b6ebSBrian Hill 		}
339856ecc7bSBrian Hill 
340856ecc7bSBrian Hill 		case TASK_COMPLETED_WITH_ERRORS:
341856ecc7bSBrian Hill 		{
3425bf2b6ebSBrian Hill 			BString errorDetails;
3435bf2b6ebSBrian Hill 			status_t result = message->FindString(key_details, &errorDetails);
3445bf2b6ebSBrian Hill 			if (result == B_OK) {
3455bf2b6ebSBrian Hill 				(new BAlert("error", errorDetails, kOKLabel, NULL, NULL,
3465bf2b6ebSBrian Hill 					B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go(NULL);
3475bf2b6ebSBrian Hill 			}
3485bf2b6ebSBrian Hill 			BString repoName = message->GetString(key_name,
3495bf2b6ebSBrian Hill 				kNewRepoDefaultName.String());
3505bf2b6ebSBrian Hill 			int16 count;
3515bf2b6ebSBrian Hill 			status_t result1 = message->FindInt16(key_count, &count);
3525bf2b6ebSBrian Hill 			RepoRow* rowItem;
3535bf2b6ebSBrian Hill 			status_t result2 = message->FindPointer(key_rowptr, (void**)&rowItem);
3545bf2b6ebSBrian Hill 			if (result1 == B_OK && result2 == B_OK) {
3555bf2b6ebSBrian Hill 				_TaskCompleted(rowItem, count, repoName);
3565bf2b6ebSBrian Hill 				// Refresh the enabled status of each row since it is unsure what
3575bf2b6ebSBrian Hill 				// caused the error
3585bf2b6ebSBrian Hill 				_RefreshList();
3595bf2b6ebSBrian Hill 			}
3605bf2b6ebSBrian Hill 			_UpdateButtons();
3615bf2b6ebSBrian Hill 			break;
3625bf2b6ebSBrian Hill 		}
363856ecc7bSBrian Hill 
364856ecc7bSBrian Hill 		case TASK_COMPLETED:
365856ecc7bSBrian Hill 		{
3665bf2b6ebSBrian Hill 			BString repoName = message->GetString(key_name,
3675bf2b6ebSBrian Hill 				kNewRepoDefaultName.String());
3685bf2b6ebSBrian Hill 			int16 count;
3695bf2b6ebSBrian Hill 			status_t result1 = message->FindInt16(key_count, &count);
3705bf2b6ebSBrian Hill 			RepoRow* rowItem;
3715bf2b6ebSBrian Hill 			status_t result2 = message->FindPointer(key_rowptr, (void**)&rowItem);
3725bf2b6ebSBrian Hill 			if (result1 == B_OK && result2 == B_OK) {
3735bf2b6ebSBrian Hill 				_TaskCompleted(rowItem, count, repoName);
3745bf2b6ebSBrian Hill 				// If the completed row has siblings then enabling this row may
3755bf2b6ebSBrian Hill 				// have disabled one of the other siblings, do full refresh.
3765bf2b6ebSBrian Hill 				if (rowItem->HasSiblings() && rowItem->IsEnabled())
3775bf2b6ebSBrian Hill 					_RefreshList();
3785bf2b6ebSBrian Hill 			}
3795bf2b6ebSBrian Hill 			_UpdateButtons();
3805bf2b6ebSBrian Hill 			break;
3815bf2b6ebSBrian Hill 		}
382856ecc7bSBrian Hill 
383856ecc7bSBrian Hill 		case TASK_CANCELED:
384856ecc7bSBrian Hill 		{
3855bf2b6ebSBrian Hill 			int16 count;
3865bf2b6ebSBrian Hill 			status_t result1 = message->FindInt16(key_count, &count);
3875bf2b6ebSBrian Hill 			RepoRow* rowItem;
3885bf2b6ebSBrian Hill 			status_t result2 = message->FindPointer(key_rowptr, (void**)&rowItem);
3895bf2b6ebSBrian Hill 			if (result1 == B_OK && result2 == B_OK)
3905bf2b6ebSBrian Hill 				_TaskCanceled(rowItem, count);
3915bf2b6ebSBrian Hill 			// Refresh the enabled status of each row since it is unsure what
3925bf2b6ebSBrian Hill 			// caused the cancelation
3935bf2b6ebSBrian Hill 			_RefreshList();
3945bf2b6ebSBrian Hill 			_UpdateButtons();
3955bf2b6ebSBrian Hill 			break;
3965bf2b6ebSBrian Hill 		}
397856ecc7bSBrian Hill 
3985bf2b6ebSBrian Hill 		case UPDATE_LIST:
3995bf2b6ebSBrian Hill 			_RefreshList();
4005bf2b6ebSBrian Hill 			_UpdateButtons();
4015bf2b6ebSBrian Hill 			break;
4025bf2b6ebSBrian Hill 
403856ecc7bSBrian Hill 		case STATUS_VIEW_COMPLETED_TIMEOUT:
404856ecc7bSBrian Hill 		{
4055bf2b6ebSBrian Hill 			int32 timerID;
4065bf2b6ebSBrian Hill 			status_t result = message->FindInt32(key_ID, &timerID);
4075bf2b6ebSBrian Hill 			if (result == B_OK && timerID == fLastCompletedTimerId)
4085bf2b6ebSBrian Hill 				_UpdateStatusView();
4095bf2b6ebSBrian Hill 			break;
4105bf2b6ebSBrian Hill 		}
411856ecc7bSBrian Hill 
4125bf2b6ebSBrian Hill 		default:
4135bf2b6ebSBrian Hill 			BView::MessageReceived(message);
4145bf2b6ebSBrian Hill 	}
4155bf2b6ebSBrian Hill }
4165bf2b6ebSBrian Hill 
4175bf2b6ebSBrian Hill 
4185bf2b6ebSBrian Hill void
4195bf2b6ebSBrian Hill RepositoriesView::_AddSelectedRowsToQueue()
4205bf2b6ebSBrian Hill {
4215bf2b6ebSBrian Hill 	RepoRow* rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection());
4225bf2b6ebSBrian Hill 	while (rowItem) {
4235bf2b6ebSBrian Hill 		rowItem->SetTaskState(STATE_IN_QUEUE_WAITING);
4245bf2b6ebSBrian Hill 		BMessage taskMessage(DO_TASK);
4255bf2b6ebSBrian Hill 		taskMessage.AddPointer(key_rowptr, rowItem);
4265bf2b6ebSBrian Hill 		fTaskLooper->PostMessage(&taskMessage);
4275bf2b6ebSBrian Hill 		rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection(rowItem));
4285bf2b6ebSBrian Hill 	}
4295bf2b6ebSBrian Hill }
4305bf2b6ebSBrian Hill 
4315bf2b6ebSBrian Hill 
4325bf2b6ebSBrian Hill void
4335bf2b6ebSBrian Hill RepositoriesView::_TaskStarted(RepoRow* rowItem, int16 count)
4345bf2b6ebSBrian Hill {
4355bf2b6ebSBrian Hill 	fRunningTaskCount = count;
4365bf2b6ebSBrian Hill 	rowItem->SetTaskState(STATE_IN_QUEUE_RUNNING);
4375bf2b6ebSBrian Hill 	// Only present a status count if there is more than one task in queue
4385bf2b6ebSBrian Hill 	if (count > 1) {
4395bf2b6ebSBrian Hill 		_UpdateStatusView();
4405bf2b6ebSBrian Hill 		fShowCompletedStatus = true;
4415bf2b6ebSBrian Hill 	}
4425bf2b6ebSBrian Hill }
4435bf2b6ebSBrian Hill 
4445bf2b6ebSBrian Hill 
4455bf2b6ebSBrian Hill void
4465bf2b6ebSBrian Hill RepositoriesView::_TaskCompleted(RepoRow* rowItem, int16 count, BString& newName)
4475bf2b6ebSBrian Hill {
4485bf2b6ebSBrian Hill 	fRunningTaskCount = count;
4495bf2b6ebSBrian Hill 	_ShowCompletedStatusIfDone();
4505bf2b6ebSBrian Hill 
4515bf2b6ebSBrian Hill 	// Update row state and values
4525bf2b6ebSBrian Hill 	rowItem->SetTaskState(STATE_NOT_IN_QUEUE);
4535bf2b6ebSBrian Hill 	if (kNewRepoDefaultName.Compare(rowItem->Name()) == 0
454856ecc7bSBrian Hill 		&& newName.Compare("") != 0) {
4555bf2b6ebSBrian Hill 		rowItem->SetName(newName.String());
456*3e967b3fSBrian Hill 		_SaveList();
457856ecc7bSBrian Hill 	}
4585bf2b6ebSBrian Hill 	_UpdateFromRepoConfig(rowItem);
4595bf2b6ebSBrian Hill }
4605bf2b6ebSBrian Hill 
4615bf2b6ebSBrian Hill 
4625bf2b6ebSBrian Hill void
4635bf2b6ebSBrian Hill RepositoriesView::_TaskCanceled(RepoRow* rowItem, int16 count)
4645bf2b6ebSBrian Hill {
4655bf2b6ebSBrian Hill 	fRunningTaskCount = count;
4665bf2b6ebSBrian Hill 	_ShowCompletedStatusIfDone();
4675bf2b6ebSBrian Hill 
4685bf2b6ebSBrian Hill 	// Update row state and values
4695bf2b6ebSBrian Hill 	rowItem->SetTaskState(STATE_NOT_IN_QUEUE);
4705bf2b6ebSBrian Hill 	_UpdateFromRepoConfig(rowItem);
4715bf2b6ebSBrian Hill }
4725bf2b6ebSBrian Hill 
4735bf2b6ebSBrian Hill 
4745bf2b6ebSBrian Hill void
4755bf2b6ebSBrian Hill RepositoriesView::_ShowCompletedStatusIfDone()
4765bf2b6ebSBrian Hill {
4775bf2b6ebSBrian Hill 	// If this is the last task show completed status text for 3 seconds
4785bf2b6ebSBrian Hill 	if (fRunningTaskCount == 0 && fShowCompletedStatus) {
4795bf2b6ebSBrian Hill 		fListStatusView->SetText(kStatusCompletedText);
4805bf2b6ebSBrian Hill 		fLastCompletedTimerId = rand();
4815bf2b6ebSBrian Hill 		BMessage timerMessage(STATUS_VIEW_COMPLETED_TIMEOUT);
4825bf2b6ebSBrian Hill 		timerMessage.AddInt32(key_ID, fLastCompletedTimerId);
4835bf2b6ebSBrian Hill 		new BMessageRunner(this, &timerMessage, 3000000, 1);
4845bf2b6ebSBrian Hill 		fShowCompletedStatus = false;
4855bf2b6ebSBrian Hill 	} else
4865bf2b6ebSBrian Hill 		_UpdateStatusView();
4875bf2b6ebSBrian Hill }
4885bf2b6ebSBrian Hill 
4895bf2b6ebSBrian Hill 
4905bf2b6ebSBrian Hill void
4915bf2b6ebSBrian Hill RepositoriesView::_UpdateFromRepoConfig(RepoRow* rowItem)
4925bf2b6ebSBrian Hill {
4935bf2b6ebSBrian Hill 	BPackageKit::BPackageRoster pRoster;
4945bf2b6ebSBrian Hill 	BPackageKit::BRepositoryConfig repoConfig;
4955bf2b6ebSBrian Hill 	BString repoName(rowItem->Name());
4965bf2b6ebSBrian Hill 	status_t result = pRoster.GetRepositoryConfig(repoName, &repoConfig);
4975bf2b6ebSBrian Hill 	// Repo name was found and the URL matches
4985bf2b6ebSBrian Hill 	if (result == B_OK && repoConfig.BaseURL() == rowItem->Url())
4995bf2b6ebSBrian Hill 		rowItem->SetEnabled(true);
5005bf2b6ebSBrian Hill 	else
5015bf2b6ebSBrian Hill 		rowItem->SetEnabled(false);
5025bf2b6ebSBrian Hill }
5035bf2b6ebSBrian Hill 
5045bf2b6ebSBrian Hill 
5055bf2b6ebSBrian Hill void
5065bf2b6ebSBrian Hill RepositoriesView::AddManualRepository(BString url)
5075bf2b6ebSBrian Hill {
508856ecc7bSBrian Hill 	BUrl newRepoUrl(url);
509856ecc7bSBrian Hill 	if (!newRepoUrl.IsValid())
510856ecc7bSBrian Hill 		return;
511856ecc7bSBrian Hill 
5125bf2b6ebSBrian Hill 	BString name(kNewRepoDefaultName);
5135bf2b6ebSBrian Hill 	int32 index;
5145bf2b6ebSBrian Hill 	int32 listCount = fListView->CountRows();
5155bf2b6ebSBrian Hill 	for (index = 0; index < listCount; index++) {
5165bf2b6ebSBrian Hill 		RepoRow* repoItem = dynamic_cast<RepoRow*>(fListView->RowAt(index));
517856ecc7bSBrian Hill 		BUrl rowRepoUrl(repoItem->Url());
5185bf2b6ebSBrian Hill 		// Find an already existing URL
519856ecc7bSBrian Hill 		if (newRepoUrl == rowRepoUrl) {
5205bf2b6ebSBrian Hill 			(new BAlert("duplicate",
5215bf2b6ebSBrian Hill 				B_TRANSLATE_COMMENT("This repository URL already exists.",
5225bf2b6ebSBrian Hill 					"Error message"),
5235bf2b6ebSBrian Hill 				kOKLabel))->Go(NULL);
5245bf2b6ebSBrian Hill 			return;
5255bf2b6ebSBrian Hill 		}
526856ecc7bSBrian Hill 	}
5275bf2b6ebSBrian Hill 	RepoRow* newRepo = _AddRepo(name, url, false);
5285bf2b6ebSBrian Hill 	_FindSiblings();
5295bf2b6ebSBrian Hill 	fListView->DeselectAll();
5305bf2b6ebSBrian Hill 	fListView->AddToSelection(newRepo);
5315bf2b6ebSBrian Hill 	_UpdateButtons();
5325bf2b6ebSBrian Hill 	_SaveList();
533*3e967b3fSBrian Hill 	if (fEnableButton->IsEnabled())
534*3e967b3fSBrian Hill 		fEnableButton->Invoke();
5355bf2b6ebSBrian Hill }
5365bf2b6ebSBrian Hill 
5375bf2b6ebSBrian Hill 
5385bf2b6ebSBrian Hill status_t
5395bf2b6ebSBrian Hill RepositoriesView::_EmptyList()
5405bf2b6ebSBrian Hill {
541856ecc7bSBrian Hill 	BRow* row = fListView->RowAt((int32)0, NULL);
542856ecc7bSBrian Hill 	while (row != NULL) {
5435bf2b6ebSBrian Hill 		fListView->RemoveRow(row);
5445bf2b6ebSBrian Hill 		delete row;
545856ecc7bSBrian Hill 		row = fListView->RowAt((int32)0, NULL);
5465bf2b6ebSBrian Hill 	}
5475bf2b6ebSBrian Hill 	return B_OK;
5485bf2b6ebSBrian Hill }
5495bf2b6ebSBrian Hill 
5505bf2b6ebSBrian Hill 
5515bf2b6ebSBrian Hill void
5525bf2b6ebSBrian Hill RepositoriesView::_InitList()
5535bf2b6ebSBrian Hill {
5545bf2b6ebSBrian Hill 	// Get list of known repositories from the settings file
5555bf2b6ebSBrian Hill 	int32 index, repoCount;
5565bf2b6ebSBrian Hill 	BStringList nameList, urlList;
5575bf2b6ebSBrian Hill 	status_t result = fSettings.GetRepositories(repoCount, nameList, urlList);
5585bf2b6ebSBrian Hill 	if (result == B_OK) {
5595bf2b6ebSBrian Hill 		BString name, url;
5605bf2b6ebSBrian Hill 		for (index = 0; index < repoCount; index++) {
5615bf2b6ebSBrian Hill 			name = nameList.StringAt(index);
5625bf2b6ebSBrian Hill 			url = urlList.StringAt(index);
5635bf2b6ebSBrian Hill 			_AddRepo(name, url, false);
5645bf2b6ebSBrian Hill 		}
5655bf2b6ebSBrian Hill 	}
5665bf2b6ebSBrian Hill 	_UpdateListFromRoster();
5675bf2b6ebSBrian Hill 	fListView->SetSortColumn(fListView->ColumnAt(kUrlColumn), false, true);
5685bf2b6ebSBrian Hill 	fListView->ResizeAllColumnsToPreferred();
5695bf2b6ebSBrian Hill }
5705bf2b6ebSBrian Hill 
5715bf2b6ebSBrian Hill 
5725bf2b6ebSBrian Hill void
5735bf2b6ebSBrian Hill RepositoriesView::_RefreshList()
5745bf2b6ebSBrian Hill {
5755bf2b6ebSBrian Hill 	// Clear enabled status on all rows
5765bf2b6ebSBrian Hill 	int32 index, listCount = fListView->CountRows();
5775bf2b6ebSBrian Hill 	for (index = 0; index < listCount; index++) {
5785bf2b6ebSBrian Hill 		RepoRow* repoItem = dynamic_cast<RepoRow*>(fListView->RowAt(index));
5795bf2b6ebSBrian Hill 		if (repoItem->TaskState() == STATE_NOT_IN_QUEUE)
5805bf2b6ebSBrian Hill 			repoItem->SetEnabled(false);
5815bf2b6ebSBrian Hill 	}
5825bf2b6ebSBrian Hill 	// Get current list of enabled repositories
5835bf2b6ebSBrian Hill 	_UpdateListFromRoster();
5845bf2b6ebSBrian Hill }
5855bf2b6ebSBrian Hill 
5865bf2b6ebSBrian Hill 
5875bf2b6ebSBrian Hill void
5885bf2b6ebSBrian Hill RepositoriesView::_UpdateListFromRoster()
5895bf2b6ebSBrian Hill {
5905bf2b6ebSBrian Hill 	// Get list of currently enabled repositories
5915bf2b6ebSBrian Hill 	BStringList repositoryNames;
5925bf2b6ebSBrian Hill 	BPackageKit::BPackageRoster pRoster;
5935bf2b6ebSBrian Hill 	status_t result = pRoster.GetRepositoryNames(repositoryNames);
5945bf2b6ebSBrian Hill 	if (result != B_OK) {
5955bf2b6ebSBrian Hill 		(new BAlert("error",
5965bf2b6ebSBrian Hill 			B_TRANSLATE_COMMENT("Repositories could not retrieve the names of "
5975bf2b6ebSBrian Hill 				"the currently enabled repositories.", "Alert error message"),
5985bf2b6ebSBrian Hill 			kOKLabel, NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(NULL);
5995bf2b6ebSBrian Hill 		return;
6005bf2b6ebSBrian Hill 	}
6015bf2b6ebSBrian Hill 	BPackageKit::BRepositoryConfig repoConfig;
6025bf2b6ebSBrian Hill 	int16 index, count = repositoryNames.CountStrings();
6035bf2b6ebSBrian Hill 	for (index = 0; index < count; index++) {
6045bf2b6ebSBrian Hill 		const BString& repoName = repositoryNames.StringAt(index);
6055bf2b6ebSBrian Hill 		result = pRoster.GetRepositoryConfig(repoName, &repoConfig);
6065bf2b6ebSBrian Hill 		if (result == B_OK)
6075bf2b6ebSBrian Hill 			_AddRepo(repoName, repoConfig.BaseURL(), true);
6085bf2b6ebSBrian Hill 		else {
6095bf2b6ebSBrian Hill 			BString text(B_TRANSLATE_COMMENT("Error getting repository"
6105bf2b6ebSBrian Hill 				" configuration for %name%.", "Alert error message, "
6115bf2b6ebSBrian Hill 				"do not translate %name%"));
6125bf2b6ebSBrian Hill 			text.ReplaceFirst("%name%", repoName);
6135bf2b6ebSBrian Hill 			(new BAlert("error", text, kOKLabel))->Go(NULL);
6145bf2b6ebSBrian Hill 		}
6155bf2b6ebSBrian Hill 	}
6165bf2b6ebSBrian Hill 	_FindSiblings();
6175bf2b6ebSBrian Hill 	_SaveList();
6185bf2b6ebSBrian Hill }
6195bf2b6ebSBrian Hill 
6205bf2b6ebSBrian Hill 
6215bf2b6ebSBrian Hill void
6225bf2b6ebSBrian Hill RepositoriesView::_SaveList()
6235bf2b6ebSBrian Hill {
6245bf2b6ebSBrian Hill 	BStringList nameList, urlList;
6255bf2b6ebSBrian Hill 	int32 index;
6265bf2b6ebSBrian Hill 	int32 listCount = fListView->CountRows();
6275bf2b6ebSBrian Hill 	for (index = 0; index < listCount; index++) {
6285bf2b6ebSBrian Hill 		RepoRow* repoItem = dynamic_cast<RepoRow*>(fListView->RowAt(index));
6295bf2b6ebSBrian Hill 		nameList.Add(repoItem->Name());
6305bf2b6ebSBrian Hill 		urlList.Add(repoItem->Url());
6315bf2b6ebSBrian Hill 	}
6325bf2b6ebSBrian Hill 	fSettings.SetRepositories(nameList, urlList);
6335bf2b6ebSBrian Hill }
6345bf2b6ebSBrian Hill 
6355bf2b6ebSBrian Hill 
6365bf2b6ebSBrian Hill RepoRow*
6375bf2b6ebSBrian Hill RepositoriesView::_AddRepo(BString name, BString url, bool enabled)
6385bf2b6ebSBrian Hill {
639856ecc7bSBrian Hill 	// URL must be valid
640856ecc7bSBrian Hill 	BUrl repoUrl(url);
641856ecc7bSBrian Hill 	if (!repoUrl.IsValid())
6425bf2b6ebSBrian Hill 		return NULL;
6435bf2b6ebSBrian Hill 	int32 index;
6445bf2b6ebSBrian Hill 	int32 listCount = fListView->CountRows();
6455bf2b6ebSBrian Hill 	// Find if the repo already exists in list
6465bf2b6ebSBrian Hill 	for (index = 0; index < listCount; index++) {
6475bf2b6ebSBrian Hill 		RepoRow* repoItem = dynamic_cast<RepoRow*>(fListView->RowAt(index));
648856ecc7bSBrian Hill 		BUrl itemUrl(repoItem->Url());
649856ecc7bSBrian Hill 		if (repoUrl == itemUrl) {
6505bf2b6ebSBrian Hill 			// update name and enabled values
651856ecc7bSBrian Hill 			if (name != repoItem->Name())
6525bf2b6ebSBrian Hill 				repoItem->SetName(name.String());
6535bf2b6ebSBrian Hill 			repoItem->SetEnabled(enabled);
654856ecc7bSBrian Hill 			return repoItem;
6555bf2b6ebSBrian Hill 		}
6565bf2b6ebSBrian Hill 	}
657856ecc7bSBrian Hill 	RepoRow* addedRow = new RepoRow(name, url, enabled);
6585bf2b6ebSBrian Hill 	fListView->AddRow(addedRow);
6595bf2b6ebSBrian Hill 	return addedRow;
6605bf2b6ebSBrian Hill }
6615bf2b6ebSBrian Hill 
6625bf2b6ebSBrian Hill 
6635bf2b6ebSBrian Hill void
6645bf2b6ebSBrian Hill RepositoriesView::_FindSiblings()
6655bf2b6ebSBrian Hill {
6665bf2b6ebSBrian Hill 	BStringList namesFound, namesWithSiblings;
6675bf2b6ebSBrian Hill 	int32 index, listCount = fListView->CountRows();
6685bf2b6ebSBrian Hill 	// Find repository names that are duplicated
6695bf2b6ebSBrian Hill 	for (index = 0; index < listCount; index++) {
6705bf2b6ebSBrian Hill 		RepoRow* repoItem = dynamic_cast<RepoRow*>(fListView->RowAt(index));
6715bf2b6ebSBrian Hill 		BString name = repoItem->Name();
6725bf2b6ebSBrian Hill 		// Ignore newly added repos since we don't know the real name yet
6735bf2b6ebSBrian Hill 		if (name.Compare(kNewRepoDefaultName)==0)
6745bf2b6ebSBrian Hill 			continue;
6755bf2b6ebSBrian Hill 		// First time a name is found- no sibling (yet)
6765bf2b6ebSBrian Hill 		if (!namesFound.HasString(name))
6775bf2b6ebSBrian Hill 			namesFound.Add(name);
6785bf2b6ebSBrian Hill 		// Name was already found once so this name has 2 or more siblings
6795bf2b6ebSBrian Hill 		else if (!namesWithSiblings.HasString(name))
6805bf2b6ebSBrian Hill 			namesWithSiblings.Add(name);
6815bf2b6ebSBrian Hill 	}
6825bf2b6ebSBrian Hill 	// Set sibling values for each row
6835bf2b6ebSBrian Hill 	for (index = 0; index < listCount; index++) {
6845bf2b6ebSBrian Hill 		RepoRow* repoItem = dynamic_cast<RepoRow*>(fListView->RowAt(index));
6855bf2b6ebSBrian Hill 		BString name = repoItem->Name();
6865bf2b6ebSBrian Hill 		repoItem->SetHasSiblings(namesWithSiblings.HasString(name));
6875bf2b6ebSBrian Hill 	}
6885bf2b6ebSBrian Hill }
6895bf2b6ebSBrian Hill 
6905bf2b6ebSBrian Hill 
6915bf2b6ebSBrian Hill void
6925bf2b6ebSBrian Hill RepositoriesView::_UpdateButtons()
6935bf2b6ebSBrian Hill {
6945bf2b6ebSBrian Hill 	RepoRow* rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection());
6955bf2b6ebSBrian Hill 	// At least one row is selected
6965bf2b6ebSBrian Hill 	if (rowItem) {
697856ecc7bSBrian Hill 		bool someAreEnabled = false;
698856ecc7bSBrian Hill 		bool someAreDisabled = false;
699856ecc7bSBrian Hill 		bool someAreInQueue = false;
7005bf2b6ebSBrian Hill 		int32 selectedCount = 0;
7015bf2b6ebSBrian Hill 		RepoRow* rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection());
7025bf2b6ebSBrian Hill 		while (rowItem) {
7035bf2b6ebSBrian Hill 			selectedCount++;
7045bf2b6ebSBrian Hill 			uint32 taskState = rowItem->TaskState();
7055bf2b6ebSBrian Hill 			if ( taskState == STATE_IN_QUEUE_WAITING
706856ecc7bSBrian Hill 				|| taskState == STATE_IN_QUEUE_RUNNING) {
7075bf2b6ebSBrian Hill 				someAreInQueue = true;
708856ecc7bSBrian Hill 			}
7095bf2b6ebSBrian Hill 			if (rowItem->IsEnabled())
7105bf2b6ebSBrian Hill 				someAreEnabled = true;
7115bf2b6ebSBrian Hill 			else
7125bf2b6ebSBrian Hill 				someAreDisabled = true;
7135bf2b6ebSBrian Hill 			rowItem = dynamic_cast<RepoRow*>(fListView->CurrentSelection(rowItem));
7145bf2b6ebSBrian Hill 		}
7155bf2b6ebSBrian Hill 		// Change button labels depending on which rows are selected
7165bf2b6ebSBrian Hill 		if (selectedCount > 1) {
7175bf2b6ebSBrian Hill 			fEnableButton->SetLabel(kLabelEnableAll);
7185bf2b6ebSBrian Hill 			fDisableButton->SetLabel(kLabelDisableAll);
7195bf2b6ebSBrian Hill 		} else {
7205bf2b6ebSBrian Hill 			fEnableButton->SetLabel(kLabelEnable);
7215bf2b6ebSBrian Hill 			fDisableButton->SetLabel(kLabelDisable);
7225bf2b6ebSBrian Hill 		}
7235bf2b6ebSBrian Hill 		// Set which buttons should be enabled
7245bf2b6ebSBrian Hill 		fRemoveButton->SetEnabled(!someAreEnabled && !someAreInQueue);
7255bf2b6ebSBrian Hill 		if ((someAreEnabled && someAreDisabled) || someAreInQueue) {
7265bf2b6ebSBrian Hill 			// there are a mix of enabled and disabled repositories selected
7275bf2b6ebSBrian Hill 			fEnableButton->SetEnabled(false);
7285bf2b6ebSBrian Hill 			fDisableButton->SetEnabled(false);
7295bf2b6ebSBrian Hill 		} else {
7305bf2b6ebSBrian Hill 			fEnableButton->SetEnabled(someAreDisabled);
7315bf2b6ebSBrian Hill 			fDisableButton->SetEnabled(someAreEnabled);
7325bf2b6ebSBrian Hill 		}
7335bf2b6ebSBrian Hill 
7345bf2b6ebSBrian Hill 	} else {
7355bf2b6ebSBrian Hill 		// No selected rows
7365bf2b6ebSBrian Hill 		fEnableButton->SetLabel(kLabelEnable);
7375bf2b6ebSBrian Hill 		fDisableButton->SetLabel(kLabelDisable);
7385bf2b6ebSBrian Hill 		fEnableButton->SetEnabled(false);
7395bf2b6ebSBrian Hill 		fDisableButton->SetEnabled(false);
7405bf2b6ebSBrian Hill 		fRemoveButton->SetEnabled(false);
7415bf2b6ebSBrian Hill 	}
7425bf2b6ebSBrian Hill }
7435bf2b6ebSBrian Hill 
7445bf2b6ebSBrian Hill 
7455bf2b6ebSBrian Hill void
7465bf2b6ebSBrian Hill RepositoriesView::_UpdateStatusView()
7475bf2b6ebSBrian Hill {
7485bf2b6ebSBrian Hill 	if (fRunningTaskCount) {
7495bf2b6ebSBrian Hill 		BString text(kStatusViewText);
7505bf2b6ebSBrian Hill 		text.Append(" ");
7515bf2b6ebSBrian Hill 		text << fRunningTaskCount;
7525bf2b6ebSBrian Hill 		fListStatusView->SetText(text);
7535bf2b6ebSBrian Hill 	} else
7545bf2b6ebSBrian Hill 		fListStatusView->SetText("");
7555bf2b6ebSBrian Hill }
756