1 /* $BEGIN_LICENSE
2 
3 This file is part of Musique.
4 Copyright 2013, Flavio Tordini <flavio.tordini@gmail.com>
5 
6 Musique is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 Musique is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with Musique.  If not, see <http://www.gnu.org/licenses/>.
18 
19 $END_LICENSE */
20 
21 #include "albumlistview.h"
22 
23 #include <QtSql>
24 
25 #include "artistsqlmodel.h"
26 #include "database.h"
27 #include "finderitemdelegate.h"
28 #include "iconutils.h"
29 #include "mainwindow.h"
30 #ifdef APP_EXTRA
31 #include "extra.h"
32 #endif
33 
34 namespace {
35 const char *sortByKey = "albumSortBy";
36 const char *reverseOrderKey = "albumReverseOrder";
37 } // namespace
38 
AlbumListView(QWidget * parent)39 AlbumListView::AlbumListView(QWidget *parent) : FinderListView(parent), showToolBar(false) {
40     toolBar = new QToolBar();
41     toolBar->hide();
42     toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
43     toolBar->setIconSize(QSize(16, 16));
44 
45     QSettings settings;
46     sortBy = static_cast<SortBy>(settings.value(sortByKey, SortByYear).toInt());
47 
48     QMenu *sortMenu = new QMenu(this);
49     QActionGroup *sortGroup = new QActionGroup(this);
50 
51     QAction *sortByArtistAction = new QAction(tr("Artist"), this);
52     sortByArtistAction->setActionGroup(sortGroup);
53     sortByArtistAction->setCheckable(true);
54     if (sortBy == SortByArtist) sortByArtistAction->setChecked(true);
55     connect(sortByArtistAction, SIGNAL(triggered()), SLOT(setSortByArtist()));
56     sortMenu->addAction(sortByArtistAction);
57 
58     QAction *sortByNameAction = new QAction(tr("Title"), this);
59     sortByNameAction->setActionGroup(sortGroup);
60     sortByNameAction->setCheckable(true);
61     if (sortBy == SortByTitle) sortByNameAction->setChecked(true);
62     connect(sortByNameAction, SIGNAL(triggered()), SLOT(setSortByTitle()));
63     sortMenu->addAction(sortByNameAction);
64 
65     QAction *sortByYearAction = new QAction(tr("Year"), this);
66     sortByYearAction->setActionGroup(sortGroup);
67     sortByYearAction->setCheckable(true);
68     if (sortBy == SortByYear) sortByYearAction->setChecked(true);
69     connect(sortByYearAction, SIGNAL(triggered()), SLOT(setSortByYear()));
70     sortMenu->addAction(sortByYearAction);
71 
72     QAction *sortByPopularityAction = new QAction(tr("Popularity"), this);
73     sortByPopularityAction->setActionGroup(sortGroup);
74     sortByPopularityAction->setCheckable(true);
75     if (sortBy == SortByPopularity) sortByPopularityAction->setChecked(true);
76     connect(sortByPopularityAction, SIGNAL(triggered()), SLOT(setSortByPopularity()));
77     sortMenu->addAction(sortByPopularityAction);
78 
79     sortMenu->addSeparator();
80 
81     reversedOrder = settings.value(reverseOrderKey, false).toBool();
82 
83     QAction *reversedOrderAction = new QAction(tr("Reversed Order"), this);
84     reversedOrderAction->setCheckable(true);
85     if (reversedOrder) reversedOrderAction->setChecked(true);
86     connect(reversedOrderAction, SIGNAL(triggered(bool)), SLOT(setReversedOrder(bool)));
87     sortMenu->addAction(reversedOrderAction);
88 
89     QToolButton *sortButton = new QToolButton(this);
90     sortButton->setText(tr("Sort by"));
91     IconUtils::setWidgetIcon(sortButton, "sort");
92     sortButton->setIconSize(QSize(16, 16));
93     sortButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
94     sortButton->setPopupMode(QToolButton::InstantPopup);
95     sortButton->setMenu(sortMenu);
96     QWidgetAction *widgetAction = new QWidgetAction(this);
97     widgetAction->setDefaultWidget(sortButton);
98     widgetAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_O));
99     toolBar->addAction(widgetAction);
100 }
101 
appear()102 void AlbumListView::appear() {
103     FinderListView::appear();
104     if (showToolBar) {
105         QStatusBar *statusBar = MainWindow::instance()->statusBar();
106         statusBar->insertPermanentWidget(0, toolBar);
107         toolBar->show();
108     }
109 }
110 
disappear()111 void AlbumListView::disappear() {
112     FinderListView::disappear();
113     if (showToolBar) {
114         QStatusBar *statusBar = MainWindow::instance()->statusBar();
115         statusBar->removeWidget(toolBar);
116     }
117 }
118 
updateQuery(bool transition)119 void AlbumListView::updateQuery(bool transition) {
120     QString sql = "select id from albums where trackCount>0";
121 
122     switch (sortBy) {
123     case SortByArtist:
124         sql = "select b.id from albums b, artists a"
125               " where b.artist=a.id and b.trackCount>0"
126               " order by a.name collate nocase";
127         if (reversedOrder) sql += " desc";
128         sql += ", b.year";
129         if (!reversedOrder) sql += " desc";
130         sql += ", b.trackCount";
131         if (!reversedOrder) sql += " desc";
132         break;
133     case SortByYear:
134         sql += " and year>0 order by year";
135         if (!reversedOrder) sql += " desc";
136         break;
137     case SortByPopularity:
138         sql += " order by listeners";
139         if (!reversedOrder) sql += " desc";
140         break;
141     default:
142         sql += " order by title collate nocase";
143         if (reversedOrder) sql += " desc";
144         break;
145     }
146 
147 #ifdef APP_EXTRA
148     if (transition) Extra::fadeInWidget(this, this);
149 #endif
150 
151     if (!sqlModel->query().isValid()) QTimer::singleShot(500, this, SLOT(preloadThumbs()));
152 
153     sqlModel->setQuery(sql, Database::instance().getConnection());
154     if (sqlModel->lastError().isValid()) qWarning() << sqlModel->lastError().text();
155 
156     scrollToTop();
157     showToolBar = true;
158 }
159 
preloadThumbs()160 void AlbumListView::preloadThumbs() {
161     QSqlDatabase db = Database::instance().getConnection();
162     QSqlQuery query(sqlModel->query().lastQuery(), db);
163     bool success = query.exec();
164     if (!success)
165         qDebug() << query.lastQuery() << query.lastError().text() << query.lastError().number();
166 
167     const qreal pixelRatio = devicePixelRatioF();
168 
169     while (query.next()) {
170         int albumId = query.value(0).toInt();
171         Album *album = Album::forId(albumId);
172         album->getThumb(delegate->getItemWidth(), delegate->getItemHeight(), pixelRatio);
173         qApp->processEvents();
174     }
175 }
176 
setSortBy(SortBy sortBy)177 void AlbumListView::setSortBy(SortBy sortBy) {
178     this->sortBy = sortBy;
179     updateQuery(true);
180     QSettings settings;
181     settings.setValue(sortByKey, (int)sortBy);
182 }
183 
setReversedOrder(bool reversedOrder)184 void AlbumListView::setReversedOrder(bool reversedOrder) {
185     this->reversedOrder = reversedOrder;
186     updateQuery(true);
187     QSettings settings;
188     settings.setValue(reverseOrderKey, reversedOrder);
189 }
190