1 /***************************************************************************
2  *   Copyright (C) 2008-2021 by Andrzej Rybczak                            *
3  *   andrzej@rybczak.net                                                   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
19  ***************************************************************************/
20 
21 #ifndef NCMPCPP_SEARCH_ENGINE_H
22 #define NCMPCPP_SEARCH_ENGINE_H
23 
24 #include <cassert>
25 
26 #include "interfaces.h"
27 #include "mpdpp.h"
28 #include "regex_filter.h"
29 #include "screens/screen.h"
30 #include "song_list.h"
31 
32 struct SEItem
33 {
SEItemSEItem34 	SEItem() : m_is_song(false), m_buffer(0) { }
SEItemSEItem35 	SEItem(NC::Buffer *buf) : m_is_song(false), m_buffer(buf) { }
SEItemSEItem36 	SEItem(const MPD::Song &s) : m_is_song(true), m_song(s) { }
SEItemSEItem37 	SEItem(const SEItem &ei) { *this = ei; }
~SEItemSEItem38 	~SEItem() {
39 		if (!m_is_song)
40 			delete m_buffer;
41 	}
42 
mkBufferSEItem43 	NC::Buffer &mkBuffer() {
44 		assert(!m_is_song);
45 		delete m_buffer;
46 		m_buffer = new NC::Buffer();
47 		return *m_buffer;
48 	}
49 
isSongSEItem50 	bool isSong() const { return m_is_song; }
51 
bufferSEItem52 	NC::Buffer &buffer() { assert(!m_is_song && m_buffer); return *m_buffer; }
songSEItem53 	MPD::Song &song() { assert(m_is_song); return m_song; }
54 
bufferSEItem55 	const NC::Buffer &buffer() const { assert(!m_is_song && m_buffer); return *m_buffer; }
songSEItem56 	const MPD::Song &song() const { assert(m_is_song); return m_song; }
57 
58 	SEItem &operator=(const SEItem &se) {
59 		if (this == &se)
60 			return *this;
61 		m_is_song = se.m_is_song;
62 		if (se.m_is_song)
63 			m_song = se.m_song;
64 		else if (se.m_buffer)
65 			m_buffer = new NC::Buffer(*se.m_buffer);
66 		else
67 			m_buffer = 0;
68 		return *this;
69 	}
70 
71 private:
72 	bool m_is_song;
73 
74 	NC::Buffer *m_buffer;
75 	MPD::Song m_song;
76 };
77 
78 struct SearchEngineWindow: NC::Menu<SEItem>, SongList
79 {
SearchEngineWindowSearchEngineWindow80 	SearchEngineWindow() { }
SearchEngineWindowSearchEngineWindow81 	SearchEngineWindow(NC::Menu<SEItem> &&base)
82 	: NC::Menu<SEItem>(std::move(base)) { }
83 
84 	virtual SongIterator currentS() override;
85 	virtual ConstSongIterator currentS() const override;
86 	virtual SongIterator beginS() override;
87 	virtual ConstSongIterator beginS() const override;
88 	virtual SongIterator endS() override;
89 	virtual ConstSongIterator endS() const override;
90 
91 	virtual std::vector<MPD::Song> getSelectedSongs() override;
92 };
93 
94 struct SearchEngine: Screen<SearchEngineWindow>, Filterable, HasActions, HasSongs, Searchable, Tabbable
95 {
96 	SearchEngine();
97 
98 	// Screen<SearchEngineWindow> implementation
99 	virtual void resize() override;
100 	virtual void switchTo() override;
101 
102 	virtual std::wstring title() override;
typeSearchEngine103 	virtual ScreenType type() override { return ScreenType::SearchEngine; }
104 
updateSearchEngine105 	virtual void update() override { }
106 
107 	virtual void mouseButtonPressed(MEVENT me) override;
108 
isLockableSearchEngine109 	virtual bool isLockable() override { return true; }
isMergableSearchEngine110 	virtual bool isMergable() override { return true; }
111 
112 	// Searchable implementation
113 	virtual bool allowsSearching() override;
114 	virtual const std::string &searchConstraint() override;
115 	virtual void setSearchConstraint(const std::string &constraint) override;
116 	virtual void clearSearchConstraint() override;
117 	virtual bool search(SearchDirection direction, bool wrap, bool skip_current) override;
118 
119 	// Filterable implementation
120 	virtual bool allowsFiltering() override;
121 	virtual std::string currentFilter() override;
122 	virtual void applyFilter(const std::string &filter) override;
123 
124 	// HasActions implementation
125 	virtual bool actionRunnable() override;
126 	virtual void runAction() override;
127 
128 	// HasSongs implementation
129 	virtual bool itemAvailable() override;
130 	virtual bool addItemToPlaylist(bool play) override;
131 	virtual std::vector<MPD::Song> getSelectedSongs() override;
132 
133 	// private members
134 	void reset();
135 
136 	static size_t StaticOptions;
137 	static size_t SearchButton;
138 	static size_t ResetButton;
139 
140 private:
141 	void Prepare();
142 	void Search();
143 
144 	Regex::ItemFilter<SEItem> m_search_predicate;
145 
146 	const char **SearchMode;
147 
148 	static const char *SearchModes[];
149 
150 	static const size_t ConstraintsNumber = 11;
151 	static const char *ConstraintsNames[];
152 	std::string itsConstraints[ConstraintsNumber];
153 
154 	static bool MatchToPattern;
155 };
156 
157 extern SearchEngine *mySearcher;
158 
159 #endif // NCMPCPP_SEARCH_ENGINE_H
160 
161