autorotate for maemo
[tomamp] / mainwindow.cpp
1 #include <QtGui>
2 #include <QtDebug>
3 #include <QInputDialog>
4
5 #include "mainwindow.h"
6 #include "time.h"
7
8 //#define AVOID_INPUT_DIALOG 0
9
10 MainWindow::MainWindow()
11     : plman (this), settings (tr ("TomAmp"), "TomAmp"), isPlaying (false)
12 {
13 #ifdef Q_WS_MAEMO_5
14     setAttribute(Qt::WA_Maemo5AutoOrientation, true);
15 #endif
16     audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
17     mediaObject = new Phonon::MediaObject(this);
18
19     mediaObject->setTickInterval(1000);
20     connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
21     connect(mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
22         this, SLOT(stateChanged(Phonon::State,Phonon::State)));
23     connect(mediaObject, SIGNAL(currentSourceChanged(Phonon::MediaSource)),
24         this, SLOT(sourceChanged(Phonon::MediaSource)));
25     connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
26     connect (&plman, SIGNAL (playlistChanged (int)), this, SLOT (playlistChanged(int)));
27     connect (&plman, SIGNAL (itemUpdated(int)), this, SLOT (itemUpdated (int)));
28     connect (&plman, SIGNAL (itemRemoved(int)), this, SLOT (itemRemoved (int)));
29
30     Phonon::createPath(mediaObject, audioOutput);
31
32     qsrand (time (NULL));
33     repeat = settings.value("repeat", false).toBool();
34     shuffle = settings.value("shuffle", false).toBool();
35     setupShuffleList();
36     setupActions();
37     setupMenus();
38     setupUi();
39     show ();
40     timeLcd->display("00:00:00");
41     plman.addStringList(settings.value("lastPlaylist").toStringList());
42     setupShuffleList();
43     int curind = settings.value("currentIndex", -1).toInt ();
44     if (curind >= 0)
45         setItem (curind, false);
46     audioOutput->setVolume(settings.value("volume", .5).toReal());
47     QApplication::setWindowIcon(QIcon (QPixmap (":images/tomamp")));
48 }
49
50 MainWindow::~MainWindow()
51 {
52     settings.setValue("shuffle", shuffle);
53     settings.setValue("repeat", repeat);
54     settings.setValue("lastPlaylist", plman.playlistStrings());
55     settings.setValue("volume", audioOutput->volume());
56     settings.setValue("currentIndex", plman.indexOf(mediaObject->currentSource()));
57     for (int i = 0; i < musicTable->columnCount(); ++i)
58     {
59         QString lab = QString ("colWidth_%1").arg (i);
60         settings.setValue(lab, musicTable->columnWidth(i));
61     }
62 }
63
64 void MainWindow::addFiles()
65 {
66     QString folder = settings.value("LastFolder").toString();
67     if (folder.isEmpty())
68         folder = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
69     QStringList files = QFileDialog::getOpenFileNames(this, tr("Select Files To Add"),
70                     folder, "Music files (*.mp3 *.ogg *.wav *.flac);;Playlists (*.m3u *.pls)");
71
72     if (files.isEmpty())
73         return;
74
75     QString dir = QFileInfo (files[0]).absoluteDir().absolutePath();
76     settings.setValue("LastFolder", dir);
77     QStringList toadd;
78     foreach (QString string, files)
79     {
80         if (string.toLower().endsWith(".pls") || string.toLower().endsWith(".m3u"))
81             plman.addPlaylist(string);
82         else
83             toadd.append (string);
84     }
85     plman.addStringList(toadd);
86 }
87
88 void MainWindow::addFolder()
89 {
90     QString folder = settings.value("LastFolder").toString();
91     if (folder.isEmpty())
92         folder = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
93     QString dir = QFileDialog::getExistingDirectory(this,
94             tr("Select Directory To Add"),
95             folder);
96
97     if (dir.isEmpty())
98         return;
99
100     settings.setValue("LastFolder", dir);
101
102     QStringList filters;
103     QStringList files = QDir (dir).entryList(filters, QDir::AllDirs);
104     files.removeAll(".");
105     files.removeAll("..");
106     bool recursive = false;
107     if (files.size())
108         recursive = QMessageBox::question(this, "Add all folders", "Subfolders have been detected, add everything?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes;
109     plman.parseAndAddFolder(dir, recursive);
110 }
111
112
113 void MainWindow::addUrl()
114 {
115 #ifdef AVOID_INPUT_DIALOG
116     QString url = "http://war.str3am.com:7970";
117 #else
118     QString url = QInputDialog::getText(this, "Get URL", "Please type in the stream URL");
119 #endif
120     if (url.isEmpty() || !url.toLower().startsWith("http"))
121         return;
122     QStringList toadd;
123     toadd << url;
124     plman.addStringList(toadd);
125 }
126
127
128 void MainWindow::about()
129 {
130     QMessageBox::information(this, tr("About TomAmp v0.1"),
131         tr("TomAmp is a simple playlist-based music player.\n\n"
132         "(c) 2010 Tamas Marki <tmarki@gmail.com>\n\n"
133         "Please send comments and bug reports to the above e-mail address.\n\n"
134         "Icons by http://itweek.deviantart.com/"));
135 }
136
137 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */)
138 {
139     switch (newState)
140     {
141         case Phonon::ErrorState:
142             if (mediaObject->errorType() == Phonon::FatalError)
143             {
144 //                QMessageBox::warning(this, tr("Fatal Error"),
145 //                mediaObject->errorString() + mediaObject->currentSource().fileName() + ", " + mediaObject->currentSource().url().toString());
146             }
147             else
148             {
149 //                QMessageBox::warning(this, tr("Error"),
150 //                mediaObject->errorString());
151             }
152             next ();
153             break;
154         case Phonon::PlayingState:
155             setWindowTitle(mediaObject->metaData().value("TITLE") + " - TomAmp");
156             pauseAction->setVisible(true);
157             playAction->setVisible (false);
158             playAction->setEnabled(false);
159             pauseAction->setEnabled(true);
160             stopAction->setEnabled(true);
161             //lastPlayed = plman.indexOf(mediaObject->currentSource());
162             break;
163         case Phonon::StoppedState:
164             setWindowTitle("TomAmp");
165             stopAction->setEnabled(false);
166             playAction->setEnabled(true);
167             pauseAction->setVisible(false);
168             playAction->setVisible(true);
169             pauseAction->setEnabled(false);
170             timeLcd->display("00:00:00");
171             unhighlightRow(plman.indexOf(mediaObject->currentSource()));
172             break;
173         case Phonon::PausedState:
174             pauseAction->setEnabled(false);
175             stopAction->setEnabled(true);
176             pauseAction->setVisible(false);
177             playAction->setVisible(true);
178             playAction->setEnabled(true);
179             break;
180         case Phonon::BufferingState:
181             break;
182         default:
183         ;
184     }
185 }
186
187 void MainWindow::next()
188 {
189     bool wasPlaying = isPlaying;
190     if (mediaObject->state () == Phonon::ErrorState)
191         wasPlaying = true;
192     int index = plman.indexOf(mediaObject->currentSource());
193     if (shuffle)
194     {
195         index = shuffleList.indexOf(plman.indexOf(mediaObject->currentSource())) + 1;
196         while (index < shuffleList.size () && !plman.getItem(shuffleList[index]).playable)
197         {
198             index += 1;
199         }
200         if (index < shuffleList.size ())
201         {
202             setItem (index, wasPlaying);
203         }
204         else if (repeat)
205         {
206             index = 0;
207             while ((index) < shuffleList.size () && !plman.getItem(shuffleList[index]).playable)
208             {
209                 index += 1;
210             }
211             setItem (index, wasPlaying);
212         }
213     }
214     else
215     {
216         index++;
217         while ((index) < plman.size () && !plman.getItem(index).playable)
218         {
219             index += 1;
220         }
221         if (index < plman.size())
222         {
223             setItem (index, wasPlaying);
224         }
225         else if (repeat)
226         {
227             index = 0;
228             while ((index) < plman.size () && !plman.getItem(index).playable)
229             {
230                 index += 1;
231             }
232             setItem (index, wasPlaying);
233         }
234     }
235 }
236
237 void MainWindow::setItem(int i, bool doplay)
238 {
239     if (i < plman.size() && i >= 0)
240     {
241         if (lastPlayed >= 0)
242             unhighlightRow(lastPlayed);
243         if (shuffle)
244         {
245             mediaObject->setCurrentSource(plman.at (shuffleList[i]));
246         }
247         else
248         {
249             mediaObject->setCurrentSource(plman.at(i));
250         }
251     }
252     if (doplay && mediaObject->currentSource().type() != Phonon::MediaSource::Invalid)
253     {
254         play();
255     }
256     else
257         stop ();
258 }
259
260 void MainWindow::previous()
261 {
262     bool wasPlaying = isPlaying;//(mediaObject->state () == Phonon::PlayingState);
263     if (mediaObject->state () == Phonon::ErrorState)
264         wasPlaying = true;
265     int index = plman.indexOf(mediaObject->currentSource());
266     if (shuffle)
267     {
268         index = shuffleList.indexOf(plman.indexOf(mediaObject->currentSource())) - 1;
269         while (index >= 0 && !plman.getItem(shuffleList[index]).playable)
270         {
271             index--;
272         }
273         if (index >= 0)
274         {
275             setItem (index, wasPlaying);
276         }
277         else if (repeat)
278         {
279             index = plman.size () - 1;
280             while (index >= 0 && !plman.getItem(shuffleList[index]).playable)
281             {
282                 index--;
283             }
284             setItem (index, wasPlaying);
285         }
286 /*        if (index < 0)
287             wasPlaying = false;*/
288
289     }
290     else
291     {
292         index--;
293         while ((index) >= 0 && !plman.getItem(index).playable)
294         {
295             index--;
296         }
297         if (index >= 0)
298         {
299             setItem (index, wasPlaying);
300         }
301         else if (repeat)
302         {
303             index = plman.size() - 1;
304             while ((index) >= 0 && !plman.getItem(index).playable)
305             {
306                 index--;
307             }
308             setItem (index, wasPlaying);
309         }
310     }
311 }
312
313 void MainWindow::highlightRow (int i)
314 {
315     for (int j = 0; j < 3; ++j)
316     {
317         QTableWidgetItem* item = musicTable->item(i, j);
318         if (item)
319         {
320             QFont font = item->font();
321             font.setBold(true);
322             font.setItalic(true);
323             item->setFont(font);
324         }
325     }
326 }
327
328 void MainWindow::unhighlightRow (int i)
329 {
330     for (int j = 0; j < 3; ++j)
331     {
332         QTableWidgetItem* item = musicTable->item(i, j);
333         if (item)
334         {
335             QFont font = item->font();
336             font.setBold(false);
337             font.setItalic(false);
338             item->setFont(font);
339         }
340     }
341 }
342
343
344 void MainWindow::tick(qint64 time)
345 {
346     QTime displayTime((time / 3600000), (time / 60000) % 60, (time / 1000) % 60);
347
348     timeLcd->display(displayTime.toString("HH:mm:ss"));
349 }
350
351 void MainWindow::tableClicked(int row, int /* column */)
352 {
353 //    bool wasPlaying = mediaObject->state() == Phonon::PlayingState;
354
355 /*    mediaObject->stop();
356     mediaObject->clearQueue();*/
357
358     if (row >= plman.size())
359         return;
360
361     int index = row;
362     while (index < shuffleList.size () && !plman.getItem(index).playable)
363     {
364         index += 1;
365     }
366     if (plman.size() > index)
367     {
368         if (shuffle)
369             index = shuffleList.indexOf(index);
370         setItem (index, true);
371 //        mediaObject->play();
372     }
373     else
374     {
375         index = 0;
376         while (index < plman.size () && !plman.getItem(index).playable)
377         {
378             index += 1;
379         }
380         if (plman.size() > index)
381         {
382             if (shuffle)
383                 index = shuffleList.indexOf(index);
384             setItem (index, true);
385 //            mediaObject->play();
386         }
387     }
388
389 }
390
391 void MainWindow::sourceChanged(const Phonon::MediaSource &source)
392 {
393     int ind = plman.indexOf(source);
394     highlightRow(ind);
395     unhighlightRow(lastPlayed);
396     lastPlayed = ind;
397     musicTable->selectRow(ind);
398     timeLcd->display("00:00:00");
399 }
400
401
402 void MainWindow::aboutToFinish()
403 {
404     int index = plman.indexOf(mediaObject->currentSource()) + 1;
405     if (shuffle)
406     {
407         index = shuffleList.indexOf(plman.indexOf(mediaObject->currentSource())) + 1;
408         if (index < shuffleList.size ())
409         {
410             mediaObject->enqueue(plman.at (shuffleList[index]));
411         }
412         else if (repeat)
413         {
414             mediaObject->enqueue(plman.at (shuffleList[0]));
415         }
416
417     }
418     else
419     {
420         if (plman.size() > index)
421         {
422             mediaObject->enqueue(plman.at(index));
423         }
424         else if (repeat)
425         {
426             mediaObject->enqueue(plman.at(0));
427         }
428     }
429 }
430
431 void MainWindow::finished()
432 {
433 }
434
435 void MainWindow::setupActions()
436 {
437     playAction = new QAction(QIcon (QPixmap (":images/play")), "", this);
438     playAction->setShortcut(tr("Crl+P"));
439     playAction->setDisabled(true);
440     pauseAction = new QAction(QIcon (QPixmap (":images/pause")), "", this);
441     pauseAction->setShortcut(tr("Ctrl+A"));
442     pauseAction->setDisabled(true);
443     pauseAction->setVisible(false);
444     stopAction = new QAction(QIcon (QPixmap (":images/stop")), "", this);
445     stopAction->setShortcut(tr("Ctrl+S"));
446     stopAction->setDisabled(true);
447     nextAction = new QAction(QIcon (QPixmap (":images/next")), "", this);
448     nextAction->setShortcut(tr("Ctrl+N"));
449     previousAction = new QAction(QIcon (QPixmap (":images/previous")), "", this);
450     previousAction->setShortcut(tr("Ctrl+R"));
451     if (repeat)
452         repeatAction = new QAction(QIcon (QPixmap (":images/repeatActive")), "", this);
453     else
454         repeatAction = new QAction(QIcon (QPixmap (":images/repeat")), "", this);
455     repeatAction->setCheckable(true);
456     repeatAction->setChecked(repeat);
457     repeatAction->setShortcut(tr("Ctrl+I"));
458     if (shuffle)
459         shuffleAction = new QAction(QIcon (QPixmap (":images/shuffleActive")), "", this);
460     else
461         shuffleAction = new QAction(QIcon (QPixmap (":images/shuffle")), "", this);
462     shuffleAction->setCheckable(true);
463     shuffleAction->setChecked(shuffle);
464     shuffleAction->setShortcut(tr("Ctrl+H"));
465     volumeAction = new QAction(QIcon (QPixmap (":images/volume")), "", this);
466     volumeAction->setCheckable(true);
467     volumeAction->setShortcut(tr("Ctrl+V"));
468     addFilesAction = new QAction(tr("Add &File"), this);
469     addFilesAction->setShortcut(tr("Ctrl+F"));
470     addFoldersAction = new QAction(tr("Add F&older"), this);
471     addFoldersAction->setShortcut(tr("Ctrl+O"));
472     addUrlAction = new QAction(tr("Add &Url"), this);
473     addUrlAction->setShortcut(tr("Ctrl+U"));
474     savePlaylistAction = new QAction (tr("Sa&ve Playlist"), this);
475     savePlaylistAction->setShortcut(tr ("Ctrl+V"));
476     loadPlaylistAction = new QAction (tr("&Load Playlist"), this);
477     loadPlaylistAction->setShortcut(tr("Ctrl+L"));
478     clearPlaylistAction = new QAction (tr("&Clear Playlist"), this);
479     clearPlaylistAction->setShortcut(tr("Ctrl+C"));
480     exitAction = new QAction(tr("E&xit"), this);
481     exitAction->setShortcut(tr("Ctrl+X"));
482     aboutAction = new QAction(tr("A&bout"), this);
483     aboutAction->setShortcut(tr("Ctrl+B"));
484     aboutQtAction = new QAction(tr("About &Qt"), this);
485     aboutQtAction->setShortcut(tr("Ctrl+Q"));
486 /*    removeSelected = new QAction (tr("&Delete from playlist"));
487     removeSelected->setShortcut(tr ("Ctrl+D"));*/
488
489     connect(playAction, SIGNAL(triggered()), this, SLOT(play()));
490     connect(pauseAction, SIGNAL(triggered()), mediaObject, SLOT(pause()) );
491     connect(stopAction, SIGNAL(triggered()), this, SLOT(stop()));
492     connect(repeatAction, SIGNAL(triggered()), this, SLOT(repeatToggle()));
493     connect(shuffleAction, SIGNAL(triggered()), this, SLOT(shuffleToggle()));
494     connect(volumeAction, SIGNAL(triggered()), this, SLOT(volumeToggle()));
495
496     connect(addFilesAction, SIGNAL(triggered()), this, SLOT(addFiles()));
497     connect(addFoldersAction, SIGNAL(triggered()), this, SLOT(addFolder()));
498     connect(addUrlAction, SIGNAL(triggered()), this, SLOT(addUrl()));
499     connect (savePlaylistAction, SIGNAL (triggered()), this, SLOT (savePlaylist()));
500     connect (loadPlaylistAction, SIGNAL (triggered()), this, SLOT (loadPlaylist()));
501     connect (clearPlaylistAction, SIGNAL (triggered()), &plman, SLOT (clearPlaylist()));
502     connect (nextAction, SIGNAL(triggered()), this, SLOT(next()));
503     connect (previousAction, SIGNAL(triggered()), this, SLOT(previous()));
504     connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
505     connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
506     connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
507 //    connect (removeSelected, SIGNAL (triggered()), this, SLOT (removeSelectedItem()));
508 }
509
510 void MainWindow::removeSelectedItem()
511 {
512     if (QMessageBox::question(this, "Confirm remove", "Are you sure you want to remove this item?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
513         return;
514     int row = musicTable->currentRow();
515     if (row >= 0)
516         plman.removeItem(row);
517 }
518
519 void MainWindow::removeAllButSelectedItem()
520 {
521     if (QMessageBox::question(this, "Confirm remove", "Are you sure you want to remove all other items?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
522         return;
523     int row = musicTable->currentRow();
524     if (row >= 0)
525     {
526         QString uri = plman.getItem(row).uri;
527         QStringList lst;
528         lst << uri;
529         plman.clearPlaylist();
530         plman.addStringList(lst);
531     }
532 }
533
534 void MainWindow::repeatToggle ()
535 {
536     repeat = !repeat;
537     settings.setValue("repeat", QVariant (repeat));
538     if (repeat)
539         repeatAction->setIcon(QIcon (QPixmap (":images/repeatActive")));
540     else
541         repeatAction->setIcon(QIcon (QPixmap (":images/repeat")));
542 }
543
544 void MainWindow::shuffleToggle ()
545 {
546     shuffle = !shuffle;
547     settings.setValue("shuffle", QVariant (shuffle));
548     if (shuffle)
549         shuffleAction->setIcon(QIcon (QPixmap (":images/shuffleActive")));
550     else
551         shuffleAction->setIcon(QIcon (QPixmap (":images/shuffle")));
552 }
553
554 void MainWindow::volumeToggle ()
555 {
556     volumeSlider->setVisible(volumeAction->isChecked());
557 }
558
559 void MainWindow::play()
560 {
561     mediaObject->play();
562     lastPlayed = plman.indexOf(mediaObject->currentSource());
563     highlightRow(lastPlayed);
564     isPlaying = true;
565 }
566
567 void MainWindow::stop()
568 {
569     mediaObject->stop();
570     isPlaying = false;
571 }
572
573
574 void MainWindow::setupMenus()
575 {
576     QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
577     fileMenu->addAction(addFilesAction);
578     fileMenu->addAction(addFoldersAction);
579     fileMenu->addAction(addUrlAction);
580     fileMenu->addSeparator();
581     fileMenu->addAction(savePlaylistAction);
582     fileMenu->addAction(loadPlaylistAction);
583     fileMenu->addAction(clearPlaylistAction);
584 //    fileMenu->addAction(exitAction);
585
586     QMenu *aboutMenu = menuBar()->addMenu(tr("&Help"));
587     aboutMenu->addAction(aboutAction);
588     aboutMenu->addAction(aboutQtAction);
589 }
590
591 void MainWindow::setupUi()
592 {
593     QToolBar *bar = new QToolBar;
594
595     bar->setOrientation(Qt::Vertical);
596     bar->setStyleSheet("padding:7px");
597     //bar->addAction(volumeAction);
598
599     seekSlider = new Phonon::SeekSlider(this);
600     seekSlider->setMediaObject(mediaObject);
601
602     volumeSlider = new Phonon::VolumeSlider(this);
603     volumeSlider->setAudioOutput(audioOutput);
604     volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
605     volumeSlider->setOrientation(Qt::Horizontal);
606     volumeSlider->setMuteVisible(false);
607 //    volumeAddedAction = bar->addWidget(volumeSlider);
608 //    volumeAddedAction->setVisible(false);
609     bar->addAction(playAction);
610     bar->addAction(pauseAction);
611     bar->addAction(stopAction);
612     bar->addAction(repeatAction);
613     bar->addAction(shuffleAction);
614     bar->addAction(nextAction);
615     bar->addAction(previousAction);
616
617     contextMenu = new QMenu (this);
618     removeSelected = contextMenu->addAction(tr ("Remove selected"));
619     removeAllButSelected = contextMenu->addAction(tr("Remove all but selected"));
620     connect (removeSelected, SIGNAL (triggered()), this, SLOT (removeSelectedItem()));
621     connect (removeAllButSelected, SIGNAL (triggered()), this, SLOT (removeAllButSelectedItem()));
622
623
624     timeLcd = new QLCDNumber;
625
626     QStringList headers;
627     headers << tr("Artist") << tr("Title") << tr("Album") << "Controls";
628
629     musicTable = new QTableWidget(0, 4);
630     musicTable->setHorizontalHeaderLabels(headers);
631     musicTable->setSelectionMode(QAbstractItemView::SingleSelection);
632     musicTable->setSelectionBehavior(QAbstractItemView::SelectRows);
633     connect(musicTable, SIGNAL(cellDoubleClicked(int,int)),
634         this, SLOT(tableClicked(int,int)));
635     connect(musicTable, SIGNAL(cellClicked(int,int)),
636         this, SLOT(cellClicked(int,int)));
637 /*    for (int i = 0; i < 3; ++i)
638     {
639         if (!musicTable->horizontalHeaderItem(i))
640             continue;
641         musicTable->horizontalHeaderItem(i)->setBackgroundColor(QColor (128, 128, 255));;
642         musicTable->horizontalHeaderItem(i)->setForeground(QColor (255, 255, 255));
643     }*/
644     for (int i = 0; i < musicTable->columnCount(); ++i)
645     {
646         QString lab = QString ("colWidth_%1").arg (i);
647         int val = settings.value(lab, 0).toInt();
648         if (val)
649             musicTable->setColumnWidth(i, val);
650 //        settings.setValue(lab, musicTable->columnWidth(i));
651     }
652
653
654     QHBoxLayout *seekerLayout = new QHBoxLayout;
655     QToolBar* bar2 = new QToolBar;
656     bar2->addAction(volumeAction);
657     seekerLayout->addWidget(bar2);
658     seekerLayout->addWidget(volumeSlider);
659     seekerLayout->addWidget(seekSlider);
660     seekerLayout->addWidget(timeLcd);
661
662     QVBoxLayout *playbackLayout = new QVBoxLayout;
663     volumeSlider->hide ();
664     playbackLayout->addWidget(bar);
665
666     QVBoxLayout *seekAndTableLayout = new QVBoxLayout;
667
668     seekAndTableLayout->addWidget(musicTable);
669     seekAndTableLayout->addLayout(seekerLayout);
670
671     QHBoxLayout *mainLayout = new QHBoxLayout;
672     mainLayout->addLayout(seekAndTableLayout);
673     mainLayout->addLayout(playbackLayout);
674
675     QWidget *widget = new QWidget;
676     widget->setLayout(mainLayout);
677
678     setCentralWidget(widget);
679     setWindowTitle("TomAmp");
680 }
681
682 void MainWindow::cellClicked(int /*row*/, int)
683 {
684 }
685
686 void MainWindow::contextMenuEvent (QContextMenuEvent*e)
687 {
688     if (!childAt (e->pos()))
689         return;
690     if (childAt (e->pos())->parentWidget() != musicTable)
691         return;
692     contextMenu->popup(e->globalPos());
693 }
694
695
696 void MainWindow::setupShuffleList()
697 {
698     QList<int> tmp;
699     int index = plman.indexOf(mediaObject->currentSource());
700     if (index < 0)
701         index = 0;
702     for (int i = 0; i < plman.size(); ++i)
703     {
704         if ((i != index))
705             tmp.append(i);
706     }
707     shuffleList.clear();
708     shuffleList.append (index);
709     while (tmp.size ())
710     {
711         int ind = qrand () % tmp.size();
712         shuffleList.append(tmp[ind]);
713         tmp.removeAt(ind);
714     }
715 }
716
717 void MainWindow::savePlaylist ()
718 {
719     QString filename = QFileDialog::getSaveFileName(this, tr("Please select file name"), "", "Playlist Files (*.m3u *.pls)");
720     if (filename.isEmpty())
721         return;
722     plman.savePlaylist(filename);
723 }
724
725 void MainWindow::loadPlaylist ()
726 {
727     QString filename = QFileDialog::getOpenFileName(this, tr("Select playlist file to load"), "", "*.m3u *.pls");
728     if (filename.isEmpty())
729         return;
730     plman.loadPlaylist (filename);
731 }
732
733 void MainWindow::playlistChanged(int from)
734 {
735     while (musicTable->rowCount() > from)
736     {
737         musicTable->removeRow(musicTable->rowCount () - 1);
738     }
739     int firstGood = -1;
740     for (int i = from; i < plman.size (); ++i)
741     {
742         if (firstGood < 0 && plman.getItem (i).playable)
743             firstGood = i;
744         int currentRow = musicTable->rowCount();
745         musicTable->insertRow(currentRow);
746         setRowFromItem (currentRow, plman.getItem(i));
747     }
748 /*    if (plman.indexOf(mediaObject->currentSource()) < 0)
749     {
750         setItem (firstGood, false);
751     }*/
752     setupShuffleList();
753 }
754
755 void MainWindow::setRowFromItem (int row, const PlaylistItem& item)
756 {
757     if (row >= musicTable->rowCount())
758         return;
759     if (item.artist.isEmpty() && item.title.isEmpty())
760     {
761         QTableWidgetItem *item1 = new QTableWidgetItem(item.uri);
762         item1->setFlags(item1->flags() ^ Qt::ItemIsEditable);
763         musicTable->setItem(row, 1, item1);
764     }
765     else
766     {
767         QTableWidgetItem *item1 = new QTableWidgetItem(item.artist);
768         item1->setFlags(item1->flags() ^ Qt::ItemIsEditable);
769         musicTable->setItem(row, 0, item1);
770         QTableWidgetItem *item2 = new QTableWidgetItem(item.title);
771         item2->setFlags(item2->flags() ^ Qt::ItemIsEditable);
772         musicTable->setItem(row, 1, item2);
773         QTableWidgetItem *item3 = new QTableWidgetItem(item.album);
774         item3->setFlags(item3->flags() ^ Qt::ItemIsEditable);
775         musicTable->setItem(row, 2, item3);
776     }
777
778     if (!musicTable->cellWidget(row, 3))
779     {
780         QToolBar* bar = new QToolBar;
781         QLabel* up = new QLabel;
782         up->setText(QString::fromUtf8("<b><a href='up'>▲</a></b>"));
783         up->setStyleSheet("padding-right:3px;");
784         up->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
785         bar->addWidget(up);
786         QLabel* down = new QLabel;
787         down->setText(QString::fromUtf8("<b><a href='down'>▼</a></b>"));
788         down->setStyleSheet("padding-right:3px;");
789         bar->addWidget(down);
790         QLabel* del = new QLabel;
791         del->setText(QString::fromUtf8("<b><a href='del'>╳</a></b>"));
792         del->setStyleSheet("padding-right:3px;");
793         bar->addWidget(del);
794         down->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
795         bar->setProperty("row", row);
796         musicTable->setCellWidget(row, 3, bar);
797         connect (up, SIGNAL (linkActivated (const QString&)),  this, SLOT (buttonUp ()));
798         connect (down, SIGNAL (linkActivated (const QString&)),  this, SLOT (buttonDown ()));
799         connect (del, SIGNAL (linkActivated (const QString&)),  this, SLOT (buttonDel ()));
800     }
801 }
802
803 void MainWindow::buttonUp()
804 {
805     int i = sender()->parent()->property("row").toInt();
806     qDebug () << "Presses up on " << i;
807     if (i)
808     {
809         plman.moveItemUp(i);
810         setRowFromItem (i, plman.getItem(i));
811         setRowFromItem (i - 1, plman.getItem(i - 1));
812         musicTable->cellWidget(i, 3)->setProperty("row", i);
813         musicTable->cellWidget(i - 1, 3)->setProperty("row", i - 1);
814         musicTable->selectRow(i - 1);
815     }
816 }
817
818 void MainWindow::buttonDown()
819 {
820     int i = sender()->parent()->property("row").toInt();
821     qDebug () << "Presses down on " << i;
822     if (i < plman.size() - 1)
823     {
824         plman.moveItemDown(i);
825         setRowFromItem (i, plman.getItem(i));
826         setRowFromItem (i + 1, plman.getItem(i + 1));
827         musicTable->cellWidget(i, 3)->setProperty("row", i);
828         musicTable->cellWidget(i + 1, 3)->setProperty("row", i + 1);
829         musicTable->selectRow(i + 1);
830     }
831 }
832
833 void MainWindow::buttonDel()
834 {
835     int i = sender()->parent()->property("row").toInt();
836     qDebug () << "Presses del on " << i;
837     if (i < plman.size())
838     {
839         plman.removeItem(i);
840     }
841 }
842
843 void MainWindow::itemUpdated(int index)
844 {
845     if (plman.indexOf(mediaObject->currentSource()) < 0 && plman.getItem (index).playable)
846     {
847         setItem (index, false);
848     }
849     setRowFromItem (index, plman.getItem(index));
850     if (plman.indexOf(mediaObject->currentSource()) == index)
851     {
852         if (shuffle) index = shuffleList.indexOf(index);
853         setItem (index, false);
854     }
855 }
856
857 void MainWindow::itemRemoved (int i)
858 {
859     musicTable->removeRow(i);
860     for (int j = i ? (i - 1) : 0; j < musicTable->rowCount(); ++j)
861     {
862         if (musicTable->cellWidget(j, 3))
863             musicTable->cellWidget(j, 3)->setProperty("row", j);
864     }
865 }