3 Commit-ok ddb41d86be ... 060f96423c

Szerző SHA1 Üzenet Dátum
  mio 060f96423c Support Enter/Return in PlaylistWindow 5 hónapja
  mio f02b3851fa Navigate the playlist with double-click 5 hónapja
  mio cc4974193a Add initial playlist window 5 hónapja

+ 1 - 0
source/CMakeLists.txt

@@ -6,6 +6,7 @@ tde_add_executable(aster AUTOMOC
         aster_slider.cpp
         aster_slider.cpp
         aster_videoplayer.cpp
         aster_videoplayer.cpp
         playlist.cpp
         playlist.cpp
+        playlist_window.cpp
 
 
     DESTINATION
     DESTINATION
         ${BIN_INSTALL_DIR}
         ${BIN_INSTALL_DIR}

+ 14 - 0
source/aster.cpp

@@ -27,12 +27,14 @@
 #include <tqlayout.h>
 #include <tqlayout.h>
 
 
 #include "playlist.h"
 #include "playlist.h"
+#include "playlist_window.h"
 
 
 constexpr int CONTROL_HIDE_TIMER_MS = 2000;
 constexpr int CONTROL_HIDE_TIMER_MS = 2000;
 
 
 Aster::Aster(TQWidget *parent, const char *name)
 Aster::Aster(TQWidget *parent, const char *name)
     : TDEMainWindow(parent, name)
     : TDEMainWindow(parent, name)
     , m_controlTimer(-1)
     , m_controlTimer(-1)
+    , m_playlistWindow(nullptr)
 {
 {
     clearWFlags(WDestructiveClose);
     clearWFlags(WDestructiveClose);
     setMouseTracking(true);
     setMouseTracking(true);
@@ -133,6 +135,7 @@ void Aster::setupActions()
 
 
     auto viewMenu = new TDEPopupMenu(this);
     auto viewMenu = new TDEPopupMenu(this);
     KStdAction::fullScreen(this, TQ_SLOT(slotFullScreen()), actionCollection(), this, "fullscreen")->plug(viewMenu);
     KStdAction::fullScreen(this, TQ_SLOT(slotFullScreen()), actionCollection(), this, "fullscreen")->plug(viewMenu);
+    viewMenu->insertItem(i18n("Show &Playlist..."), this, TQ_SLOT(slotShowPlaylist()), CTRL | Key_L);
 
 
     auto audioMenu = new TDEPopupMenu(this);
     auto audioMenu = new TDEPopupMenu(this);
     m_audioTrackMenu = new TDEPopupMenu(audioMenu);
     m_audioTrackMenu = new TDEPopupMenu(audioMenu);
@@ -275,6 +278,17 @@ void Aster::slotShowMenubar()
     menuBar()->setShown(!menuBar()->isVisible());
     menuBar()->setShown(!menuBar()->isVisible());
 }
 }
 
 
+void Aster::slotShowPlaylist()
+{
+    if (m_playlistWindow) {
+        m_playlistWindow->show();
+        m_playlistWindow->raise();
+    } else {
+        m_playlistWindow = new PlaylistWindow(m_playlist, this);
+        m_playlistWindow->show();
+    }
+}
+
 void Aster::slotUpdateTracks()
 void Aster::slotUpdateTracks()
 {
 {
     TQValueVector<MediaTrack> tracks = m_player->audioTracks();
     TQValueVector<MediaTrack> tracks = m_player->audioTracks();

+ 9 - 6
source/aster.h

@@ -25,6 +25,7 @@
 #include "aster_videoplayer.h"
 #include "aster_videoplayer.h"
 
 
 class Playlist;
 class Playlist;
+class PlaylistWindow;
 class TDEPopupMenu;
 class TDEPopupMenu;
 
 
 class Aster : public TDEMainWindow
 class Aster : public TDEMainWindow
@@ -45,12 +46,6 @@ public slots:
     void enqueFile(const KURL &path);
     void enqueFile(const KURL &path);
 
 
 protected:
 protected:
-    Playlist *m_playlist;
-    ControlBar *m_controlBar;
-    VideoPlayer *m_player;
-    TDEPopupMenu *m_audioTrackMenu;
-    TDEPopupMenu *m_subtitleTrackMenu;
-    TDEPopupMenu *m_videoTrackMenu;
 
 
     void mouseMoveEvent(TQMouseEvent *) override;
     void mouseMoveEvent(TQMouseEvent *) override;
     void timerEvent(TQTimerEvent *) override;
     void timerEvent(TQTimerEvent *) override;
@@ -69,9 +64,17 @@ protected slots:
     void slotSetSubtitleTrack(int id);
     void slotSetSubtitleTrack(int id);
     void slotSetVideoTrack(int id);
     void slotSetVideoTrack(int id);
     void slotShowMenubar();
     void slotShowMenubar();
+    void slotShowPlaylist();
     void slotUpdateTracks();
     void slotUpdateTracks();
 
 
 private:
 private:
+    Playlist *m_playlist;
+    PlaylistWindow *m_playlistWindow;
+    ControlBar *m_controlBar;
+    VideoPlayer *m_player;
+    TDEPopupMenu *m_audioTrackMenu;
+    TDEPopupMenu *m_subtitleTrackMenu;
+    TDEPopupMenu *m_videoTrackMenu;
     int m_controlTimer;
     int m_controlTimer;
 };
 };
 
 

+ 13 - 0
source/playlist.cpp

@@ -52,6 +52,7 @@ void Playlist::append(const KURL& mrl)
 
 
 void Playlist::append(const KURL::List& items)
 void Playlist::append(const KURL::List& items)
 {
 {
+    int originalCount = count();
     for (const KURL& mrl : items) {
     for (const KURL& mrl : items) {
         if (mrl.protocol() == "media") {
         if (mrl.protocol() == "media") {
             TDEIO::UDSEntry e;
             TDEIO::UDSEntry e;
@@ -68,6 +69,8 @@ void Playlist::append(const KURL::List& items)
             d->items.append(mrl);
             d->items.append(mrl);
         }
         }
     }
     }
+
+    emit itemsInserted(originalCount, count());
 }
 }
 
 
 bool Playlist::isEmpty() const
 bool Playlist::isEmpty() const
@@ -118,4 +121,14 @@ void Playlist::previous()
     }
     }
 }
 }
 
 
