Mailing List Archive

[PATCH] Semi-unify Record/Delete menus
On Mon, Nov 11, 2002 at 11:45:37PM -0500, Isaac Richards wrote:
> On Monday 11 November 2002 08:39 pm, Jim Radford wrote:
> > Great! I assume you'd do the same for re-encode as well? If so, then
> > looking at the code and at my changes I think the cleanest thing, in
> > terms of minimizing code duplication, might be still to unify
> > PlaybackBox and DeleteBox and to just pass in one parameter that says
> > what the default action (play, delete, er-encode) is. We can key
> > showing the size off that as well. I'll work up a patch if this is
> > ok.

> Yeah, if you want to do that, it'd be cool. Most of those two files are
> already duplicates anyway, so it shouldn't be all that hard.

Here's the merge. With this you can now 'P' (play) or 'D' (delete)
from either menu and Space/Enter performs the default action.

There are a few "spacing" differences between play and record that I
emulated verbatim. Isaac, you might want to check and see if one or
the other of values would be sufficient.

-Jim

Index: keys.txt
===================================================================
RCS file: /var/lib/cvs/MC/keys.txt,v
retrieving revision 1.1
diff -u -r1.1 keys.txt
--- keys.txt 9 Nov 2002 19:53:43 -0000 1.1
+++ keys.txt 12 Nov 2002 07:22:02 -0000
@@ -6,13 +6,15 @@
- Arrow keys are used to move the highlight point around.
- ALT-F4 to exit out of the application.
- Space or Enter to take action on the item under the highlight point.
+- P to play in both "Watch a Recording" and "Delete a Recording".
+- D to delete in both "Watch a Recording" and "Delete a Recording".

Watching TV or a recording
--------------------------

