2 * Copyright 2011, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Clemens Zeidler <haiku@clemens-zeidler.de>
9 #include "MusicCollectionWindow.h"
11 #include <Application.h>
12 #include <ControlLook.h>
14 #include <ScrollView.h>
15 #include <VolumeRoster.h>
17 #include <NaturalCompare.h>
19 #include "ALMLayout.h"
20 #include "ALMLayoutBuilder.h"
24 StringItemComp(const BListItem
* first
, const BListItem
* second
)
26 BStringItem
* firstItem
= (BStringItem
*)first
;
27 BStringItem
* secondItem
= (BStringItem
*)second
;
28 return BPrivate::NaturalCompare(firstItem
->Text(), secondItem
->Text());
32 template <class ListItem
= FileListItem
>
33 class ListViewListener
: public EntryViewInterface
{
35 ListViewListener(BOutlineListView
* list
, BStringView
* countView
)
38 fCountView(countView
),
46 SetQueryString(const char* string
)
48 fQueryString
= string
;
53 EntryCreated(WatchedFile
* file
)
55 //ListItem* item1 = new ListItem(file->entry.name, file);
56 //fListView->AddItem(item1);
59 BString
count("Count: ");
61 fCountView
->SetText(count
);
63 const ssize_t bufferSize
= 256;
64 char buffer
[bufferSize
];
65 BNode
node(&file
->entry
);
68 readBytes
= node
.ReadAttr("Audio:Artist", B_STRING_TYPE
, 0, buffer
,
72 if (readBytes
>= bufferSize
)
73 readBytes
= bufferSize
- 1;
74 buffer
[readBytes
] = '\0';
76 BString artist
= (strcmp(buffer
, "") == 0) ? "Unknown" : buffer
;
77 ListItem
* artistItem
= _AddSuperItem(artist
, fArtistList
, NULL
);
79 readBytes
= node
.ReadAttr("Audio:Album", B_STRING_TYPE
, 0, buffer
,
83 buffer
[readBytes
] = '\0';
84 BString album
= (strcmp(buffer
, "") == 0) ? "Unknown" : buffer
;
85 ListItem
* albumItem
= _AddSuperItem(album
, fAlbumList
, artistItem
);
87 readBytes
= node
.ReadAttr("Media:Title", B_STRING_TYPE
, 0, buffer
,
91 buffer
[readBytes
] = '\0';
92 BString title
= (strcmp(buffer
, "") == 0) ? file
->entry
.name
95 ListItem
* item
= new ListItem(title
, file
);
97 fListView
->AddUnder(item
, albumItem
);
98 fListView
->SortItemsUnder(albumItem
, true, StringItemComp
);
100 if (fQueryString
== "")
102 if (title
.IFindFirst(fQueryString
) >= 0) {
103 fListView
->Expand(artistItem
);
104 fListView
->Expand(albumItem
);
105 } else if (album
.IFindFirst(fQueryString
) >= 0) {
106 fListView
->Expand(artistItem
);
112 EntryRemoved(WatchedFile
* file
)
114 ListItem
* item
= (ListItem
*)file
->cookie
;
115 ListItem
* album
= (ListItem
*)fListView
->Superitem(item
);
116 fListView
->RemoveItem(item
);
117 if (album
!= NULL
&& fListView
->CountItemsUnder(album
, true) == 0) {
118 ListItem
* artist
= (ListItem
*)fListView
->Superitem(album
);
119 fListView
->RemoveItem(album
);
120 if (artist
!= NULL
&& fListView
->CountItemsUnder(artist
, true) == 0)
121 fListView
->RemoveItem(artist
);
126 EntryMoved(WatchedFile
* file
)
133 AttrChanged(WatchedFile
* file
)
143 for (int32 i
= 0; i
< fListView
->FullListCountItems(); i
++)
144 delete fListView
->FullListItemAt(i
);
145 fListView
->MakeEmpty();
147 fArtistList
.MakeEmpty();
148 fAlbumList
.MakeEmpty();
150 printf("prev count %i\n", (int)fItemCount
);
152 fCountView
->SetText("Count: 0");
158 _AddSuperItem(const char* name
, BObjectList
<ListItem
>& list
,
161 ListItem
* item
= _FindStringItem(list
, name
, under
);
165 item
= new ListItem(name
);
166 fListView
->AddUnder(item
, under
);
167 fListView
->SortItemsUnder(under
, true, StringItemComp
);
170 fListView
->Collapse(item
);
176 _FindStringItem(BObjectList
<ListItem
>& list
, const char* text
,
179 for (int32 i
= 0; i
< list
.CountItems(); i
++) {
180 ListItem
* item
= list
.ItemAt(i
);
181 ListItem
* superItem
= (ListItem
*)fListView
->Superitem(item
);
182 if (parent
!= NULL
&& parent
!= superItem
)
184 if (strcmp(item
->Text(), text
) == 0)
190 BOutlineListView
* fListView
;
191 BStringView
* fCountView
;
193 BObjectList
<ListItem
> fArtistList
;
194 BObjectList
<ListItem
> fAlbumList
;
196 BString fQueryString
;
201 const uint32 kMsgQueryInput
= '&qin';
202 const uint32 kMsgItemInvoked
= '&iin';
205 MusicCollectionWindow::MusicCollectionWindow(BRect frame
, const char* title
)
207 BWindow(frame
, title
, B_DOCUMENT_WINDOW
, B_AVOID_FRONT
)
209 fQueryField
= new BTextControl("Search: ", "", NULL
);
210 fQueryField
->SetExplicitAlignment(BAlignment(B_ALIGN_HORIZONTAL_CENTER
,
211 B_ALIGN_USE_FULL_HEIGHT
));
212 fQueryField
->SetModificationMessage(new BMessage(kMsgQueryInput
));
214 fCountView
= new BStringView("Count View", "Count:");
216 fFileListView
= new MusicFileListView("File List View");
217 fFileListView
->SetInvocationMessage(new BMessage(kMsgItemInvoked
));
218 BScrollView
* scrollView
= new BScrollView("list scroll", fFileListView
, 0,
219 true, true, B_PLAIN_BORDER
);
221 BALMLayout
* layout
= new BALMLayout(B_USE_ITEM_SPACING
, B_USE_ITEM_SPACING
);
222 BALM::BALMLayoutBuilder(this, layout
)
223 .SetInsets(B_USE_WINDOW_INSETS
)
224 .Add(fQueryField
, layout
->Left(), layout
->Top())
225 .StartingAt(fQueryField
)
226 .AddToRight(fCountView
, layout
->Right())
227 .AddBelow(scrollView
, layout
->Bottom(), layout
->Left(),
230 Area
* area
= layout
->AreaFor(scrollView
);
231 area
->SetLeftInset(0);
232 area
->SetRightInset(0);
233 area
->SetBottomInset(0);
235 BSize min
= layout
->MinSize();
236 BSize max
= layout
->MaxSize();
237 SetSizeLimits(min
.Width(), max
.Width(), min
.Height(), max
.Height());
239 fEntryViewInterface
= new ListViewListener
<FileListItem
>(fFileListView
,
241 fQueryHandler
= new QueryHandler(fEntryViewInterface
);
242 AddHandler(fQueryHandler
);
243 fQueryReader
= new QueryReader(fQueryHandler
);
244 fQueryHandler
->SetReadThread(fQueryReader
);
246 // start initial query
247 PostMessage(kMsgQueryInput
);
251 MusicCollectionWindow::~MusicCollectionWindow()
254 delete fQueryHandler
;
255 delete fEntryViewInterface
;
260 MusicCollectionWindow::QuitRequested()
262 be_app
->PostMessage(B_QUIT_REQUESTED
);
268 MusicCollectionWindow::MessageReceived(BMessage
* message
)
270 switch (message
->what
) {
275 case kMsgItemInvoked
:
276 fFileListView
->Launch(message
);
280 BWindow::MessageReceived(message
);
286 CaseInsensitiveString(BString
&instring
, BString
&outstring
)
292 if (instring
[i
] >= 65 && instring
[i
] <= 90) // capital letters
294 int ch
= instring
[i
] + 32;
297 outstring
+= instring
[i
];
299 } else if (instring
[i
] >= 97 && instring
[i
] <= 122)
301 int ch
= instring
[i
]-32;
303 outstring
+= instring
[i
];
307 outstring
+= instring
[i
];
314 MusicCollectionWindow::_StartNewQuery()
316 fQueryReader
->Reset();
317 fQueryHandler
->Reset();
319 BString orgString
= fQueryField
->Text();
320 ((ListViewListener
<FileListItem
>*)fEntryViewInterface
)->SetQueryString(
324 //BVolumeRoster().GetBootVolume(&volume);
325 BVolumeRoster roster
;
326 while (roster
.GetNextVolume(&volume
) == B_OK
) {
327 if (!volume
.KnowsQuery())
329 BQuery
* query
= _CreateQuery(orgString
);
330 query
->SetVolume(&volume
);
331 fQueryReader
->AddQuery(query
);
339 MusicCollectionWindow::_CreateQuery(BString
& orgString
)
341 BQuery
* query
= new BQuery
;
344 CaseInsensitiveString(orgString
, queryString
);
346 query
->PushAttr("Media:Title");
347 query
->PushString(queryString
);
348 query
->PushOp(B_CONTAINS
);
350 query
->PushAttr("Audio:Album");
351 query
->PushString(queryString
);
352 query
->PushOp(B_CONTAINS
);
355 query
->PushAttr("Audio:Artist");
356 query
->PushString(queryString
);
357 query
->PushOp(B_CONTAINS
);
360 if (queryString
== "") {
361 query
->PushAttr("BEOS:TYPE");
362 query
->PushString("audio/");
363 query
->PushOp(B_BEGINS_WITH
);
367 query
->PushAttr("BEOS:TYPE");
368 query
->PushString("audio/");
369 query
->PushOp(B_BEGINS_WITH
);
371 query
->PushAttr("name");
372 query
->PushString(queryString
);
373 query
->PushOp(B_CONTAINS
);
374 query
->PushOp(B_AND
);