* New types are now no longer directly added, but delayed a bit (via a BMessageRunner);

this is done so that the type can be fully installed before investigating it.
* When the preferred app of a type changes, the "is application" property will be
  reexamined - this should help in letting new application types appear in the
  FileTypesWindow list, but not in the ApplicationTypesWindow list.
* Added a progress window for removing uninstalled apps.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16726 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-03-11 23:47:26 +00:00
parent 8fee027ee3
commit dcf60976b6
3 changed files with 198 additions and 32 deletions

View File

@ -24,7 +24,9 @@
#include <PopUpMenu.h>
#include <Query.h>
#include <Roster.h>
#include <Screen.h>
#include <ScrollView.h>
#include <StatusBar.h>
#include <StringView.h>
#include <TextView.h>
#include <Volume.h>
@ -33,7 +35,21 @@
#include <stdio.h>
class ProgressWindow : public BWindow {
public:
ProgressWindow(const char* message, int32 max, volatile bool* signalQuit);
virtual ~ProgressWindow();
virtual void MessageReceived(BMessage* message);
private:
BStatusBar* fStatusBar;
BButton* fAbortButton;
volatile bool* fQuitListener;
};
const uint32 kMsgTypeSelected = 'typs';
const uint32 kMsgTypeInvoked = 'typi';
const uint32 kMsgRemoveUninstalled = 'runs';
@ -71,6 +87,77 @@ variety_to_text(uint32 variety)
// #pragma mark -
ProgressWindow::ProgressWindow(const char* message, int32 max, volatile bool* signalQuit)
: BWindow(BRect(0, 0, 300, 200), "Progress", B_MODAL_WINDOW_LOOK,
B_MODAL_SUBSET_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS | B_NOT_V_RESIZABLE),
fQuitListener(signalQuit)
{
BView* topView = new BView(Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW);
topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
AddChild(topView);
char count[100];
snprintf(count, sizeof(count), "/%ld", max);
BRect rect = Bounds().InsetByCopy(8, 8);
fStatusBar = new BStatusBar(rect, "status", message, count);
fStatusBar->SetMaxValue(max);
fStatusBar->SetResizingMode(B_FOLLOW_LEFT_RIGHT);
float width, height;
fStatusBar->GetPreferredSize(&width, &height);
fStatusBar->ResizeTo(rect.Width(), height);
topView->AddChild(fStatusBar);
fAbortButton = new BButton(rect, "abort", "Abort", new BMessage(B_CANCEL),
B_FOLLOW_H_CENTER | B_FOLLOW_TOP);
fAbortButton->ResizeToPreferred();
fAbortButton->MoveTo((Bounds().Width() - fAbortButton->Bounds().Width()) / 2,
fStatusBar->Frame().bottom + 10.0f);
topView->AddChild(fAbortButton);
ResizeTo(width * 1.4f, fAbortButton->Frame().bottom + 8.0f);
SetSizeLimits(width + 42.0f, 32767.0f,
Bounds().Height(), Bounds().Height());
// center on screen
BScreen screen(this);
MoveTo(screen.Frame().left + (screen.Frame().Width() - Bounds().Width()) / 2.0f,
screen.Frame().top + (screen.Frame().Height() - Bounds().Height()) / 2.0f);
}
ProgressWindow::~ProgressWindow()
{
}
void
ProgressWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_UPDATE_STATUS_BAR:
char count[100];
snprintf(count, sizeof(count), "%ld", (int32)fStatusBar->CurrentValue() + 1);
fStatusBar->Update(1, NULL, count);
break;
case B_CANCEL:
fAbortButton->SetEnabled(false);
if (fQuitListener != NULL)
*fQuitListener = true;
break;
default:
BWindow::MessageReceived(message);
break;
}
}
// #pragma mark -
ApplicationTypesWindow::ApplicationTypesWindow(BRect frame)
: BWindow(frame, "Application Types", B_TITLED_WINDOW,
B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS)
@ -96,6 +183,7 @@ ApplicationTypesWindow::ApplicationTypesWindow(BRect frame)
fTypeListView = new MimeTypeListView(rect, "listview", "application", true, true,
B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM);
fTypeListView->SetSelectionMessage(new BMessage(kMsgTypeSelected));
fTypeListView->SetInvocationMessage(new BMessage(kMsgTypeInvoked));
BScrollView* scrollView = new BScrollView("scrollview", fTypeListView,
B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, B_FRAME_EVENTS | B_WILL_DRAW, false, true);
@ -213,9 +301,17 @@ ApplicationTypesWindow::_RemoveUninstalled()
// Note: this runs in the looper's thread, which isn't that nice
int32 removed = 0;
volatile bool quit = false;
for (int32 i = fTypeListView->FullListCountItems(); i-- > 0;) {
BWindow* progressWindow = new ProgressWindow("Removing uninstalled application types",
fTypeListView->FullListCountItems(), &quit);
progressWindow->AddToSubset(this);
progressWindow->Show();
for (int32 i = fTypeListView->FullListCountItems(); i-- > 0 && !quit;) {
MimeTypeItem* item = dynamic_cast<MimeTypeItem*>(fTypeListView->FullListItemAt(i));
progressWindow->PostMessage(B_UPDATE_STATUS_BAR);
if (item == NULL)
continue;
@ -257,6 +353,8 @@ ApplicationTypesWindow::_RemoveUninstalled()
}
}
progressWindow->PostMessage(B_QUIT_REQUESTED);
char message[512];
snprintf(message, sizeof(message), "%ld Application Type%s could be removed.",
removed, removed == 1 ? "" : "s");
@ -366,7 +464,6 @@ ApplicationTypesWindow::_SetType(BMimeType* type, int32 forceUpdate)
}
void
ApplicationTypesWindow::FrameResized(float width, float height)
{
@ -393,6 +490,25 @@ ApplicationTypesWindow::MessageReceived(BMessage* message)
break;
}
case kMsgTypeInvoked:
{
int32 index;
if (message->FindInt32("index", &index) == B_OK) {
MimeTypeItem* item = (MimeTypeItem*)fTypeListView->ItemAt(index);
if (item != NULL) {
BMimeType type(item->Type());
entry_ref ref;
if (type.GetAppHint(&ref) == B_OK) {
BMessage refs(B_REFS_RECEIVED);
refs.AddRef("refs", &ref);
be_app->PostMessage(&refs);
}
}
}
break;
}
case kMsgRemoveUninstalled:
_RemoveUninstalled();
break;

