1 /*
2  * Strawberry Music Player
3  * This file was part of Clementine.
4  * Copyright 2010, David Sansome <me@davidsansome.com>
5  *
6  * Strawberry 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  * Strawberry 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 Strawberry.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "config.h"
22 
23 #include <algorithm>
24 
25 #include <QWidget>
26 #include <QAbstractItemModel>
27 #include <QFileInfo>
28 #include <QFileSystemModel>
29 #include <QDir>
30 #include <QMenu>
31 #include <QUrl>
32 #include <QtEvents>
33 
34 #include "core/iconloader.h"
35 #include "core/mimedata.h"
36 #include "core/utilities.h"
37 #include "fileviewlist.h"
38 
39 FileViewList::FileViewList(QWidget *parent)
40     : QListView(parent),
41       menu_(new QMenu(this)) {
42 
43   menu_->addAction(IconLoader::Load("media-playback-start"), tr("Append to current playlist"), this, &FileViewList::AddToPlaylistSlot);
44   menu_->addAction(IconLoader::Load("media-playback-start"), tr("Replace current playlist"), this, &FileViewList::LoadSlot);
45   menu_->addAction(IconLoader::Load("document-new"), tr("Open in new playlist"), this, &FileViewList::OpenInNewPlaylistSlot);
46   menu_->addSeparator();
47   menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, &FileViewList::CopyToCollectionSlot);
48   menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, &FileViewList::MoveToCollectionSlot);
49   menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, &FileViewList::CopyToDeviceSlot);
50   menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, &FileViewList::DeleteSlot);
51 
52   menu_->addSeparator();
53   menu_->addAction(IconLoader::Load("edit-rename"), tr("Edit track information..."), this, &FileViewList::EditTagsSlot);
54   menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, &FileViewList::ShowInBrowser);
55 
56   setAttribute(Qt::WA_MacShowFocusRect, false);
57 
58 }
59 
60 void FileViewList::contextMenuEvent(QContextMenuEvent *e) {
61 
62   menu_selection_ = selectionModel()->selection();
63 
64   menu_->popup(e->globalPos());
65   e->accept();
66 
67 }
68 
69 QList<QUrl> FileViewList::UrlListFromSelection() const {
70 
71   QList<QUrl> urls;
72   const QModelIndexList indexes = menu_selection_.indexes();
73   for (const QModelIndex &index : indexes) {
74     if (index.column() == 0) {
75       urls << QUrl::fromLocalFile(qobject_cast<QFileSystemModel*>(model())->fileInfo(index).canonicalFilePath());
76     }
77   }
78   std::sort(urls.begin(), urls.end());
79 
80   return urls;
81 
82 }
83 
84 MimeData *FileViewList::MimeDataFromSelection() const {
85 
86   MimeData *mimedata = new MimeData;
87   mimedata->setUrls(UrlListFromSelection());
88 
89   QList<QString> filenames = FilenamesFromSelection();
90 
91   // if just one folder selected - use it's path as the new playlist's name
92   if (filenames.size() == 1 && QFileInfo(filenames.first()).isDir()) {
93     if (filenames.first().length() > 20) {
94       mimedata->name_for_new_playlist_ = QDir(filenames.first()).dirName();
95     }
96     else {
97       mimedata->name_for_new_playlist_ = filenames.first();
98     }
99   }
100   // otherwise, use the current root path
101   else {
102     QString path = qobject_cast<QFileSystemModel*>(model())->rootPath();
103     if (path.length() > 20) {
104       QFileInfo info(path);
105       if (info.isDir()) {
106         mimedata->name_for_new_playlist_ = QDir(info.filePath()).dirName();
107       }
108       else {
109         mimedata->name_for_new_playlist_ = info.completeBaseName();
110       }
111     }
112     else {
113       mimedata->name_for_new_playlist_ = path;
114     }
115   }
116 
117   return mimedata;
118 
119 }
120 
121 QStringList FileViewList::FilenamesFromSelection() const {
122 
123   QStringList filenames;
124   const QModelIndexList indexes = menu_selection_.indexes();
125   for (const QModelIndex &index : indexes) {
126     if (index.column() == 0) {
127       filenames << qobject_cast<QFileSystemModel*>(model())->filePath(index);
128     }
129   }
130   return filenames;
131 
132 }
133 
134 void FileViewList::LoadSlot() {
135 
136   MimeData *mimedata = MimeDataFromSelection();
137   mimedata->clear_first_ = true;
138   emit AddToPlaylist(mimedata);
139 
140 }
141 
142 void FileViewList::AddToPlaylistSlot() {
143   emit AddToPlaylist(MimeDataFromSelection());
144 }
145 
146 void FileViewList::OpenInNewPlaylistSlot() {
147 
148   MimeData *mimedata = MimeDataFromSelection();
149   mimedata->open_in_new_playlist_ = true;
150   emit AddToPlaylist(mimedata);
151 
152 }
153 
154 void FileViewList::CopyToCollectionSlot() {
155   emit CopyToCollection(UrlListFromSelection());
156 }
157 
158 void FileViewList::MoveToCollectionSlot() {
159   emit MoveToCollection(UrlListFromSelection());
160 }
161 
162 void FileViewList::CopyToDeviceSlot() {
163   emit CopyToDevice(UrlListFromSelection());
164 }
165 
166 void FileViewList::DeleteSlot() {
167   emit Delete(FilenamesFromSelection());
168 }
169 
170 void FileViewList::EditTagsSlot() {
171   emit EditTags(UrlListFromSelection());
172 }
173 
174 void FileViewList::mousePressEvent(QMouseEvent *e) {
175 
176   switch (e->button()) {
177     case Qt::XButton1:
178       emit Back();
179       break;
180     case Qt::XButton2:
181       emit Forward();
182       break;
183     // enqueue to playlist with middleClick
184     case Qt::MiddleButton: {
185       QListView::mousePressEvent(e);
186 
187       // we need to update the menu selection
188       menu_selection_ = selectionModel()->selection();
189 
190       MimeData *mimedata = new MimeData;
191       mimedata->setUrls(UrlListFromSelection());
192       mimedata->enqueue_now_ = true;
193       emit AddToPlaylist(mimedata);
194       break;
195     }
196     default:
197       QListView::mousePressEvent(e);
198       break;
199   }
200 
201 }
202 
203 void FileViewList::ShowInBrowser() {
204   Utilities::OpenInFileBrowser(UrlListFromSelection());
205 }
206