Fix several problems with new DynamicBias
[amarok:rengelss-amarok.git] / src / dynamic / biases / IfElseBias.cpp
1 /****************************************************************************************
2  * Copyright (c) 2011 Ralf Engels <ralf-engels@gmx.de>                                  *
3  *                                                                                      *
4  * This program is free software; you can redistribute it and/or modify it under        *
5  * the terms of the GNU General Public License as published by the Free Software        *
6  * Foundation; either version 2 of the License, or (at your option) version 3 or        *
7  * any later version accepted by the membership of KDE e.V. (or its successor approved  *
8  * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of  *
9  * version 3 of the license.                                                            *
10  *                                                                                      *
11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
13  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
14  *                                                                                      *
15  * You should have received a copy of the GNU General Public License along with         *
16  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
17  ****************************************************************************************/
18
19 #define DEBUG_PREFIX "IfElseBias"
20
21 #include "IfElseBias.h"
22
23 #include "amarokconfig.h"
24 #include "core/support/Debug.h"
25 // #include "DynamicBiasWidgets.h"
26
27 #include <QtGlobal> // for qRound
28 #include <QPainter>
29 #include <QXmlStreamReader>
30 #include <QXmlStreamReader>
31 #include <QXmlStreamWriter>
32
33 #include <klocale.h>
34
35 QString
36 Dynamic::IfElseBiasFactory::i18nName() const
37 { return i18nc("Name of the \"IfElse\" bias", "If Else"); }
38
39 QString
40 Dynamic::IfElseBiasFactory::name() const
41 { return Dynamic::IfElseBias::sName(); }
42
43 QString
44 Dynamic::IfElseBiasFactory::i18nDescription() const
45 { return i18nc("Description of the \"IfElse\" bias",
46                    "The \"IfElse\" bias adds tracks they match at least one of the sub biases. It will only check the second sub-bias if the first doesn't return any results."); }
47
48 Dynamic::BiasPtr
49 Dynamic::IfElseBiasFactory::createBias()
50 { return Dynamic::BiasPtr( new Dynamic::IfElseBias() ); }
51
52
53
54
55 Dynamic::IfElseBias::IfElseBias()
56     : OrBias()
57 { }
58
59 QString
60 Dynamic::IfElseBias::sName()
61 {
62     return QLatin1String( "ifElseBias" );
63 }
64
65 QString
66 Dynamic::IfElseBias::name() const
67 {
68     return Dynamic::IfElseBias::sName();
69 }
70
71 QString
72 Dynamic::IfElseBias::toString() const
73 {
74     return i18nc("IfElse bias representation", "Match all sequentially");
75 }
76
77 void
78 Dynamic::IfElseBias::paintOperator( QPainter* painter, const QRect& rect, Dynamic::AbstractBias* bias )
79 {
80     if( m_biases.indexOf( Dynamic::BiasPtr(bias) ) > 0 )
81         painter->drawText( rect.adjusted(2, 0, -2, 0),
82                            Qt::AlignRight,
83                            i18nc("Prefix for IfElseBias. Shown in front of a bias in the dynamic playlist view", "else" ) );
84 }
85
86 Dynamic::TrackSet
87 Dynamic::IfElseBias::matchingTracks( int position,
88                                      const Meta::TrackList& playlist,
89                                      int contextCount,
90                                      Dynamic::TrackCollectionPtr universe ) const
91 {
92     // store the parameters in case we need to request additional matching tracks later
93     m_position = position;
94     m_playlist = playlist;
95     m_contextCount = contextCount;
96     m_universe = universe;
97
98     m_tracks = Dynamic::TrackSet( universe, false );
99     m_outstandingMatches = 0;
100
101     foreach( Dynamic::BiasPtr bias, m_biases )
102     {
103         m_tracks = bias->matchingTracks( position, playlist, contextCount, universe );
104         if( m_tracks.isOutstanding() )
105         {
106             m_outstandingMatches++;
107             return m_tracks;
108         }
109         else
110         {
111             removeDuplicate();
112             if( !m_tracks.isEmpty() ) {
113                 return m_tracks;
114             }
115         }
116     }
117
118     return m_tracks;
119 }
120
121 void
122 Dynamic::IfElseBias::resultReceived( const Dynamic::TrackSet &tracks )
123 {
124     m_tracks = tracks;
125     --m_outstandingMatches;
126
127     // we got some tracks result
128     removeDuplicate();
129     if( !m_tracks.isEmpty() )
130     {
131         emit resultReady( m_tracks );
132         return;
133     }
134
135     // ok. check the next biases
136     bool alreadyChecked = true;
137     foreach( Dynamic::BiasPtr bias, m_biases )
138     {
139         // jump over already checked biases
140         if( bias.data() == sender() )
141         {
142             alreadyChecked = false;
143             continue;
144         }
145         else if( alreadyChecked )
146         {
147             continue;
148         }
149
150         // check the next bias
151         m_tracks = bias->matchingTracks( m_position, m_playlist,
152                                          m_contextCount, m_universe );
153         if( m_tracks.isOutstanding() )
154         {
155             m_outstandingMatches++;
156             return; // wait for the next results
157         }
158         else
159         {
160             removeDuplicate();
161             if( !m_tracks.isEmpty() ) {
162                 emit resultReady( m_tracks );
163                 return;
164             }
165         }
166     }
167     emit resultReady( m_tracks );
168 }
169
170 // we need to eliminate duplicates now to have a propper check for an empty result
171 void
172 Dynamic::IfElseBias::removeDuplicate() const
173 {
174     if( AmarokConfig::dynamicDuplicates() )
175         return;
176
177     for( int i = 0; i < m_position; i++ )
178         if( m_playlist[i] )
179             m_tracks.subtract( m_playlist[i] );
180 }
181
182 #include "IfElseBias.moc"
183