+void Playlist::setCurrentIndex(int index)
+{
+    if (index >= d->items.count() || index < 0) {
+        return;
+    }
+    d->index = index;
+    emit currentIndexChanged(d->index);
+    emit currentItemChanged(d->items[d->index]);
+}
+
 #include "playlist.moc"
 #include "playlist.moc"

+ 2 - 0
source/playlist.h

@@ -66,6 +66,8 @@ public slots:
 	void next();
 	void next();
 	/*! Return to the previous playlist item. */
 	/*! Return to the previous playlist item. */
 	void previous();
 	void previous();
+	/*! Navigate to the playlist item at \a index. */
+	void setCurrentIndex(int index);
 
 
 private:
 private:
 	class PlaylistPrivate* d;
 	class PlaylistPrivate* d;

+ 176 - 0
source/playlist_window.cpp

@@ -0,0 +1,176 @@
+/*
+    Copyright (C) 2025 mio <stigma@disroot.org>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+#include "playlist_window.h"
+
+#include "playlist.h"
+
+#include <tqlayout.h>
+#include <tqpalette.h>
+#include <tqtable.h>
+#include <tqpainter.h>
+
+#include <tdefilemetainfo.h>
+#include <tdelocale.h>
+
+class PlaylistTable : public TQTable
+{
+public:
+	PlaylistTable(TQWidget *parent, const char *name)
+		: TQTable(parent, name)
+		, m_currentRow(0)
+	{}
+
+	void paintCell(TQPainter *p, int row, int col, const TQRect& cr, bool selected, const TQColorGroup& cg) override
+	{
+		if (row == m_currentRow)
+		{
+			// TODO: This should be configurable via settings.
+			TQColorGroup group = cg;
+
+			group.setColor(TQColorGroup::Text, palette().active().buttonText());
+			group.setBrush(TQColorGroup::Base, palette().active().button());
+
+			TQTable::paintCell(p, row, col, cr, selected, group);
+		}
+		else
+		{
+			TQTable::paintCell(p, row, col, cr, selected, cg);
+		}
+	}
+
+	void setCurrentRow(int row)
+	{
+		m_currentRow = row;
+		repaintContents(visibleRect());
+	}
+
+private:
+	int m_currentRow;
+};
+
+PlaylistWindow::PlaylistWindow(Playlist *playlist, TQWidget *parent, const char *name)
+	: TQWidget(parent, name, WType_TopLevel)
+	, m_playlist(playlist)
+{
+	setCaption(i18n("Aster - Playlist"));
+
+	auto layout = new TQVBoxLayout(this);
+
+	m_table = new PlaylistTable(this, "playlist_window_table");
+	m_table->setFocusStyle(TQTable::FollowStyle);
+	m_table->setLeftMargin(0);
+	m_table->setNumCols(2);
+	m_table->setReadOnly(true);
+	m_table->setSelectionMode(TQTable::SingleRow);
+
+	m_table->horizontalHeader()->setLabel(0, i18n("Title"));
+	m_table->horizontalHeader()->setLabel(1, i18n("Duration"));
+	m_table->setColumnStretchable(0, true);
+
+	connect(m_playlist, TQ_SIGNAL(currentIndexChanged(int)), TQ_SLOT(slotIndexChanged(int)));
+	connect(m_playlist, TQ_SIGNAL(itemsInserted(int, int)),	TQ_SLOT(slotItemsInserted(int, int)));
+
+	connect(m_table, TQ_SIGNAL(doubleClicked(int, int, int, const TQPoint&)),
+		TQ_SLOT(slotTableDoubleClicked(int, int, int, const TQPoint&)));
+
+	layout->add(m_table);
+
+	/* FIXME: No way to iterate playlist */
+	m_table->insertRows(0, m_playlist->count());
+	for (size_t i = 0; i < m_playlist->count(); ++i)
+	{
+		KFileMetaInfo info(m_playlist->at(i));
+		if (info.isEmpty())
+		{
+			m_table->setText(i, 0, m_playlist->at(i).fileName());
+			m_table->setText(i, 1, TQString::fromLatin1("00:00:00"));
+		}
+		else
+		{
+			m_table->setText(i, 0, "TITLE!");
+			m_table->setText(i, 1, TQString::fromLatin1("00:00:00"));
+		}
+	}
+
+	static_cast<PlaylistTable*>(m_table)->setCurrentRow(m_playlist->currentIndex());
+
+	resize(500, 200);
+	move(parent->x() + (parent->width() / 2) - (width() / 2),
+		parent->y() + (parent->height() / 2) - (height() / 2));
+}
+
+void PlaylistWindow::keyReleaseEvent(TQKeyEvent *event)
+{
+	switch (event->key())
+	{
+	case Key_Enter:
+	case Key_Return: {
+		int current = m_table->selection(m_table->currentSelection()).topRow();
+		if (current == m_playlist->currentIndex()) {
+			// Should this restart? (as with double-clicking)
+			return;
+		}
+		m_playlist->setCurrentIndex(current);
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+void PlaylistWindow::slotIndexChanged(int index)
+{
+	static_cast<PlaylistTable*>(m_table)->setCurrentRow(index);
+}
+
+void PlaylistWindow::slotItemsInserted(int start, int end)
+{
+	const int count = end - start;
+	m_table->insertRows(m_table->numRows(), count);
+	for (int i = 0; i < count; ++i)
+	{
+		KFileMetaInfo info(m_playlist->at(start + i));
+		if (info.isEmpty())
+		{
+			m_table->setText(start + i, 0, m_playlist->at(start + i).fileName());
+			m_table->setText(start + i, 1, TQString::fromLatin1("00:00:00"));
+		}
+		else
+		{
+			m_table->setText(start + i, 0, "TITLE!");
+			m_table->setText(start + i, 1, TQString::fromLatin1("00:00:00"));
+		}
+	}
+}
+
+void PlaylistWindow::slotTableDoubleClicked(int row, int, int button, const TQPoint&)
+{
+	if (button != TQt::LeftButton)
+	{
+		return;
+	}
+
+	// Should this restart?
+	if (m_playlist->currentIndex() == row)
+	{
+		return;
+	}
+
+	m_playlist->setCurrentIndex(row);
+}
+
+#include "playlist_window.moc"

+ 45 - 0
source/playlist_window.h

@@ -0,0 +1,45 @@
+/*
+    Copyright (C) 2025 mio <stigma@disroot.org>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef ASTER_PLAYLIST_WINDOW_H
+#define ASTER_PLAYLIST_WINDOW_H
+
+#include <tqwidget.h>
+
+class Playlist;
+class TQTable;
+
+class PlaylistWindow : public TQWidget
+{
+	TQ_OBJECT
+
+public:
+	PlaylistWindow(Playlist *playlist, TQWidget *parent, const char *name = nullptr);
+
+protected slots:
+	void slotIndexChanged(int);
+	void slotItemsInserted(int, int);
+	void slotTableDoubleClicked(int, int, int, const TQPoint&);
+
+protected:
+	void keyReleaseEvent(TQKeyEvent *) override;
+
+private:
+	Playlist *m_playlist;
+	TQTable *m_table;
+};
+
+#endif /* ASTER_PLAYLIST_WINDOW_H */