📄 qmplaylist.cpp
字号:
}/*! */voidQmPlayList::dropEvent( QDropEvent *event){ if ( ! QUriDrag::canDecode(event)) return QmListView::dropEvent(event); QStringList files; if ( ! QUriDrag::decodeLocalFiles(event, files)) return; QFileInfo fileinfo; int count = 0; QListViewItem *dropAt = 0; if (childCount() > 1) // dropindicator is 1 child dropAt = dynamic_cast<QListViewItem*>(dropPos()); for (QStringList::Iterator it = files.begin(); it != files.end(); it++) { fileinfo.setFile(*it); if (fileinfo.isFile()) { QString ext = fileinfo.fileName().right(3).lower(); if (ext == "mp3") { if (dropAt && dropAt->depth()) dropAt = new QmSongItem(reinterpret_cast<QmPlayListItem*>(dropAt->parent()), dropAt, *it); else dropAt = new QmSongItem(this, dropAt, *it); } else { dropAt = loadPlayList(fileinfo.filePath(), reinterpret_cast<QmPlayListItem*>(dropAt)); } } else { if (dropAt && dropAt->depth()) { dropAt = new QmDirItem(reinterpret_cast<QmDirItem*>(dropAt->parent()), dropAt, *it, count, true); } else { dropAt = new QmDirItem(this, dropAt, *it, count, true); } } } setDirty(); QmMainWindow::mainwin->statusUpdate(new Message(Message::Status, "Dropped %d songs", count)); stopDragging();}/*! \return True if the playlist has been changed since last saved, false otherwise/ \sa setDirty()*/boolQmPlayList::isDirty() const { return m_Dirty;}/*! Sets the dirty flag. A function is used to provide a place to put stuff that needs to be done when the playlist is changed. \sa isDirty() */voidQmPlayList::setDirty() { m_SongIndexDirty = m_Dirty = true;}/*! Remove directories so the play-tree becomes a play-list.*/voidQmPlayList::flatten() { setUpdatesEnabled(false); m_DeletingItems = true; // ensure songs in index updateSongIndex(); // remove songs from list so they're not deleted with the directories // takeItem is needlessly expensive for this, consider reimplementing it QListViewItem *parent; for (uint i = 0; i < m_SongIndex.size(); ++i) { if ((parent = m_SongIndex[i]->parent()) != 0) parent->takeItem(m_SongIndex[i]); else takeItem(m_SongIndex[i]); } QListView::clear(); // add songs from index QListView::insertItem(m_SongIndex[0]); for (uint i = 1; i< m_SongIndex.size(); ++i) insertItem( 0, m_SongIndex[i], m_SongIndex[i-1] ); m_DeletingItems = false; setUpdatesEnabled(true); triggerUpdate();}/*! Searches for the string \a s (case insensitive) and highlights the item, if found. The last search is remembered. If the same string is passed in twice (or more), the search continues from where the last match was found. Otherwise, the search starts from the top.*/voidQmPlayList::search( const QString& s){ static QString prev_search = QString::null; static QListViewItem *last_found = 0; QListViewItem *start_item = 0; if(prev_search == s) { if(last_found) start_item = last_found->itemBelow(); if(start_item == 0) start_item = firstChild(); } else { prev_search = s; start_item = firstChild(); } for(QListViewItemIterator it(start_item); it.current() != 0; ++it) { if(it.current()->text(0).contains(s, false)) { last_found = it.current(); ensureItemVisible(it.current()); QmPlayListItem::setMatchItem(reinterpret_cast<QmPlayListItem*>(it.current())); return; } } QmPlayListItem::setMatchItem(0);}/*! Re-arranges the playlist. Currently makes nodes for Artists with sub-nodes for album; if something else makes sense, pass the QmSongItem attributes to the compareSongs constructor. */voidQmPlayList::reGroup() { updateSongIndex(); if (m_SongIndex.empty()) return; m_DeletingItems = true; setUpdatesEnabled(false); std::sort(m_SongIndex.begin(), m_SongIndex.end(), compareSongs<>(&QmSongItem::m_Artist, &QmSongItem::m_Album, &QmSongItem::m_CdPosition)); // remove songs from widget QListViewItem *parent; for (SongIndexIterator i=m_SongIndex.begin(); i!=m_SongIndex.end(); ++i) { if ((parent=(*i)->parent()) != 0) parent->takeItem(*i); else takeItem(*i); } QListView::clear(); // add songs, creating groups QString curArtist = m_SongIndex[0]->artist(); QString curAlbum = m_SongIndex[0]->album(); QmDirItem *artist = new QmDirItem(this, 0, curArtist); QmDirItem *album = new QmDirItem(artist, 0, curAlbum); album->insertItem(m_SongIndex[0]); QmSongItem *prev = m_SongIndex[0]; // insertItem doesn't take a `after' or `append' parameter, doh. std::vector<QmSongItem*> various; for (uint i = 1; i < m_SongIndex.size(); i++) { if (m_SongIndex[i]->multiArtistp()) { various.push_back(m_SongIndex[i]); continue; } if (m_SongIndex[i]->album() != curAlbum) { if (m_SongIndex[i]->artist() != curArtist) { curArtist = m_SongIndex[i]->artist(); artist = new QmDirItem(this, artist, curArtist); prev = 0; } curAlbum = m_SongIndex[i]->album(); album = new QmDirItem(artist, 0, curAlbum); prev = 0; } album->insertItem(m_SongIndex[i]); if (prev) m_SongIndex[i]->moveItem(prev); prev = m_SongIndex[i]; } if (!various.empty()) { QString tmp(tr("Various")); artist = new QmDirItem(this, 0, tmp); std::sort(various.begin(), various.end(), compareSongs<>(&QmSongItem::m_Album, &QmSongItem::m_CdPosition)); QString albumName; for (SongIndexIteratorR i=various.rbegin(); i!=various.rend(); ++i) { if ((*i)->album() != albumName) { albumName = (*i)->album(); album = new QmDirItem(artist, 0, albumName); } album->insertItem(*i); } } reCalculate(); updateColumnWidths(); m_DeletingItems = false; setUpdatesEnabled(true); triggerUpdate();}/*! Expands first level directories and closes all others. \sa expandAll()*/voidQmPlayList::expandFirstLevel(){ collapseAll(); for (QListViewItem *i = firstChild(); i; i = i->nextSibling()) i->setOpen(true); updateColumnWidths();}/*! Expands all directories. \sa collapseAll(), expandFirstLevel()*/voidQmPlayList::expandAll(){ for (QListViewItemIterator i(this); i.current(); i++) i.current()->setOpen(true); updateColumnWidths();}/*! Collapses all directories. \sa expandAll(), expandFirstLevel()*/voidQmPlayList::collapseAll(){ for (QListViewItemIterator i(this); i.current(); i++) i.current()->setOpen(false); updateColumnWidths();}/*! Saves the playlist in xml format.*/voidQmPlayList::saveAsXml(const QString &filename) { int depth = 0; int song_count = 0; int dir_count = 0; long start_time = time(0); QmMainWindow::mainwin->setState( QmMainWindow::Busy ); QFile save_file( filename); if ( !save_file.open( IO_WriteOnly ) ) { QmMainWindow::mainwin->statusUpdate(new Message(Message::Error, "Error: Could not write to \"%s\"", save_file.name().latin1())); return; } QTextStream out( &save_file ); if (QString("utf-8") == QmConfig::instance()->getString("stuff", "encoding")) out.setEncoding(QTextStream::UnicodeUTF8); out << "<?xml version='1.0' encoding=\"" << QmConfig::instance()->getString( "stuff", "encoding") << "\"?>\n" << "<!DOCTYPE APOLLO-PLAYLIST>\n" << "<apollo-playlist>\n"; QmDirItem *dir; QmSongItem *song; for (QListViewItemIterator it(this); it.current(); ++it) { for (;it.current()->depth() < depth; --depth) out << "</dir>\n"; if (reinterpret_cast<QmPlayListItem*>(it.current())->isSong()) { song = reinterpret_cast<QmSongItem*>(it.current()); song->writeXml(out); if (++song_count%100 == 0) { QmMainWindow::mainwin->statusUpdate(new Message(Message::Update, "Saved %d songs in %d folders (%ld seconds)", song_count, dir_count, time(0) - start_time)); } } else { dir = reinterpret_cast<QmDirItem*>(it.current()); dir->writeXml(out); if (++dir_count%10==0) { QmMainWindow::mainwin->statusUpdate(new Message(Message::Update, "Saved %d songs in %d folders (%ld seconds)", song_count, dir_count, time(0)-start_time)); } depth++; } } while (depth-->0) out << "</dir>\n"; out << "</apollo-playlist>\n"; int duration = time(0) - start_time; if (duration > 0) { QmMainWindow::mainwin->statusUpdate(new Message(Message::Status, "Saved %d songs in %d folders (%ld seconds, %s)", song_count, dir_count, time(0) - start_time, filename.latin1())); } else { QmMainWindow::mainwin->statusUpdate(new Message(Message::Status, "Saved %d songs in %d folders (%s)", song_count, dir_count, filename.latin1())); } m_Dirty = false; QmMainWindow::mainwin->setState( QmMainWindow::Ready );}voidQmPlayList::saveAsM3u(const QString &filename) { QmMainWindow::mainwin->setState( QmMainWindow::Busy ); QFile save_file( filename); if ( !save_file.open( IO_WriteOnly ) ) { QmMainWindow::mainwin->statusUpdate(new Message(Message::Error, "Error: Could not write to \"%s\"", save_file.name().latin1())); return; } QTextStream out( &save_file ); updateSongIndex(); for (uint i=0; i<m_SongIndex.size(); ++i) out << m_SongIndex[i]->filePath() << "\n"; QmMainWindow::mainwin->statusUpdate(new Message(Message::Status, "Saved %d songs in %s", m_SongIndex.size(), filename.latin1())); QmMainWindow::mainwin->setState(QmMainWindow::Ready);}/*! \return The playlist filename. */const QString&QmPlayList::filename() const{ return m_Filename;}/*! Calculates statistics, currently playlength, needs to be called manually until we come up with an acceptable performace auto-scheme. */longQmPlayList::reCalculate(){ long ret=0; for (QListViewItem *i = firstChild(); i; i=i->nextSibling()) ret += static_cast<QmPlayListItem*>(i)->updateLength(); updateSongIndex(); m_PlayLength = m_PlayLengthNotCounted = 0; for (int i = m_SongIndex.size() - 1; i >= 0; --i) { if (m_SongIndex[i]->length() > 0) m_PlayLength += m_SongIndex[i]->length(); else m_PlayLengthNotCounted++; } QString tmp; secondsToTimeString(m_PlayLength, tmp); if(m_PlayLengthNotCounted > 0) { QmMainWindow::mainwin->statusUpdate(new Message(Message::Status, "%d songs %s (%d not counted)", m_SongIndex.size(), tmp.latin1(), m_PlayLengthNotCounted)); } else { QmMainWindow::mainwin->statusUpdate(new Message(Message::Status, "%d songs, %s", m_SongIndex.size(), tmp.latin1())); } return ret;}/*! \todo */voidQmPlayList::updateColumnWidths(){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -