Added playlist actions (insert, delete, move up, move down), with only insert working...
[kworship.git] / kworship / songdb / KwSongdbFilterNode.cpp
blob537637c2fd1154fd96a5995099d728d1039cb24a
1 /***************************************************************************
2 * This file is part of KWorship. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
5 * KWorship 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 * KWorship 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 KWorship. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
20 /**
21 * @file KwSongdbFilterNode.cpp
22 * @brief A node for filtering songs.
23 * @author James Hogan <james@albanarts.com>
26 #include "KwSongdbFilterNode.h"
27 #include "KwSongdbVersionNode.h"
28 #include "KwSongdb.h"
30 #include <QSqlQuery>
32 #include <cassert>
35 * Constructors + destructor.
38 /// Primary constructor.
39 KwSongdbFilterNode::KwSongdbFilterNode(const KwSongdbFilterLevelList* filters, QString label, KwSongdbNode* parent)
40 : KwSongdbNode(parent)
41 , m_label(label)
42 , m_filterLevels(filters)
43 , m_currentFilter(0)
44 , m_knownValue()
45 , m_query(0)
47 assert(0 != filters);
48 assert(filters->size() > 0);
49 m_knownValue.next = 0;
50 setupQuery();
53 /// Destructor.
54 KwSongdbFilterNode::~KwSongdbFilterNode()
56 delete m_query;
60 * Private constructors
63 /// Primary constructor.
64 KwSongdbFilterNode::KwSongdbFilterNode(KwSongdbFilterNode* parent, QString label, QString knownIdExpression, int knownId)
65 : KwSongdbNode(parent)
66 , m_label(label)
67 , m_filterLevels(parent->m_filterLevels)
68 , m_currentFilter(parent->m_currentFilter + 1)
69 , m_knownValue()
70 , m_query(0)
72 m_knownValue.idExpression = knownIdExpression;
73 m_knownValue.idValue = knownId;
74 m_knownValue.next = &parent->m_knownValue;
75 setupQuery();
79 * Associated data access
82 KwSongdbSong* KwSongdbFilterNode::associatedSong()
84 KnownValue* val = &m_knownValue;
85 while (val->next)
87 if (val->idExpression == "`Song`.`id`")
89 return KwSongdb::self()->songById(val->idValue);
91 val = val->next;
93 return 0;
96 KwSongdbVersion* KwSongdbFilterNode::associatedSongVersion()
98 // If only the one child, ask it
99 if (getChildCount() == 1)
101 KwSongdbNode* child = dynamic_cast<KwSongdbNode*>(getChild(0));
102 if (0 != child)
104 return child->associatedSongVersion();
107 return 0;
111 * Main interface
114 /// Get data associated with the node.
115 QVariant KwSongdbFilterNode::getData(int role, int column)
117 if (role == Qt::DisplayRole)
119 if (column == 0)
121 return m_label;
124 else if (role == Qt::DecorationRole)
126 // Use icon of previous filter
127 if (column == 0 && m_currentFilter > 0)
129 return (*m_filterLevels)[m_currentFilter - 1].icon;
132 return QVariant();
135 /// Get the number of children.
136 int KwSongdbFilterNode::getChildCount() const
138 int rows = 0;
139 if (m_query->isActive())
141 rows = m_query->size();
142 if (rows == -1)
144 if (m_query->first())
146 rows = 1;
147 while (m_query->next())
149 ++rows;
153 assert(rows != -1);
155 return rows;
158 /// Get a child node by index.
159 KwSongdbNode* KwSongdbFilterNode::_getChild(int index)
161 bool seekResult = m_query->seek(index);
162 if (seekResult)
164 /// @todo implement "end condition"
165 if (m_currentFilter < m_filterLevels->size() - 1)
167 return _newNode(m_query->value(1).toString(),
168 (*m_filterLevels)[m_currentFilter].idExpression, m_query->value(0).toInt());
170 else
172 assert(m_currentFilter == m_filterLevels->size() - 1);
173 return _newFinalNode(m_query->value(1).toString(), m_query->value(0).toInt(),
174 (*m_filterLevels)[m_currentFilter].icon);
177 else
179 return 0;
183 /// Get flags for this item.
184 Qt::ItemFlags KwSongdbFilterNode::getFlags(Qt::ItemFlags defaultFlags) const
186 Qt::ItemFlags flags = defaultFlags;
187 // Only allow dragging if only one final song version within
188 /// @todo improve so it works at 3 levels
189 if (m_currentFilter == m_filterLevels->size()-1 && m_query->size() == 1)
191 flags |= Qt::ItemIsDragEnabled;
193 return flags;
196 /// Get mime data string for this set of songs.
197 QString KwSongdbFilterNode::mimeData()
199 // If a single child node, ask that
200 assert(m_currentFilter == m_filterLevels->size()-1 && m_query->size() == 1);
201 return _getChild(0)->mimeData();
204 /// Get a new node of this type.
205 KwSongdbFilterNode* KwSongdbFilterNode::_newNode(QString label, QString idExpression, int idValue)
207 return new KwSongdbFilterNode(this, label, idExpression, idValue);
210 /// Get a new final node.
211 KwSongdbNode* KwSongdbFilterNode::_newFinalNode(QString label, int id, const QIcon& icon)
213 KwSongdbVersionNode* node = new KwSongdbVersionNode(this, label, id);
214 node->setIcon(icon);
215 return node;
219 * Private functions
222 /// Setup the query.
223 void KwSongdbFilterNode::setupQuery()
225 if (0 == m_query)
227 // Collect joins and where conditions
228 QString innerJoins;
229 QStringList whereClauses;
230 for (int i = 0; i <= m_currentFilter; ++i)
232 const KwSongdbFilterLevel& filterI = m_filterLevels->at(i);
233 QStringList::const_iterator it;
234 for (it = filterI.innerJoinClauses.begin(); it != filterI.innerJoinClauses.end(); ++it)
236 innerJoins += "INNER JOIN " + (*it) + " ";
238 whereClauses << filterI.whereClauses;
240 KnownValue* knownValue = &m_knownValue;
241 while (0 != knownValue->next)
243 whereClauses << (knownValue->idExpression + " = ?");
244 knownValue = knownValue->next;
247 // Generate the SQL query
248 const KwSongdbFilterLevel& filterLevel = m_filterLevels->at(m_currentFilter);
249 QString query = "SELECT " + filterLevel.idExpression + " AS id,"
250 + filterLevel.labelExpression + " AS label "
251 "FROM " + m_filterLevels->at(0).tableName + " ";
252 query += innerJoins;
253 if (!whereClauses.empty())
255 query += "WHERE " + whereClauses.join(" AND ") + " ";
257 if (!filterLevel.orderBy.empty())
259 query += "ORDER BY " + filterLevel.orderBy.join(",");
261 query += ";";
263 // perform the query
264 m_query = new QSqlQuery();
265 m_query->prepare(query);
266 knownValue = &m_knownValue;
267 while (0 != knownValue->next)
269 m_query->addBindValue(knownValue->idValue);
270 knownValue = knownValue->next;
272 m_query->exec();