- Up and down arrow keys change the channel.
- Type the channel number to go directly to the channel.
-- P to pause / unpause.
+- P to pause / play.
- Left arrow to rewind the configured number of seconds. (default is 5)
- Right arrow to fast forward the configured number of seconds. (default is 30)
- C to hange inputs on TV Tuner card
Index: programs/mythfrontend/main.cpp
===================================================================
RCS file: /var/lib/cvs/MC/programs/mythfrontend/main.cpp,v
retrieving revision 1.41
diff -u -r1.41 main.cpp
--- programs/mythfrontend/main.cpp 30 Oct 2002 18:20:36 -0000 1.41
+++ programs/mythfrontend/main.cpp 12 Nov 2002 07:22:05 -0000
@@ -42,7 +42,7 @@
int startPlayback(MythContext *context)
{
QSqlDatabase *db = QSqlDatabase::database();
- PlaybackBox pbb(context, tvList.begin().data(), db);
+ PlaybackBox pbb(context, tvList.begin().data(), db, PlaybackBox::Play);

pbb.Show();

@@ -54,7 +54,7 @@
int startDelete(MythContext *context)
{
QSqlDatabase *db = QSqlDatabase::database();
- DeleteBox delbox(context, tvList.begin().data(), db);
+ PlaybackBox delbox(context, tvList.begin().data(), db, PlaybackBox::Delete);

delbox.Show();

Index: programs/mythfrontend/mythfrontend.pro
===================================================================
RCS file: /var/lib/cvs/MC/programs/mythfrontend/mythfrontend.pro,v
retrieving revision 1.21
diff -u -r1.21 mythfrontend.pro
--- programs/mythfrontend/mythfrontend.pro 29 Oct 2002 04:58:52 -0000 1.21
+++ programs/mythfrontend/mythfrontend.pro 12 Nov 2002 07:22:05 -0000
@@ -28,8 +28,8 @@
TARGETDEPS += ../../libs/libavcodec/libavcodec.a

# Input
-HEADERS += scheduler.h playbackbox.h deletebox.h programlistitem.h
+HEADERS += scheduler.h playbackbox.h programlistitem.h
HEADERS += viewscheduled.h

-SOURCES += main.cpp scheduler.cpp playbackbox.cpp deletebox.cpp
+SOURCES += main.cpp scheduler.cpp playbackbox.cpp
SOURCES += programlistitem.cpp viewscheduled.cpp
Index: programs/mythfrontend/playbackbox.cpp
===================================================================
RCS file: /var/lib/cvs/MC/programs/mythfrontend/playbackbox.cpp,v
retrieving revision 1.30
diff -u -r1.30 playbackbox.cpp
--- programs/mythfrontend/playbackbox.cpp 31 Oct 2002 20:23:49 -0000 1.30
+++ programs/mythfrontend/playbackbox.cpp 12 Nov 2002 07:22:05 -0000
@@ -6,6 +6,7 @@
#include <qsqldatabase.h>
#include <qlistview.h>
#include <qdatetime.h>
+#include <qprogressbar.h>
#include <qapplication.h>
#include <qtimer.h>
#include <qimage.h>
@@ -18,13 +19,16 @@
#include "NuppelVideoPlayer.h"
#include "yuv2rgb.h"

-#include "libmyth/mythcontext.h"
#include "libmyth/programinfo.h"
+#include "libmyth/dialogbox.h"
+#include "libmyth/mythcontext.h"

PlaybackBox::PlaybackBox(MythContext *context, TV *ltv, QSqlDatabase *ldb,
+ PlaybackBox::BoxType ltype,
QWidget *parent, const char *name)
: QDialog(parent, name)
{
+ type = ltype;
tv = ltv;
db = ldb;
fileprefix = context->GetFilePrefix();
@@ -42,20 +46,31 @@
QFont::Bold));
setCursor(QCursor(Qt::BlankCursor));

- QVBoxLayout *vbox = new QVBoxLayout(this, (int)(20 * wmult));
+ QVBoxLayout *vbox =
+ new QVBoxLayout(this, (int)((type == Delete ? 15 : 20) * wmult));

- QLabel *label = new QLabel("Select a recording to view:", this);
+ QLabel *label = new QLabel(type == Delete ?
+ "Select a recording to permanantly delete:" :
+ "Select a recording to view:",
+ this);
vbox->addWidget(label);

- QListView *listview = new QListView(this);
-
+ listview = new MyListView(this);
listview->addColumn("Date");
listview->addColumn("Title");
+ if(type == Delete)
+ listview->addColumn("Size");

- listview->setColumnWidth(0, (int)(220 * wmult));
- listview->setColumnWidth(1, (int)(520 * wmult));
- listview->setColumnWidthMode(0, QListView::Manual);
- listview->setColumnWidthMode(1, QListView::Manual);
+ if(type == Delete) {
+ listview->setColumnWidth(0, (int)(200 * wmult));
+ listview->setColumnWidth(1, (int)(455 * wmult));
+ listview->setColumnWidth(2, (int)(90 * wmult));
+ } else {
+ listview->setColumnWidth(0, (int)(220 * wmult));
+ listview->setColumnWidth(1, (int)(520 * wmult));
+ listview->setColumnWidthMode(0, QListView::Manual);
+ listview->setColumnWidthMode(1, QListView::Manual);
+ }

listview->setSorting(-1, false);
listview->setAllColumnsShowFocus(TRUE);
@@ -63,7 +78,11 @@
connect(listview, SIGNAL(returnPressed(QListViewItem *)), this,
SLOT(selected(QListViewItem *)));
connect(listview, SIGNAL(spacePressed(QListViewItem *)), this,
- SLOT(selected(QListViewItem *)));
+ SLOT(selected(QListViewItem *)));
+ connect(listview, SIGNAL(deletePressed(QListViewItem *)), this,
+ SLOT(remove(QListViewItem *)));
+ connect(listview, SIGNAL(playPressed(QListViewItem *)), this,
+ SLOT(play(QListViewItem *)));
connect(listview, SIGNAL(selectionChanged(QListViewItem *)), this,
SLOT(changed(QListViewItem *)));

@@ -74,8 +93,8 @@
ProgramListItem *item = NULL;

thequery = "SELECT chanid,starttime,endtime,title,subtitle,description "
- "FROM recorded ORDER BY starttime;";
-
+ "FROM recorded ORDER BY starttime DESC;";
+
query = db->exec(thequery);