View File

@ -7,11 +7,15 @@
#include "MimeTypeListView.h"
#include <Bitmap.h>
#include <MessageRunner.h>
// TODO: lazy type collecting (super types only at startup)
const uint32 kMsgAddType = 'adtp';
status_t
icon_for_type(BMimeType& type, BBitmap& bitmap, icon_size size,
icon_source* _source)
@ -430,6 +434,51 @@ MimeTypeListView::_MakeTypesUnique(MimeTypeItem* underItem)
}
void
MimeTypeListView::_AddNewType(const char* type)
{
MimeTypeItem* item = FindItem(type);
BMimeType mimeType(type);
bool isApp = mimetype_is_application_signature(mimeType);
if (fApplicationMode ^ isApp || !mimeType.IsInstalled()) {
if (item != NULL) {
// type doesn't belong here
RemoveItem(item);
delete item;
}
return;
}
if (item != NULL) {
// for some reason, the type already exists
return;
}
BMimeType superType;
MimeTypeItem* superItem = NULL;
if (mimeType.GetSupertype(&superType) == B_OK)
superItem = FindItem(superType.Type());
item = new MimeTypeItem(mimeType, fShowIcons, fSupertype.Type() != NULL);
item->SetApplicationMode(isApp);
if (superItem != NULL) {
AddUnder(item, superItem);
InvalidateItem(IndexOf(superItem));
// the super item is not picked up from the class (ie. bug)
} else
AddItem(item);
UpdateItem(item);
if (!fSelectNewType.ICompare(mimeType.Type())) {
SelectItem(item);
fSelectNewType = "";
}
}
void
MimeTypeListView::AttachedToWindow()
{
@ -470,7 +519,7 @@ MimeTypeListView::MessageReceived(BMessage* message)
case B_SHORT_DESCRIPTION_CHANGED:
{
// update label
MimeTypeItem* item = FindItem(type);
if (item != NULL)
UpdateItem(item);
@ -478,33 +527,17 @@ MimeTypeListView::MessageReceived(BMessage* message)
}
case B_MIME_TYPE_CREATED:
{
// create new item
BMimeType created(type);
bool isApp = mimetype_is_application_signature(created);
if (fApplicationMode ^ isApp)
break;
// delay creation of new item a bit, until the type is fully installed
BMimeType superType;
MimeTypeItem* superItem = NULL;
if (created.GetSupertype(&superType) == B_OK)
superItem = FindItem(superType.Type());
BMessage addType(kMsgAddType);
addType.AddString("type", type);
MimeTypeItem* item = new MimeTypeItem(created, fShowIcons,
fSupertype.Type() != NULL);
item->SetApplicationMode(isApp);
if (superItem != NULL) {
AddUnder(item, superItem);
InvalidateItem(IndexOf(superItem));
// the super item is not picked up from the class (ie. bug)
} else
AddItem(item);
UpdateItem(item);
if (!fSelectNewType.ICompare(type)) {
SelectItem(item);
fSelectNewType = "";
// TODO: free runner again!
BMessageRunner* runner = new BMessageRunner(this, &addType,
200000ULL, 1);
if (runner->InitCheck() != B_OK) {
delete runner;
_AddNewType(type);
}
break;
}
@ -519,15 +552,23 @@ MimeTypeListView::MessageReceived(BMessage* message)
break;
}
case B_PREFERRED_APP_CHANGED:
{
// try to add or remove this type (changing the preferred app
// might change visibility in our list)
_AddNewType(type);
// supposed to fall through
}
case B_ICON_CHANGED:
// TODO: take B_ICON_FOR_TYPE_CHANGED into account, too
if (fShowIcons) {
{
MimeTypeItem* item = FindItem(type);
if (item != NULL && fShowIcons) {
// refresh item
MimeTypeItem* item = FindItem(type);
if (item != NULL)
InvalidateItem(IndexOf(item));
InvalidateItem(IndexOf(item));
}
break;
}
default:
break;
@ -535,6 +576,14 @@ MimeTypeListView::MessageReceived(BMessage* message)
break;
}
case kMsgAddType:
{
const char* type;
if (message->FindString("type", &type) == B_OK)
_AddNewType(type);
break;
}
default:
BOutlineListView::MessageReceived(message);
}

View File

@ -79,6 +79,7 @@ class MimeTypeListView : public BOutlineListView {
void _CollectSubtypes(const char* supertype, MimeTypeItem* supertypeItem);
void _CollectTypes();
void _MakeTypesUnique(MimeTypeItem* underItem = NULL);
void _AddNewType(const char* type);
BMimeType fSupertype;
BString fSelectNewType;