Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

media library: add new logic for advanced filtering using a smartplay…

…list

There are three new Container info booleans for skins: Container.CanFilter,
Container.CanFilterAdvanced and Container.Filtered where CanFilter and
CanFilterAdvanced are mutually exclusive. These can be used for visibility
conditions of the existing "Filter" button and a new "Filter" button for
advanced filtering.
Furthermore a new action "filter" is available which will open the respective
filter dialog depending on whether the container/list supports simple or
advanced filtering.
  • Loading branch information...
commit b0272427083c0f2820a3b282a6141d17520c25c1 1 parent 221eaf9
@Montellese authored
View
23 xbmc/GUIInfoManager.cpp
@@ -431,7 +431,10 @@ const infomap container_bools[] ={{ "onnext", CONTAINER_MOVE_NEXT },
{ "currentpage", CONTAINER_CURRENT_PAGE },
{ "scrolling", CONTAINER_SCROLLING },
{ "hasnext", CONTAINER_HAS_NEXT },
- { "hasprevious", CONTAINER_HAS_PREVIOUS }};
+ { "hasprevious", CONTAINER_HAS_PREVIOUS },
+ { "canfilter", CONTAINER_CAN_FILTER },
+ { "canfilteradvanced",CONTAINER_CAN_FILTERADVANCED },
+ { "filtered", CONTAINER_FILTERED }};
const infomap container_ints[] = {{ "row", CONTAINER_ROW },
{ "column", CONTAINER_COLUMN },
@@ -2204,6 +2207,24 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
bReturn = control->GetCondition(condition, 0);
}
}
+ else if (condition == CONTAINER_CAN_FILTER)
+ {
+ CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW);
+ if (window)
+ bReturn = !((CGUIMediaWindow*)window)->CanFilterAdvanced();
+ }
+ else if (condition == CONTAINER_CAN_FILTERADVANCED)
+ {
+ CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW);
+ if (window)
+ bReturn = ((CGUIMediaWindow*)window)->CanFilterAdvanced();
+ }
+ else if (condition == CONTAINER_FILTERED)
+ {
+ CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW);
+ if (window)
+ bReturn = ((CGUIMediaWindow*)window)->IsFiltered();
+ }
else if (condition == VIDEOPLAYER_HAS_INFO)
bReturn = ((m_currentFile->HasVideoInfoTag() && !m_currentFile->GetVideoInfoTag()->IsEmpty()) ||
(m_currentFile->HasPVRChannelInfoTag() && !m_currentFile->GetPVRChannelInfoTag()->IsEmpty()));
View
4 xbmc/GUIInfoManager.h
@@ -289,6 +289,10 @@ namespace INFO
#define LASTFM_CANLOVE 331
#define LASTFM_CANBAN 332
+#define CONTAINER_CAN_FILTER 342
+#define CONTAINER_CAN_FILTERADVANCED 343
+#define CONTAINER_FILTERED 344
+
#define CONTAINER_SCROLL_PREVIOUS 345 // NOTE: These 5 must be kept in this consecutive order
#define CONTAINER_MOVE_PREVIOUS 346
#define CONTAINER_STATIC 347
View
2  xbmc/guilib/Key.h
@@ -309,6 +309,8 @@
#define ACTION_SUBTITLE_VSHIFT_DOWN 231 // shift down subtitles in DVDPlayer
#define ACTION_SUBTITLE_ALIGN 232 // toggle vertical alignment of subtitles
+#define ACTION_FILTER 233
+
// Window ID defines to make the code a bit more readable
#define WINDOW_INVALID 9999
#define WINDOW_HOME 10000
View
1  xbmc/input/ButtonTranslator.cpp
@@ -189,6 +189,7 @@ static const ActionMapping actions[] =
{"jumpsms7" , ACTION_JUMP_SMS7},
{"jumpsms8" , ACTION_JUMP_SMS8},
{"jumpsms9" , ACTION_JUMP_SMS9},
+ {"filter" , ACTION_FILTER},
{"filterclear" , ACTION_FILTER_CLEAR},
{"filtersms2" , ACTION_FILTER_SMS2},
{"filtersms3" , ACTION_FILTER_SMS3},
View
9 xbmc/music/windows/GUIWindowMusicBase.cpp
@@ -1350,6 +1350,15 @@ void CGUIWindowMusicBase::OnPrepareFileItems(CFileItemList &items)
{
}
+bool CGUIWindowMusicBase::CheckFilterAdvanced(CFileItemList &items)
+{
+ CStdString content = items.GetContent();
+ if (items.IsMusicDb() && (content.Equals("artists") || content.Equals("albums") || content.Equals("songs")))
+ return true;
+
+ return false;
+}
+
void CGUIWindowMusicBase::OnInitWindow()
{
CGUIMediaWindow::OnInitWindow();
View
2  xbmc/music/windows/GUIWindowMusicBase.h
@@ -71,6 +71,8 @@ class CGUIWindowMusicBase : public CGUIMediaWindow
virtual void OnPrepareFileItems(CFileItemList &items);
virtual CStdString GetStartFolder(const CStdString &dir);
+ virtual bool CheckFilterAdvanced(CFileItemList &items);
+
// new methods
virtual void PlayItem(int iItem);
virtual bool OnPlayMedia(int iItem);
View
2  xbmc/music/windows/GUIWindowMusicNav.cpp
@@ -272,7 +272,7 @@ bool CGUIWindowMusicNav::Update(const CStdString &strDirectory)
if (CGUIWindowMusicBase::Update(strDirectory))
{
- m_thumbLoader.Load(*m_vecItems);
+ m_thumbLoader.Load(*m_unfilteredItems);
return true;
}
View
9 xbmc/video/windows/GUIWindowVideoBase.cpp
@@ -1830,6 +1830,15 @@ void CGUIWindowVideoBase::OnPrepareFileItems(CFileItemList &items)
{
}
+bool CGUIWindowVideoBase::CheckFilterAdvanced(CFileItemList &items)
+{
+ CStdString content = items.GetContent();
+ if (items.IsVideoDb() && (content.Equals("movies") || content.Equals("tvshows") || content.Equals("episodes") || content.Equals("musicvideos")))
+ return true;
+
+ return false;
+}
+
void CGUIWindowVideoBase::AddToDatabase(int iItem)
{
if (iItem < 0 || iItem >= m_vecItems->Size())
View
2  xbmc/video/windows/GUIWindowVideoBase.h
@@ -89,6 +89,8 @@ class CGUIWindowVideoBase : public CGUIMediaWindow, public IBackgroundLoaderObse
virtual void OnItemLoaded(CFileItem* pItem) {};
virtual void OnPrepareFileItems(CFileItemList &items);
+ virtual bool CheckFilterAdvanced(CFileItemList &items);
+
virtual void GetContextButtons(int itemNumber, CContextButtons &buttons);
void GetNonContextButtons(int itemNumber, CContextButtons &buttons);
virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button);
View
18 xbmc/video/windows/GUIWindowVideoNav.cpp
@@ -527,8 +527,24 @@ void CGUIWindowVideoNav::UpdateButtons()
bool CGUIWindowVideoNav::GetFilteredItems(const CStdString &filter, CFileItemList &items)
{
- bool listchanged = CGUIMediaWindow::GetFilteredItems(filter, items);
+ bool listchanged = false;
+ bool updateItems = false;
+ if (!m_canFilterAdvanced)
+ listchanged = CGUIMediaWindow::GetFilteredItems(filter, items);
+ else
+ listchanged = CGUIMediaWindow::GetAdvanceFilteredItems(items, updateItems);
+
listchanged |= ApplyWatchedFilter(items);
+
+ // there are new items so we need to run the thumbloader
+ if (updateItems)
+ {
+ if (m_thumbLoader.IsLoading())
+ m_thumbLoader.StopThread();
+
+ m_thumbLoader.Load(items);
+ }
+
return listchanged;
}
View
188 xbmc/windows/GUIMediaWindow.cpp
@@ -64,16 +64,18 @@
#include "interfaces/python/XBPython.h"
#endif
#include "interfaces/Builtins.h"
+#include "dialogs/GUIDialogMediaFilter.h"
+#include "filesystem/SmartPlaylistDirectory.h"
#if defined(TARGET_ANDROID)
#include "xbmc/android/activity/XBMCApp.h"
#endif
-#define CONTROL_BTNVIEWASICONS 2
-#define CONTROL_BTNSORTBY 3
-#define CONTROL_BTNSORTASC 4
-#define CONTROL_BTN_FILTER 19
+#define CONTROL_BTNVIEWASICONS 2
+#define CONTROL_BTNSORTBY 3
+#define CONTROL_BTNSORTASC 4
+#define CONTROL_BTN_FILTER 19
-#define CONTROL_LABELFILES 12
+#define CONTROL_LABELFILES 12
using namespace std;
using namespace ADDON;
@@ -87,6 +89,7 @@ CGUIMediaWindow::CGUIMediaWindow(int id, const char *xmlFile)
m_vecItems->SetPath("?");
m_iLastControl = -1;
m_iSelectedItem = -1;
+ m_canFilterAdvanced = false;
m_guiState.reset(CGUIViewState::GetViewState(GetID(), *m_vecItems));
}
@@ -175,6 +178,9 @@ bool CGUIMediaWindow::OnAction(const CAction &action)
if (CGUIWindow::OnAction(action))
return true;
+ if (action.GetID() == ACTION_FILTER)
+ return Filter();
+
// live filtering
if (action.GetID() == ACTION_FILTER_CLEAR)
{
@@ -273,22 +279,10 @@ bool CGUIMediaWindow::OnMessage(CGUIMessage& message)
}
else if (iControl == CONTROL_BTN_FILTER)
{
- if (GetControl(iControl)->GetControlType() == CGUIControl::GUICONTROL_EDIT)
- { // filter updated
- CGUIMessage selected(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_BTN_FILTER);
- OnMessage(selected);
- OnFilterItems(selected.GetLabel());
+ if (m_canFilterAdvanced)
return true;
- }
- if (GetProperty("filter").empty())
- {
- CStdString filter = GetProperty("filter").asString();
- CGUIKeyboardFactory::ShowAndGetFilter(filter, false);
- SetProperty("filter", filter);
- }
- else
- OnFilterItems("");
- return true;
+
+ return Filter();
}
else if (m_viewControl.HasControl(iControl)) // list/thumb control
{
@@ -415,16 +409,21 @@ bool CGUIMediaWindow::OnMessage(CGUIMessage& message)
}
else if (message.GetParam1() == GUI_MSG_FILTER_ITEMS && IsActive())
{
- CStdString filter(GetProperty("filter").asString());
- if (message.GetParam2() == 1) // append
- filter += message.GetStringParam();
- else if (message.GetParam2() == 2)
- { // delete
- if (filter.size())
- filter = filter.Left(filter.size() - 1);
+ CStdString filter;
+ // check if this is meant for advanced filtering
+ if (message.GetParam2() != 10)
+ {
+ filter = GetProperty("filter").asString();
+ if (message.GetParam2() == 1) // append
+ filter += message.GetStringParam();
+ else if (message.GetParam2() == 2)
+ { // delete
+ if (filter.size())
+ filter = filter.Left(filter.size() - 1);
+ }
+ else
+ filter = message.GetStringParam();
}
- else
- filter = message.GetStringParam();
OnFilterItems(filter);
return true;
}
@@ -561,10 +560,8 @@ void CGUIMediaWindow::UpdateButtons()
items.Format("%i %s", m_vecItems->GetObjectCount(), g_localizeStrings.Get(127).c_str());
SET_CONTROL_LABEL(CONTROL_LABELFILES, items);
- //#ifdef PRE_SKIN_VERSION_3
- SET_CONTROL_SELECTED(GetID(),CONTROL_BTN_FILTER, !GetProperty("filter").empty());
- SET_CONTROL_LABEL2(CONTROL_BTN_FILTER, GetProperty("filter").asString());
- //#endif
+ if (!m_canFilterAdvanced)
+ SET_CONTROL_LABEL2(CONTROL_BTN_FILTER, GetProperty("filter").asString());
}
void CGUIMediaWindow::ClearFileItems()
@@ -700,6 +697,7 @@ bool CGUIMediaWindow::GetDirectory(const CStdString &strDirectory, CFileItemList
// clear the filter
SetProperty("filter", "");
+ m_filter.Reset();
return true;
}
@@ -781,6 +779,11 @@ bool CGUIMediaWindow::Update(const CStdString &strDirectory)
}
m_iLastControl = GetFocusedControlID();
+ // Check whether to enabled advanced filtering based on the content type
+ m_canFilterAdvanced = CheckFilterAdvanced(*m_vecItems);
+ if (m_canFilterAdvanced)
+ m_filter.SetType(m_vecItems->GetContent());
+
// Ask the derived class if it wants to load additional info
// for the fileitems like media info or additional
// filtering on the items, setting thumbs.
@@ -1543,7 +1546,9 @@ void CGUIMediaWindow::OnFilterItems(const CStdString &filter)
{
m_vecItems->ClearItems();
m_vecItems->Append(items);
- SetProperty("filter", filter);
+
+ if (!m_canFilterAdvanced)
+ SetProperty("filter", filter);
}
// and update our view control + buttons
@@ -1554,6 +1559,12 @@ void CGUIMediaWindow::OnFilterItems(const CStdString &filter)
bool CGUIMediaWindow::GetFilteredItems(const CStdString &filter, CFileItemList &items)
{
+ if (m_canFilterAdvanced)
+ {
+ bool hasNewItems;
+ return GetAdvanceFilteredItems(items, hasNewItems);
+ }
+
CStdString trimmedFilter(filter);
trimmedFilter.TrimLeft().ToLower();
@@ -1593,7 +1604,114 @@ bool CGUIMediaWindow::GetFilteredItems(const CStdString &filter, CFileItemList &
items.ClearItems();
items.Append(filteredItems);
- return (items.GetObjectCount() > 0);
+
+ return items.GetObjectCount() > 0;
+}
+
+bool CGUIMediaWindow::GetAdvanceFilteredItems(CFileItemList &items, bool &hasNewItems)
+{
+ hasNewItems = false;
+
+ if (m_filter.IsEmpty())
+ return true;
+
+ CFileItemList resultItems;
+ XFILE::CSmartPlaylistDirectory::GetDirectory(m_filter, resultItems, m_vecItems->GetPath(), true);
+
+ // put together a lookup map for faster path comparison
+ map<CStdString, CFileItemPtr> lookup;
+ for (int j = 0; j < resultItems.Size(); j++)
+ {
+ CStdString itemPath = resultItems[j]->GetPath();
+ size_t pos = itemPath.find('?');
+ if (pos != string::npos)
+ itemPath.erase(pos);
+ itemPath.ToLower();
+
+ lookup[itemPath] = resultItems[j];
+ }
+
+ // loop through all the original items and find
+ // those which are still part of the filter
+ CFileItemList filteredItems;
+ for (int i = 0; i < items.Size(); i++)
+ {
+ CFileItemPtr item = items.Get(i);
+ if (item->IsParentFolder())
+ {
+ filteredItems.Add(item);
+ continue;
+ }
+
+ // check if the item is part of the resultItems list
+ // by comparing their paths (but ignoring any special
+ // options because they differ from filter to filter)
+ CStdString path = item->GetPath();
+ size_t pos = path.find('?');
+ if (pos != string::npos)
+ path.erase(pos);
+ path.ToLower();
+
+ map<CStdString, CFileItemPtr>::iterator itItem = lookup.find(path);
+ if (itItem != lookup.end())
+ {
+ // we need to copy the path of the filtered
+ // item to be able to keep the applied filters
+ item->SetPath(itItem->second->GetPath());
+
+ // add the item to the list of filtered items
+ filteredItems.Add(item);
+
+ // remove the item from the lists
+ resultItems.Remove(itItem->second.get());
+ lookup.erase(itItem);
+ }
+ }
+
+ if (resultItems.Size() > 0)
+ {
+ filteredItems.Append(resultItems);
+ hasNewItems = true;
+ }
+
+ items.ClearItems();
+ items.Append(filteredItems);
+ return true;
+}
+
+bool CGUIMediaWindow::IsFiltered()
+{
+ return (!m_canFilterAdvanced && !GetProperty("filter").empty()) ||
+ (m_canFilterAdvanced && !m_filter.IsEmpty());
+}
+
+bool CGUIMediaWindow::Filter()
+{
+ // basic filtering
+ if (!m_canFilterAdvanced)
+ {
+ const CGUIControl *btnFilter = GetControl(CONTROL_BTN_FILTER);
+ if (btnFilter != NULL && btnFilter->GetControlType() == CGUIControl::GUICONTROL_EDIT)
+ { // filter updated
+ CGUIMessage selected(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_BTN_FILTER);
+ OnMessage(selected);
+ OnFilterItems(selected.GetLabel());
+ return true;
+ }
+ if (GetProperty("filter").empty())
+ {
+ CStdString filter = GetProperty("filter").asString();
+ CGUIKeyboardFactory::ShowAndGetFilter(filter, false);
+ SetProperty("filter", filter);
+ }
+ else
+ OnFilterItems("");
+ }
+ // advanced filtering
+ else
+ CGUIDialogMediaFilter::ShowAndEditMediaFilter(m_vecItems->GetPath(), m_filter);
+
+ return true;
}
CStdString CGUIMediaWindow::GetStartFolder(const CStdString &dir)
View
18 xbmc/windows/GUIMediaWindow.h
@@ -25,6 +25,7 @@
#include "filesystem/DirectoryHistory.h"
#include "GUIViewControl.h"
#include "dialogs/GUIDialogContextMenu.h"
+#include "playlists/SmartPlayList.h"
class CFileItemList;
@@ -47,6 +48,9 @@ class CGUIMediaWindow : public CGUIWindow
virtual CFileItemPtr GetCurrentListItem(int offset = 0);
const CGUIViewState *GetViewState() const;
+ virtual bool CanFilterAdvanced() { return m_canFilterAdvanced; }
+ virtual bool IsFiltered();
+
protected:
virtual void LoadAdditionalTags(TiXmlElement *root);
CGUIControl *GetFirstFocusableControl(int id);
@@ -73,6 +77,9 @@ class CGUIMediaWindow : public CGUIWindow
void ClearFileItems();
virtual void SortItems(CFileItemList &items);
+ virtual bool CheckFilterAdvanced(CFileItemList &items) { return false; }
+ virtual bool Filter();
+
/* \brief Called on response to a GUI_MSG_FILTER_ITEMS message
Filters the current list with the given filter using FilterItems()
\param filter the filter to use.
@@ -87,6 +94,14 @@ class CGUIMediaWindow : public CGUIWindow
*/
virtual bool GetFilteredItems(const CStdString &filter, CFileItemList &items);
+ /* \brief Retrieve the advance filtered item list
+ \param items CFileItemList to filter
+ \param hasNewItems Whether the filtered item list contains new items
+ which were not present in the original list
+ \sa GetFilteredItems
+ */
+ virtual bool GetAdvanceFilteredItems(CFileItemList &items, bool &hasNewItems);
+
// check for a disc or connection
virtual bool HaveDiscOrConnection(const CStdString& strPath, int iDriveType);
void ShowShareErrorMessage(CFileItem* pItem);
@@ -121,4 +136,7 @@ class CGUIMediaWindow : public CGUIWindow
int m_iLastControl;
int m_iSelectedItem;
CStdString m_startDirectory;
+
+ CSmartPlaylist m_filter;
+ bool m_canFilterAdvanced;
};
Please sign in to comment.
Something went wrong with that request. Please try again.