btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / musiccollection / MusicCollectionWindow.cpp
bloba84f6817070fd243877486722eddd0ca1cef99f4
1 /*
2 * Copyright 2011, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Clemens Zeidler <haiku@clemens-zeidler.de>
7 */
9 #include "MusicCollectionWindow.h"
11 #include <Application.h>
12 #include <ControlLook.h>
13 #include <Debug.h>
14 #include <ScrollView.h>
15 #include <VolumeRoster.h>
17 #include <NaturalCompare.h>
19 #include "ALMLayout.h"
20 #include "ALMLayoutBuilder.h"
23 static int
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 {
34 public:
35 ListViewListener(BOutlineListView* list, BStringView* countView)
37 fListView(list),
38 fCountView(countView),
39 fItemCount(0)
45 void
46 SetQueryString(const char* string)
48 fQueryString = string;
52 void
53 EntryCreated(WatchedFile* file)
55 //ListItem* item1 = new ListItem(file->entry.name, file);
56 //fListView->AddItem(item1);
58 fItemCount++;
59 BString count("Count: ");
60 count << fItemCount;
61 fCountView->SetText(count);
63 const ssize_t bufferSize = 256;
64 char buffer[bufferSize];
65 BNode node(&file->entry);
67 ssize_t readBytes;
68 readBytes = node.ReadAttr("Audio:Artist", B_STRING_TYPE, 0, buffer,
69 bufferSize);
70 if (readBytes < 0)
71 readBytes = 0;
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,
80 bufferSize);
81 if (readBytes < 0)
82 readBytes = 0;
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,
88 bufferSize);
89 if (readBytes < 0)
90 readBytes = 0;
91 buffer[readBytes] = '\0';
92 BString title= (strcmp(buffer, "") == 0) ? file->entry.name
93 : buffer;
95 ListItem* item = new ListItem(title, file);
96 file->cookie = item;
97 fListView->AddUnder(item, albumItem);
98 fListView->SortItemsUnder(albumItem, true, StringItemComp);
100 if (fQueryString == "")
101 return;
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);
111 void
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);
125 void
126 EntryMoved(WatchedFile* file)
128 AttrChanged(file);
132 void
133 AttrChanged(WatchedFile* file)
135 EntryRemoved(file);
136 EntryCreated(file);
140 void
141 EntriesCleared()
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);
151 fItemCount = 0;
152 fCountView->SetText("Count: 0");
156 private:
157 ListItem*
158 _AddSuperItem(const char* name, BObjectList<ListItem>& list,
159 ListItem* under)
161 ListItem* item = _FindStringItem(list, name, under);
162 if (item != NULL)
163 return item;
165 item = new ListItem(name);
166 fListView->AddUnder(item, under);
167 fListView->SortItemsUnder(under, true, StringItemComp);
168 list.AddItem(item);
170 fListView->Collapse(item);
172 return item;
175 ListItem*
176 _FindStringItem(BObjectList<ListItem>& list, const char* text,
177 ListItem* parent)
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)
183 continue;
184 if (strcmp(item->Text(), text) == 0)
185 return item;
187 return NULL;
190 BOutlineListView* fListView;
191 BStringView* fCountView;
193 BObjectList<ListItem> fArtistList;
194 BObjectList<ListItem> fAlbumList;
196 BString fQueryString;
197 int32 fItemCount;
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(),
228 layout->Right());
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,
240 fCountView);
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()
253 delete fQueryReader;
254 delete fQueryHandler;
255 delete fEntryViewInterface;
259 bool
260 MusicCollectionWindow::QuitRequested()
262 be_app->PostMessage(B_QUIT_REQUESTED);
263 return true;
267 void
268 MusicCollectionWindow::MessageReceived(BMessage* message)
270 switch (message->what) {
271 case kMsgQueryInput:
272 _StartNewQuery();
273 break;
275 case kMsgItemInvoked:
276 fFileListView->Launch(message);
277 break;
279 default:
280 BWindow::MessageReceived(message);
285 void
286 CaseInsensitiveString(BString &instring, BString &outstring)
288 outstring = "";
289 int i = 0;
290 while (instring[i])
292 if (instring[i] >= 65 && instring[i] <= 90) // capital letters
294 int ch = instring[i] + 32;
295 outstring += "[";
296 outstring += ch;
297 outstring += instring[i];
298 outstring += "]";
299 } else if (instring[i] >= 97 && instring[i] <= 122)
301 int ch = instring[i]-32;
302 outstring += "[";
303 outstring += instring[i];
304 outstring += ch;
305 outstring += "]";
306 } else
307 outstring += instring[i];
308 i++;
313 void
314 MusicCollectionWindow::_StartNewQuery()
316 fQueryReader->Reset();
317 fQueryHandler->Reset();
319 BString orgString = fQueryField->Text();
320 ((ListViewListener<FileListItem>*)fEntryViewInterface)->SetQueryString(
321 orgString);
323 BVolume volume;
324 //BVolumeRoster().GetBootVolume(&volume);
325 BVolumeRoster roster;
326 while (roster.GetNextVolume(&volume) == B_OK) {
327 if (!volume.KnowsQuery())
328 continue;
329 BQuery* query = _CreateQuery(orgString);
330 query->SetVolume(&volume);
331 fQueryReader->AddQuery(query);
334 fQueryReader->Run();
338 BQuery*
339 MusicCollectionWindow::_CreateQuery(BString& orgString)
341 BQuery* query = new BQuery;
343 BString queryString;
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);
353 query->PushOp(B_OR);
355 query->PushAttr("Audio:Artist");
356 query->PushString(queryString);
357 query->PushOp(B_CONTAINS);
358 query->PushOp(B_OR);
360 if (queryString == "") {
361 query->PushAttr("BEOS:TYPE");
362 query->PushString("audio/");
363 query->PushOp(B_BEGINS_WITH);
364 query->PushOp(B_OR);
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);
375 query->PushOp(B_OR);
377 return query;