if (query.isActive() && query.numRowsAffected() > 0)
@@ -119,11 +138,11 @@
else
{
proginfo->chanstr = "#" + proginfo->chanid;
- proginfo->channame = "#" + proginfo->chanid;
- proginfo->chansign = "#" + proginfo->chanid;
+ proginfo->channame = proginfo->chanstr;
+ proginfo->chansign = proginfo->chanstr;
}

- item = new ProgramListItem(context, listview, proginfo, 0, tv,
+ item = new ProgramListItem(context, listview, proginfo, type==Delete, tv,
fileprefix);
}
}
@@ -131,8 +150,11 @@
{
// TODO: no recordings
}
-
- listview->setFixedHeight((int)(300 * hmult));
+
+ if(type == Delete)
+ listview->setFixedHeight((int)(225 * hmult));
+ else
+ listview->setFixedHeight((int)(300 * hmult));

QHBoxLayout *hbox = new QHBoxLayout(vbox, (int)(10 * wmult));

@@ -168,8 +190,8 @@
grid->setColStretch(1, 1);
grid->setRowStretch(4, 1);

- if (m_context->GetNumSetting("GeneratePreviewPixmap") == 1 ||
- m_context->GetNumSetting("PlaybackPreview") == 1)
+ if (context->GetNumSetting("GeneratePreviewPixmap") == 1 ||
+ context->GetNumSetting("PlaybackPreview") == 1)
{
QPixmap temp((int)(160 * wmult), (int)(120 * hmult));

@@ -181,6 +203,15 @@
else
pixlabel = NULL;

+ if(type == Delete) {
+ freespace = new QLabel(" ", this);
+ vbox->addWidget(freespace);
+
+ progressbar = new QProgressBar(this);
+ UpdateProgressBar();
+ vbox->addWidget(progressbar);
+ }
+
nvp = NULL;
timer = new QTimer(this);

@@ -264,13 +295,22 @@
{
killPlayer();

+ if (!title)
+ return;
+
ProgramListItem *pgitem = (ProgramListItem *)lvitem;
if (!pgitem)
+ {
+ title->setText("");
+ date->setText("");
+ chan->setText("");
+ subtitle->setText("");
+ description->setText("");
+ if (pixlabel)
+ pixlabel->setPixmap(QPixmap(0, 0));
return;
+ }

- if (!title)
- return;
-
ProgramInfo *rec = pgitem->getProgramInfo();

if (m_context->GetNumSetting("PlaybackPreview") == 1)
@@ -321,8 +361,35 @@
timer->start(1000 / 30);
}

+static void *SpawnDelete(void *param)
+{
+ QString *filenameptr = (QString *)param;
+ QString filename = *filenameptr;
+
+ unlink(filename.ascii());
+
+ filename += ".png";
+ unlink(filename.ascii());
+
+ filename = *filenameptr;
+ filename += ".bookmark";
+ unlink(filename.ascii());
+
+ delete filenameptr;
+
+ return NULL;
+}
+
void PlaybackBox::selected(QListViewItem *lvitem)
{
+ switch(type) {
+ case Play: play(lvitem); break;
+ case Delete: remove(lvitem); break;
+ }
+}
+
+void PlaybackBox::play(QListViewItem *lvitem)
+{
killPlayer();

ProgramListItem *pgitem = (ProgramListItem *)lvitem;
@@ -336,6 +403,156 @@

startPlayer(rec);
timer->start(1000 / 30);
+}
+
+void PlaybackBox::remove(QListViewItem *lvitem)
+{
+ killPlayer();
+
+ ProgramListItem *pgitem = (ProgramListItem *)lvitem;
+ ProgramInfo *rec = pgitem->getProgramInfo();
+
+ QString message = "Are you sure you want to delete:<br><br>";
+ message += rec->title;
+ message += "<br>";
+
+ QDateTime startts = rec->startts;
+ QDateTime endts = rec->endts;
+
+ QString dateformat = m_context->GetSetting("DateFormat");
+ if (dateformat == "")
+ dateformat = "ddd MMMM d";
+ QString timeformat = m_context->GetSetting("TimeFormat");
+ if (timeformat == "")
+ timeformat = "h:mm AP";
+
+ QString timedate = endts.date().toString(dateformat) + QString(", ") +
+ startts.time().toString(timeformat) + QString(" - ") +
+ endts.time().toString(timeformat);
+
+ message += timedate;
+ message += "<br>";
+ if (rec->subtitle != "(null)")
+ message += rec->subtitle;
+ message += "<br>";
+ if (rec->description != "(null)")
+ message += rec->description;
+
+ message += "<br><br>It will be gone forever.";
+
+ DialogBox diag(m_context, message);
+
+ diag.AddButton("Yes, get rid of it");
+ diag.AddButton("No, keep it, I changed my mind");
+
+ diag.Show();
+
+ int result = diag.exec();
+
+ if (result == 1)
+ {
+ QString filename = rec->GetRecordFilename(fileprefix);
+
+ QSqlQuery query;
+ QString thequery;
+
+ QString startts = rec->startts.toString("yyyyMMddhhmm");
+ startts += "00";
+ QString endts = rec->endts.toString("yyyyMMddhhmm");
+ endts += "00";
+
+ thequery = QString("DELETE FROM recorded WHERE chanid = %1 AND title "
+ "= \"%2\" AND starttime = %3 AND endtime = %4;")
+ .arg(rec->chanid).arg(rec->title).arg(startts)
+ .arg(endts);
+
+ query = db->exec(thequery);
+ if (!query.isActive())
+ {
+ cerr << "DB Error: recorded program deletion failed, SQL query "
+ << "was:" << endl;
+ cerr << thequery << endl;
+ }
+
+ QString *fileptr = new QString(filename);
+
+ pthread_t deletethread;
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ pthread_create(&deletethread, &attr, SpawnDelete, fileptr);
+
+ if (lvitem->itemBelow())
+ {
+ listview->setCurrentItem(lvitem->itemBelow());
+ listview->setSelected(lvitem->itemBelow(), true);
+ }
+ else if (lvitem->itemAbove())
+ {
+ listview->setCurrentItem(lvitem->itemAbove());
+ listview->setSelected(lvitem->itemAbove(), true);
+ }
+ else
+ changed(NULL);
+
+ delete lvitem;
+ UpdateProgressBar();
+ }
+ else if (m_context->GetNumSetting("PlaybackPreview") == 1)
+ startPlayer(rec);
+
+ setActiveWindow();
+ raise();
+
+ timer->start(1000 / 30);
+}
+
+void PlaybackBox::GetFreeSpaceStats(int &totalspace, int &usedspace)
+{
+ QString command;
+ command.sprintf("df -k -P %s", fileprefix.ascii());
+
+ FILE *file = popen(command.ascii(), "r");
+
+ if (!file)
+ {
+ totalspace = -1;
+ usedspace = -1;
+ }
+ else
+ {
+ char buffer[1024];
+ fgets(buffer, 1024, file);
+ fgets(buffer, 1024, file);
+
+ char dummy[1024];
+ int dummyi;
+ sscanf(buffer, "%s %d %d %d %s %s\n", dummy, &totalspace, &usedspace,
+ &dummyi, dummy, dummy);
+
+ totalspace /= 1000;
+ usedspace /= 1000;
+ pclose(file);
+ }
+}
+
+void PlaybackBox::UpdateProgressBar(void)
+{
+ int total, used;
+ GetFreeSpaceStats(total, used);
+
+ QString usestr;
+ char text[128];
+ sprintf(text, "Storage: %d,%03d MB used out of %d,%03d MB total",
+ used / 1000, used % 1000,
+ total / 1000, total % 1000);
+
+ usestr = text;
+
+ freespace->setText(usestr);
+ progressbar->setTotalSteps(total);
+ progressbar->setProgress(used);
}

void PlaybackBox::timeout(void)
Index: programs/mythfrontend/playbackbox.h
===================================================================
RCS file: /var/lib/cvs/MC/programs/mythfrontend/playbackbox.h,v
retrieving revision 1.8
diff -u -r1.8 playbackbox.h
--- programs/mythfrontend/playbackbox.h 31 Oct 2002 20:23:49 -0000 1.8
+++ programs/mythfrontend/playbackbox.h 12 Nov 2002 07:22:05 -0000
@@ -8,7 +8,9 @@

class QSqlDatabase;
class QListViewItem;
+class MyListView;
class QLabel;
+class QProgressBar;
class TV;
class NuppelVideoPlayer;
class RingBuffer;
@@ -20,7 +22,10 @@
{
Q_OBJECT
public:
+ typedef enum { Play, Delete } BoxType;
+ BoxType type;
PlaybackBox(MythContext *context, TV *ltv, QSqlDatabase *ldb,
+ BoxType ltype,
QWidget *parent = 0, const char *name = 0);
~PlaybackBox(void);

@@ -28,10 +33,15 @@

protected slots:
void selected(QListViewItem *);
+ void remove(QListViewItem *);
+ void play(QListViewItem *);
void changed(QListViewItem *);
void timeout(void);

private:
+ void GetFreeSpaceStats(int &totalspace, int &usedspace);
+ void UpdateProgressBar(void);
+
QSqlDatabase *db;
TV *tv;

@@ -44,6 +54,11 @@
QLabel *chan;
QLabel *pixlabel;

+ MyListView *listview;
+
+ QLabel *freespace;
+ QProgressBar *progressbar;
+
float wmult, hmult;
int descwidth;

Index: programs/mythfrontend/programlistitem.cpp
===================================================================
RCS file: /var/lib/cvs/MC/programs/mythfrontend/programlistitem.cpp,v
retrieving revision 1.22
diff -u -r1.22 programlistitem.cpp
--- programs/mythfrontend/programlistitem.cpp 30 Oct 2002 14:52:14 -0000 1.22
+++ programs/mythfrontend/programlistitem.cpp 12 Nov 2002 07:22:05 -0000
@@ -14,16 +14,23 @@

void MyListView::keyPressEvent(QKeyEvent *e)
{
- if (e->key() == Key_Space)
+ if ( currentItem() && !currentItem()->isEnabled() )
{
- if ( currentItem() && !currentItem()->isEnabled() )
- {
- }
- else
- {
- emit spacePressed( currentItem() );
- return;
- }
+ }
+ else
+ switch(e->key())
+ {
+ case 'D':
+ emit deletePressed( currentItem() );
+ return;
+ case 'P':
+ emit playPressed( currentItem() );
+ return;
+ case Key_Space:
+ emit spacePressed( currentItem() );
+ return;
+ default:
+ cout << "Unhandled Key Jim: " << e->key() << endl;
}

QListView::keyPressEvent(e);
Index: programs/mythfrontend/programlistitem.h
===================================================================
RCS file: /var/lib/cvs/MC/programs/mythfrontend/programlistitem.h,v
retrieving revision 1.7
diff -u -r1.7 programlistitem.h
--- programs/mythfrontend/programlistitem.h 30 Oct 2002 06:30:34 -0000 1.7
+++ programs/mythfrontend/programlistitem.h 12 Nov 2002 07:22:05 -0000
@@ -2,17 +2,27 @@
#define PROGRAMLISTITEM_H_

#include <qlistview.h>
+#include <qpixmap.h>
+
+#include "libmyth/programinfo.h"

class ProgramInfo;
class QPixmap;
+class MythContext;
+class TV;

class MyListView : public QListView
{
+ Q_OBJECT
public:
MyListView(QWidget *parent) : QListView(parent) {}

protected:
void keyPressEvent( QKeyEvent *e );
+
+ signals:
+ void playPressed( QListViewItem * );
+ void deletePressed( QListViewItem * );
};

class ProgramListItem : public QListViewItem
Re: [PATCH] Semi-unify Record/Delete menus [ In reply to ]
On Tuesday 12 November 2002 02:36 am, Jim Radford wrote:
> Here's the merge. With this you can now 'P' (play) or 'D' (delete)
> from either menu and Space/Enter performs the default action.
>
> There are a few "spacing" differences between play and record that I
> emulated verbatim. Isaac, you might want to check and see if one or
> the other of values would be sufficient.

Looks good, I'll get it applied tonight.

Isaac