13 * |
13 * |
14 * Description: |
14 * Description: |
15 * |
15 * |
16 */ |
16 */ |
17 |
17 |
|
18 // System includes |
|
19 #include <QSqlDatabase> |
|
20 #include <QFile> |
|
21 #include <QDateTime> |
|
22 #include <QVariant> |
|
23 #include <QStringList> |
|
24 #include <QSqlError> |
|
25 #include <QSqlQueryModel> |
|
26 #include <QSqlRecord> |
|
27 |
|
28 // User includes |
18 #include "radiohistorymodel_p.h" |
29 #include "radiohistorymodel_p.h" |
|
30 #include "radiohistorymodel.h" |
19 #include "radiohistoryitem.h" |
31 #include "radiohistoryitem.h" |
|
32 #include "radiohistoryitem_p.h" |
|
33 #include "radiostation.h" |
|
34 #include "radiologger.h" |
|
35 |
|
36 const char* DATABASE_NAME = "radioplayhistory.db"; |
|
37 const char* DATABASE_DRIVER = "QSQLITE"; |
|
38 const char* HISTORY_TABLE = "history"; |
|
39 const char* SQL_CREATE_TABLE = "CREATE TABLE history (" |
|
40 "id INTEGER PRIMARY KEY AUTOINCREMENT, " |
|
41 "artist TEXT NOT NULL, " |
|
42 "title TEXT NOT NULL, " |
|
43 "station TEXT NOT NULL, " |
|
44 "frequency INTEGER NOT NULL, " |
|
45 "tagged INTEGER NOT NULL DEFAULT 0, " |
|
46 "fromRds INTEGER NOT NULL DEFAULT 1, " |
|
47 "time TIMESTAMP NOT NULL)"; |
|
48 |
|
49 const char* SQL_ADD_ITEM = "INSERT INTO history (artist,title,station,frequency,fromRds,time) " |
|
50 "VALUES ( ?,?,?,?,?,? )"; |
|
51 |
|
52 const char* SQL_SELECT_ALL = "SELECT * FROM history ORDER BY id DESC"; |
|
53 const char* SQL_SELECT_TAGGED = "SELECT * FROM history WHERE tagged=1";// ORDER BY id DESC"; |
|
54 |
|
55 const char* SQL_DELETE_ALL = "DELETE FROM history"; |
|
56 |
|
57 //static const char* SQL_FIND_ITEM_BY_ID = "SELECT * FROM history WHERE id = ?"; |
|
58 const char* SQL_TOGGLE_TAG = "UPDATE history SET tagged = ? WHERE id = ?"; |
|
59 |
|
60 |
|
61 #ifdef LOGGING_ENABLED |
|
62 # define GET_ERR( param ) GETSTRING( param.lastError().text() ) |
|
63 # define GET_ERR_PTR( param ) GETSTRING( param->lastError().text() ) |
|
64 #endif // LOGGING_ENABLED |
|
65 |
|
66 /*! |
|
67 * Static utility function to parse a frequency |
|
68 */ |
|
69 static QString parseFrequency( const uint frequency ) |
|
70 { |
|
71 QString loc = qtTrId( "txt_rad_dblist_val_l1_mhz" ); |
|
72 return loc.arg( RadioStation::parseFrequency( frequency ) ); |
|
73 } |
20 |
74 |
21 /*! |
75 /*! |
22 * |
76 * |
23 */ |
77 */ |
24 RadioHistoryModelPrivate::RadioHistoryModelPrivate( RadioHistoryModel* model, |
78 RadioHistoryModelPrivate::RadioHistoryModelPrivate( RadioHistoryModel* model, |
25 RadioUiEngine& uiEngine ) : |
79 RadioUiEngine& uiEngine ) : |
26 q_ptr( model ), |
80 q_ptr( model ), |
27 mUiEngine( uiEngine ), |
81 mUiEngine( uiEngine ), |
28 mTopItemIsPlaying( false ), |
82 mTopItemIsPlaying( false ), |
29 mShowDetails( false ) |
83 mShowDetails( true ), |
30 { |
84 mViewMode( ShowAll ), |
31 |
85 mRtItemClass( -1 ) |
|
86 { |
32 } |
87 } |
33 |
88 |
34 /*! |
89 /*! |
35 * |
90 * |
36 */ |
91 */ |
37 RadioHistoryModelPrivate::~RadioHistoryModelPrivate() |
92 RadioHistoryModelPrivate::~RadioHistoryModelPrivate() |
38 { |
93 { |
39 |
94 if ( mDatabase && mDatabase->isOpen() ) { |
40 } |
95 mDatabase->close(); |
|
96 } |
|
97 } |
|
98 |
|
99 /*! |
|
100 * |
|
101 */ |
|
102 bool RadioHistoryModelPrivate::connectToDatabase() |
|
103 { |
|
104 LOG_METHOD; |
|
105 QSqlDatabase db = QSqlDatabase::addDatabase( DATABASE_DRIVER ); |
|
106 if ( db.isValid() ) { |
|
107 mDatabase.reset( new QSqlDatabase( db ) ); |
|
108 mDatabase->setDatabaseName( DATABASE_NAME ); |
|
109 |
|
110 if ( !mDatabase->open() ) { |
|
111 LOG_FORMAT( "Failed to open database! error = %s", GET_ERR_PTR( mDatabase ) ); |
|
112 mDatabase.reset(); |
|
113 return false; |
|
114 } |
|
115 |
|
116 // Create the table if it does not exist |
|
117 if ( !mDatabase->tables().contains( HISTORY_TABLE ) ) { |
|
118 LOG( "RadioHistoryModelPrivate::connectToDatabase: Creating database tables." ); |
|
119 QSqlQuery query; |
|
120 if ( !query.exec( SQL_CREATE_TABLE ) ) { |
|
121 LOG_FORMAT( "Database creation failed! error = %s", GET_ERR( query ) ); |
|
122 mDatabase->close(); |
|
123 mDatabase.reset(); |
|
124 return false; |
|
125 } |
|
126 } |
|
127 } else { |
|
128 LOG_FORMAT( "Invalid database! error = %s", GET_ERR( db ) ); |
|
129 return false; |
|
130 } |
|
131 |
|
132 mQueryModel.reset( new QSqlQueryModel() ); |
|
133 setViewMode( ShowAll ); |
|
134 |
|
135 return mQueryModel->lastError().type() == QSqlError::NoError; |
|
136 } |
|
137 |
|
138 /*! |
|
139 * |
|
140 */ |
|
141 void RadioHistoryModelPrivate::addItem( const QString& artist, |
|
142 const QString& title, |
|
143 const RadioStation& station, |
|
144 bool fromRds ) |
|
145 { |
|
146 LOG_FORMAT( "RadioHistoryModelPrivate::addItem. Artist: %s, Title: %s", GETSTRING( artist ), GETSTRING( title ) ); |
|
147 |
|
148 if ( !mQueryModel ) { |
|
149 return; |
|
150 } |
|
151 |
|
152 mTopItemIsPlaying = true; |
|
153 |
|
154 QSqlQuery query = beginTransaction(); |
|
155 |
|
156 query.prepare( SQL_ADD_ITEM ); |
|
157 query.addBindValue( artist ); |
|
158 query.addBindValue( title ); |
|
159 query.addBindValue( station.name() ); |
|
160 query.addBindValue( static_cast<int>( station.frequency() / 1000 ) ); |
|
161 query.addBindValue( fromRds ); |
|
162 query.addBindValue( QDateTime::currentDateTime().toTime_t() ); |
|
163 |
|
164 commitTransaction( query, InsertRows, 0 ); |
|
165 } |
|
166 |
|
167 /*! |
|
168 * |
|
169 */ |
|
170 int RadioHistoryModelPrivate::rowCount() const |
|
171 { |
|
172 if ( !mQueryModel ) { |
|
173 return 0; |
|
174 } |
|
175 return mQueryModel->rowCount(); |
|
176 } |
|
177 |
|
178 /*! |
|
179 * |
|
180 */ |
|
181 QVariant RadioHistoryModelPrivate::data( const int row, const int role ) const |
|
182 { |
|
183 if ( mQueryModel->lastError().type() == QSqlError::NoError ) { |
|
184 |
|
185 QSqlRecord record = mQueryModel->record( row ); |
|
186 if ( role == Qt::DisplayRole ) { |
|
187 |
|
188 const QString artist = record.value( RadioHistoryValue::Artist ).toString(); |
|
189 const QString title = record.value( RadioHistoryValue::Title ).toString(); |
|
190 const QString station = record.value( RadioHistoryValue::Station ).toString(); |
|
191 const uint frequency = record.value( RadioHistoryValue::Frequency ).toUInt() * 1000; |
|
192 |
|
193 QStringList list; |
|
194 if ( mShowDetails ) { |
|
195 list.append( qtTrId( "txt_rad_dblist_1_2" ).arg( artist ).arg( title ) ); |
|
196 QDateTime dateTime = record.value( RadioHistoryValue::Time ).toDateTime(); |
|
197 const QString time = dateTime.toLocalTime().toString(); |
|
198 |
|
199 QString name = !station.isEmpty() ? station : parseFrequency( frequency ); |
|
200 list.append( qtTrId( "txt_rad_dblist_1_2" ).arg( time ).arg( name ) ); |
|
201 } else { |
|
202 list.append( artist ); |
|
203 list.append( title ); |
|
204 } |
|
205 |
|
206 return list; |
|
207 } else if ( role == Qt::DecorationRole ) { |
|
208 QVariantList list; |
|
209 const bool tagged = record.value( RadioHistoryValue::Tagged ).toBool(); |
|
210 if ( tagged ) { |
|
211 list.append( mTaggedIcon ); |
|
212 } else { |
|
213 list.append( mNonTaggedIcon ); |
|
214 } |
|
215 return list; |
|
216 } |
|
217 } |
|
218 |
|
219 return QVariant(); |
|
220 } |
|
221 |
|
222 /*! |
|
223 * |
|
224 */ |
|
225 void RadioHistoryModelPrivate::removeAll() |
|
226 { |
|
227 if ( !mQueryModel ) { |
|
228 return; |
|
229 } |
|
230 |
|
231 QSqlQuery query = beginTransaction(); |
|
232 |
|
233 query.prepare( SQL_DELETE_ALL ); |
|
234 |
|
235 // Commented out because rowsRemoved() seems to crash HbListView |
|
236 // commitTransaction( query, RemoveRows, 0, rowCount() - 1 ); |
|
237 |
|
238 commitTransaction( query, NoOp, 0 ); |
|
239 q_ptr->reset(); |
|
240 } |
|
241 |
|
242 /*! |
|
243 * |
|
244 */ |
|
245 void RadioHistoryModelPrivate::setViewMode( ViewMode mode ) |
|
246 { |
|
247 if ( !mQueryModel ) { |
|
248 return; |
|
249 } |
|
250 |
|
251 mViewMode = mode; |
|
252 mQueryModel->setQuery( mode == ShowTagged ? SQL_SELECT_TAGGED : SQL_SELECT_ALL, *mDatabase ); |
|
253 q_ptr->reset(); |
|
254 } |
|
255 |
|
256 /*! |
|
257 * |
|
258 */ |
|
259 void RadioHistoryModelPrivate::toggleTagging( const RadioHistoryItem& item, const int row ) |
|
260 { |
|
261 QSqlQuery updateQuery = beginTransaction(); |
|
262 |
|
263 updateQuery.prepare( SQL_TOGGLE_TAG ); |
|
264 updateQuery.addBindValue( item.isTagged() ? 0 : 1 ); |
|
265 updateQuery.addBindValue( item.id() ); |
|
266 |
|
267 commitTransaction( updateQuery, ChangeData, row ); |
|
268 } |
|
269 |
|
270 /*! |
|
271 * |
|
272 */ |
|
273 RadioHistoryItem RadioHistoryModelPrivate::itemAtIndex( const QModelIndex& index ) const |
|
274 { |
|
275 LOG_METHOD; |
|
276 RadioHistoryItem item; |
|
277 QSqlRecord record = mQueryModel->record( index.row() ); |
|
278 item.data_ptr()->initFromRecord( record ); |
|
279 return item; |
|
280 } |
|
281 |
|
282 /*! |
|
283 * |
|
284 */ |
|
285 void RadioHistoryModelPrivate::refreshModel() |
|
286 { |
|
287 setViewMode( mViewMode ); |
|
288 } |
|
289 |
|
290 /*! |
|
291 * |
|
292 */ |
|
293 QSqlQuery RadioHistoryModelPrivate::beginTransaction() |
|
294 { |
|
295 LOG_METHOD; |
|
296 QSqlQuery newQuery( *mDatabase ); |
|
297 mDatabase->transaction(); |
|
298 return newQuery; |
|
299 } |
|
300 |
|
301 /*! |
|
302 * |
|
303 */ |
|
304 void RadioHistoryModelPrivate::commitTransaction( QSqlQuery& query, Operation operation, int start, int end ) |
|
305 { |
|
306 LOG_METHOD; |
|
307 if ( end == -1 ) { |
|
308 end = start; |
|
309 } |
|
310 |
|
311 bool success = false; |
|
312 Q_UNUSED( success ); |
|
313 if ( query.exec() ) { |
|
314 if ( operation == InsertRows ) { |
|
315 q_ptr->beginInsertRows( QModelIndex(), start, end ); |
|
316 } else if ( operation == RemoveRows ) { |
|
317 q_ptr->beginRemoveRows( QModelIndex(), start, end ); |
|
318 } |
|
319 |
|
320 success = mDatabase->commit(); |
|
321 LOG_ASSERT( success, LOG_FORMAT( "Commit failed! err: %s", GET_ERR_PTR( mDatabase ) ) ); |
|
322 |
|
323 refreshModel(); |
|
324 |
|
325 if ( operation == InsertRows ) { |
|
326 q_ptr->endInsertRows(); |
|
327 q_ptr->emitItemAdded(); |
|
328 } else if ( operation == RemoveRows ) { |
|
329 q_ptr->endRemoveRows(); |
|
330 } else if ( operation == ChangeData ) { |
|
331 q_ptr->reportChangedData( start ); |
|
332 } |
|
333 } else { |
|
334 LOG_FORMAT( "RadioHistoryModelPrivate::commitTransaction FAILED, rolling back: error = %s", GET_ERR( query ) ); |
|
335 success = mDatabase->rollback(); |
|
336 LOG_ASSERT( success, LOG_FORMAT( "Rollback failed! err: %s", GET_ERR_PTR( mDatabase ) ) ); |
|
337 } |
|
338 } |