Rivendellaudio/rdlogmanager/edit_clock.cpp
Fred Gleason b09942e494 2015-02-06 Fred Gleason <fredg@paravelsystems.com>
* Cleaned up Qt object calls in 'rdlogmanager/'.
2015-02-06 19:18:11 -05:00

805 lines
20 KiB
C++

// edit_clock.cpp
//
// Edit Rivendell Log Clock
//
// (C) Copyright 2002-2015 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <vector>
#include <math.h>
#include <qdialog.h>
#include <qstring.h>
#include <qtextedit.h>
#include <qpainter.h>
#include <qmessagebox.h>
#include <qcolordialog.h>
#include <qspinbox.h>
#include <qcombobox.h>
#include <rddb.h>
#include <rd.h>
#include <rdconf.h>
#include <rdevent.h>
#include <rdcreate_log.h>
#include <rdescape_string.h>
#include <edit_clock.h>
#include <add_clock.h>
#include <edit_eventline.h>
#include <edit_perms.h>
#include <edit_event.h>
#include <list_clocks.h>
#include <edit_schedrules.h>
EditClock::EditClock(QString clockname,bool new_clock,
std::vector<QString> *new_clocks,QWidget *parent)
: QDialog(parent,"",true)
{
QString str;
str=QString(tr("Edit Clock:"));
setCaption(QString().sprintf("%s %s",(const char *)str,
(const char *)clockname));
edit_name=clockname;
edit_new_clock=new_clock;
edit_new_clocks=new_clocks;
//
// Fix the Window Size
//
setMinimumWidth(sizeHint().width());
setMaximumWidth(sizeHint().width());
setMinimumHeight(sizeHint().height());
setMaximumHeight(sizeHint().height());
//
// Create Fonts
//
QFont bold_font=QFont("Helvetica",12,QFont::Bold);
bold_font.setPixelSize(12);
QFont font=QFont("Helvetica",12,QFont::Normal);
font.setPixelSize(12);
edit_title_font=new QFont("Helvetica",24,QFont::Bold);
edit_title_font->setPixelSize(24);
edit_title_metrics=new QFontMetrics(*edit_title_font);
//
// Clock Names
//
edit_clockname_label=new QLabel(clockname,this);
edit_clockname_label->setGeometry(10,10,280,20);
edit_clockname_label->setFont(bold_font);
edit_shortname_edit=new QLineEdit(this);
edit_shortname_edit->setGeometry(350,10,40,20);
edit_shortname_edit->setMaxLength(3);
QLabel *label=new QLabel(edit_shortname_edit,tr("Code:"),this);
label->setGeometry(295,10,50,20);
label->setFont(bold_font);
label->setAlignment(AlignRight|AlignVCenter);
//
// Clock List
//
edit_clocks_list=new ClockListView(this);
edit_clocks_list->setGeometry(10,35,CENTER_LINE-20,sizeHint().height()-250);
edit_clocks_list->setAllColumnsShowFocus(true);
edit_clocks_list->setItemMargin(5);
edit_clocks_list->addColumn(tr("Start"));
edit_clocks_list->addColumn(tr("End"));
edit_clocks_list->addColumn(tr("Event"));
edit_clocks_list->addColumn(tr("Length"));
edit_clocks_list->setColumnAlignment(3,AlignRight);
edit_clocks_list->addColumn(tr("Count"));
edit_clocks_list->setColumnAlignment(4,AlignCenter);
connect(edit_clocks_list,
SIGNAL(doubleClicked(QListViewItem *,const QPoint &,int)),
this,SLOT(doubleClickedData(QListViewItem *,const QPoint &,int)));
connect(edit_clocks_list,SIGNAL(selectionChanged(QListViewItem *)),
this,SLOT(selectionChangedData(QListViewItem *)));
connect(edit_clocks_list,SIGNAL(editLine(int)),
this,SLOT(editEventData(int)));
//
// Add Button
//
QPushButton *button=new QPushButton(this);
button->setGeometry(10,sizeHint().height()-210,80,50);
button->setFont(bold_font);
button->setText(tr("&Add"));
connect(button,SIGNAL(clicked()),this,SLOT(addData()));
//
// Clone Button
//
button=new QPushButton(this);
button->setGeometry(110,sizeHint().height()-210,80,50);
button->setFont(bold_font);
button->setText(tr("&Clone"));
connect(button,SIGNAL(clicked()),this,SLOT(cloneData()));
//
// Edit Button
//
button=new QPushButton(this);
button->setGeometry(210,sizeHint().height()-210,80,50);
button->setFont(bold_font);
button->setText(tr("&Edit"));
connect(button,SIGNAL(clicked()),this,SLOT(editData()));
//
// Delete Button
//
button=new QPushButton(this);
button->setGeometry(310,sizeHint().height()-210,80,50);
button->setFont(bold_font);
button->setText(tr("&Delete"));
connect(button,SIGNAL(clicked()),this,SLOT(deleteData()));
//
// Remarks
//
edit_remarks_edit=new QTextEdit(this);
edit_remarks_edit->setGeometry(10,sizeHint().height()-140,CENTER_LINE-20,130);
edit_remarks_edit->setTextFormat(QTextEdit::PlainText);
label=new QLabel(edit_remarks_edit,tr("Remarks"),this);
label->setGeometry(15,sizeHint().height()-155,CENTER_LINE-20,15);
label->setFont(bold_font);
label->setAlignment(AlignLeft|AlignVCenter);
//
// Scheduler-Rules button
//
button=new QPushButton(this);
button->setGeometry(CENTER_LINE+20,sizeHint().height()-60,70,50);
button->setFont(bold_font);
button->setText(tr("Scheduler\nRules"));
connect(button,SIGNAL(clicked()),this,SLOT(schedRules()));
//
// Save Button
//
button=new QPushButton(this);
button->setGeometry(CENTER_LINE+110,sizeHint().height()-60,70,50);
button->setFont(bold_font);
button->setText(tr("&Save"));
connect(button,SIGNAL(clicked()),this,SLOT(saveData()));
//
// Save As Button
//
button=new QPushButton(this);
button->setGeometry(CENTER_LINE+190,sizeHint().height()-60,70,50);
button->setFont(bold_font);
button->setText(tr("Save &As"));
connect(button,SIGNAL(clicked()),this,SLOT(saveAsData()));
//
// Service Associations Button
//
button=new QPushButton(this);
button->setGeometry(CENTER_LINE+(sizeHint().width()-CENTER_LINE)/2-25,
sizeHint().height()-60,70,50);
button->setFont(bold_font);
button->setText(tr("&Services\nList"));
connect(button,SIGNAL(clicked()),this,SLOT(svcData()));
//
// Color Button
//
edit_color_button=new QPushButton(this);
edit_color_button->
setGeometry(CENTER_LINE+(sizeHint().width()-CENTER_LINE)/2+55,
sizeHint().height()-60,70,50);
edit_color_button->setFont(bold_font);
edit_color_button->setText(tr("Colo&r"));
connect(edit_color_button,SIGNAL(clicked()),this,SLOT(colorData()));
//
// Clock Display
//
edit_clock_label=new QLabel(this);
edit_clock_label->
setGeometry(CENTER_LINE+10,10,
sizeHint().width()-CENTER_LINE-20,sizeHint().height()-80);
//
// OK Button
//
button=new QPushButton(this);
button->setGeometry(sizeHint().width()-160,sizeHint().height()-60,70,50);
button->setDefault(true);
button->setFont(bold_font);
button->setText(tr("&OK"));
connect(button,SIGNAL(clicked()),this,SLOT(okData()));
//
// Cancel Button
//
button=new QPushButton(this);
button->setGeometry(sizeHint().width()-80,sizeHint().height()-60,70,50);
button->setFont(bold_font);
button->setText(tr("&Cancel"));
connect(button,SIGNAL(clicked()),this,SLOT(cancelData()));
//
// Populate Data
//
sched_rules_list = new SchedRulesList(clockname);
edit_clock=new RDClock();
edit_clock->setName(clockname);
edit_clock->load();
edit_shortname_edit->setText(edit_clock->shortName());
if(edit_clock->color().isValid()) {
edit_color_button->
setPalette(QPalette(edit_clock->color(),backgroundColor()));
}
edit_remarks_edit->setText(edit_clock->remarks());
edit_modified=false;
RefreshList();
}
QSize EditClock::sizeHint() const
{
return QSize(1024,698);
}
QSizePolicy EditClock::sizePolicy() const
{
return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
}
void EditClock::selectionChangedData(QListViewItem *l)
{
if(l==NULL) {
UpdateClock();
return;
}
RDListViewItem *item=(RDListViewItem *)l;
if(item->text(3).isEmpty()) {
UpdateClock();
return;
}
UpdateClock(item->text(4).toInt());
}
void EditClock::addData()
{
int line=0;
RDEventLine eventline;
RDListViewItem *item=(RDListViewItem *)edit_clocks_list->selectedItem();
if(item!=NULL) {
if(item->text(4).isEmpty()) {
line=edit_clock->size();
}
else {
line=item->text(4).toInt();
}
}
EditEventLine *edit_eventline=
new EditEventLine(&eventline,edit_clock,-1,this);
if(edit_eventline->exec()<0) {
return;
}
delete edit_eventline;
edit_clock->insert(eventline.name(),line);
edit_clock->eventLine(line)->setStartTime(eventline.startTime());
edit_clock->eventLine(line)->setLength(eventline.length());
edit_clock->eventLine(line)->load();
edit_modified=true;
RefreshList(line);
}
void EditClock::editData()
{
RDListViewItem *item=(RDListViewItem *)edit_clocks_list->selectedItem();
if(item==NULL) {
return;
}
if(item->text(4).isEmpty()) {
return;
}
int line=item->text(4).toInt();
EditEventLine *edit_eventline=
new EditEventLine(edit_clock->eventLine(line),edit_clock,line,this);
if(edit_eventline->exec()<0) {
delete edit_eventline;
return;
}
delete edit_eventline;
edit_clock->eventLine(line)->load();
edit_modified=true;
RefreshList();
}
void EditClock::cloneData()
{
RDListViewItem *item=(RDListViewItem *)edit_clocks_list->selectedItem();
if(item==NULL) {
return;
}
if(item->text(4).isEmpty()) {
return;
}
int line=item->text(4).toInt();
RDEventLine *selectedEventLine = edit_clock->eventLine(line);
RDEventLine eventline;
eventline.setName(selectedEventLine->name());
eventline.setStartTime(selectedEventLine->startTime().addMSecs(selectedEventLine->length()));
eventline.setLength(selectedEventLine->length());
EditEventLine *edit_eventline=
new EditEventLine(&eventline,edit_clock,-1,this);
if(edit_eventline->exec()<0) {
delete edit_eventline;
return;
}
delete edit_eventline;
edit_clock->insert(eventline.name(),line);
edit_clock->eventLine(line)->setStartTime(eventline.startTime());
edit_clock->eventLine(line)->setLength(eventline.length());
edit_clock->eventLine(line)->load();
edit_modified=true;
RefreshList(line);
}
void EditClock::deleteData()
{
QString str;
RDListViewItem *item=(RDListViewItem *)edit_clocks_list->selectedItem();
if(item==NULL) {
return;
}
if(item->text(4).isEmpty()) {
return;
}
str=QString(tr("Are you sure you want to\ndelete"));
if(QMessageBox::question(this,tr("Delete Event"),
QString().sprintf("%s \'%s\'?",(const char *)str,
(const char *)item->text(3)),
QMessageBox::Yes,QMessageBox::No)!=
QMessageBox::Yes) {
return;
}
edit_clock->remove(item->text(4).toInt());
edit_modified=true;
RefreshList();
}
void EditClock::schedRules()
{
unsigned edit_artistsep = edit_clock->getArtistSep();
QString clock_name = edit_clock->name();
bool rules_modified = edit_clock->getRulesModified();
EditSchedRules *dialog=
new EditSchedRules(clock_name,&edit_artistsep,sched_rules_list,
&rules_modified,this);
dialog->exec();
if (edit_clock->getArtistSep()!=edit_artistsep)
{
edit_modified=true;
}
edit_clock->setArtistSep(edit_artistsep);
edit_clock->setRulesModified(rules_modified);
if(rules_modified)
{
edit_modified=true;
}
delete dialog;
}
void EditClock::svcData()
{
EditPerms *dialog=new EditPerms(edit_name,EditPerms::ObjectClock,
this,"dialog");
dialog->exec();
delete dialog;
}
void EditClock::saveData()
{
if(!ValidateCode()) {
return;
}
Save();
edit_new_clock=false;
}
void EditClock::saveAsData()
{
QString clockname=edit_name;
QString sql;
RDSqlQuery *q;
QString str;
if(!ValidateCode()) {
return;
}
QString old_name=edit_name;
if(edit_modified) {
switch(QMessageBox::question(this,tr("Clock Modified"),
tr("The clock has been modified.\nDo you want to save?"),QMessageBox::Yes,QMessageBox::No,QMessageBox::Cancel)) {
case QMessageBox::Yes:
Save();
break;
case QMessageBox::Cancel:
case QMessageBox::NoButton:
return;
break;
}
}
if(edit_shortname_edit->text().isEmpty()) {
QMessageBox::warning(this,tr("Missing Clock Code"),
tr("You must specify a clock code!"));
return;
}
sql=
QString().sprintf("select SHORT_NAME from CLOCKS where SHORT_NAME=\"%s\"",
(const char *)
RDEscapeString(edit_shortname_edit->text()));
q=new RDSqlQuery(sql);
if(q->first()) {
QMessageBox::warning(this,tr("Code Exists"),
tr("The clock code is already in use!"));
delete q;
return;
}
delete q;
AddClock *addclock=new AddClock(&clockname,this,"addclock");
if(addclock->exec()<0) {
delete addclock;
return;
}
delete addclock;
edit_name=clockname;
sql=QString().sprintf("select NAME from CLOCKS where NAME=\"%s\"",
(const char *)clockname);
q=new RDSqlQuery(sql);
if(q->first()) {
if(QMessageBox::question(this,tr("Clock Exists"),
tr("Clock already exists! Overwrite?"),QMessageBox::Yes,QMessageBox::No)!=QMessageBox::Yes) {
delete q;
return;
}
}
delete q;
edit_clock->setName(clockname);
sql=RDCreateClockTableSql(RDClock::tableName(clockname));
q=new RDSqlQuery(sql);
delete q;
Save();
edit_new_clocks->push_back(clockname);
CopyClockPerms(old_name,clockname);
if(edit_new_clock) {
AbandonClock(old_name);
}
edit_clockname_label->setText(clockname);
UpdateClock();
str=QString(tr("Edit Clock:"));
setCaption(QString().sprintf("%s %s",(const char *)str,
(const char *)edit_name));
}
void EditClock::doubleClickedData(QListViewItem *item,const QPoint &,int)
{
editData();
}
void EditClock::colorData()
{
QColor color=QColorDialog::getColor(edit_color_button->backgroundColor(),
this,"color_dialog");
if(color.isValid()) {
edit_color_button->setPalette(QPalette(color,backgroundColor()));
}
}
void EditClock::editEventData(int line)
{
std::vector<QString> new_events;
RDEventLine *event=edit_clock->eventLine(line);
if(event==NULL) {
return;
}
EditEvent *dialog=new EditEvent(event->name(),false,&new_events,
this,"dialog");
if(dialog->exec()<-1) {
delete dialog;
return;
}
delete dialog;
RefreshNames();
}
void EditClock::okData()
{
if(!ValidateCode()) {
return;
}
Save();
done(0);
}
void EditClock::cancelData()
{
if(edit_modified) {
switch(QMessageBox::question(this,tr("Clock Modified"),
tr("The clock has been modified.\nDo you want to save?"),QMessageBox::Yes,QMessageBox::No,QMessageBox::Cancel)) {
case QMessageBox::Yes:
Save();
done(0);
break;
case QMessageBox::No:
done(-1);
break;
case QMessageBox::NoButton:
return;
}
}
else {
done(-1);
}
}
void EditClock::paintEvent(QPaintEvent *e)
{
QPainter *p=new QPainter(this);
p->setPen(QColor(black));
p->moveTo(CENTER_LINE,10);
p->lineTo(CENTER_LINE,sizeHint().height()-10);
p->end();
}
void EditClock::closeEvent(QCloseEvent *e)
{
cancelData();
}
void EditClock::Save()
{
edit_clock->setColor(edit_color_button->backgroundColor());
edit_clock->setShortName(edit_shortname_edit->text());
edit_clock->setRemarks(edit_remarks_edit->text());
edit_clock->save();
if(edit_clock->getRulesModified())
{
sched_rules_list->Save(edit_clock->name());
edit_clock->setRulesModified(false);
}
edit_modified=false;
}
void EditClock::RefreshList(int select_line)
{
UpdateClock();
RDListViewItem *prev_item=(RDListViewItem *)edit_clocks_list->selectedItem();
if((prev_item!=NULL)&&(select_line>=0)) {
select_line=prev_item->text(4).toInt();
}
RDListViewItem *item;
RDEventLine *eventline;
edit_clocks_list->clear();
item=new RDListViewItem(edit_clocks_list);
item->setText(2,tr("--- End of clock ---"));
for(int i=edit_clock->size()-1;i>=0;i--) {
if((eventline=edit_clock->eventLine(i))!=NULL) {
item=new RDListViewItem(edit_clocks_list);
item->setText(0,eventline->startTime().toString("mm:ss.zzz").left(7));
item->setText(1,eventline->startTime().
addMSecs(eventline->length()).toString("mm:ss.zzz").
left(7));
item->setText(3,RDGetTimeLength(eventline->length(),false,true));
item->setText(2,QString().sprintf("%s [%s]",
(const char *)eventline->name(),
(const char *)eventline->properties()));
item->setText(4,QString().sprintf("%d",i));
if(eventline->color().isValid()) {
item->setBackgroundColor(eventline->color());
}
if(i==select_line) {
edit_clocks_list->setSelected(item,true);
}
}
}
}
void EditClock::RefreshNames()
{
QString sql;
RDSqlQuery *q;
RDEventLine *eventline=NULL;
RDListViewItem *item=(RDListViewItem *)edit_clocks_list->firstChild();
while(item!=NULL) {
if(!item->text(4).isEmpty()) {
if((eventline=edit_clock->eventLine(item->text(4).toInt()))!=NULL) {
sql=QString().sprintf("select PROPERTIES from EVENTS\
where NAME=\"%s\"",
(const char *)RDEscapeString(eventline->name()));
q=new RDSqlQuery(sql);
if(q->next()) {
item->
setText(2,QString().sprintf("%s [%s]",
(const char *)eventline->name(),
(const char *)q->value(0).toString()));
}
delete q;
}
}
item=(RDListViewItem *)item->nextSibling();
}
}
void EditClock::UpdateClock(int line)
{
QPixmap *map=new QPixmap(edit_clock_label->size());
map->fill();
QPainter *p=new QPainter();
p->begin(map);
p->setPen(QColor(black));
p->setBrush(QColor(black));
p->setFont(*edit_title_font);
//
// Title
//
p->drawText((edit_clock_label->size().width()-
edit_title_metrics->width(edit_clock->name()))/2,
50,edit_clock->name());
//
// Pie Circle
//
p->translate(edit_clock_label->size().width()/2,
edit_clock_label->size().height()/2);
p->rotate(-90.0);
int size_x=edit_clock_label->size().width()-2*PIE_X_MARGIN;
int size_y=edit_clock_label->size().width()-2*PIE_X_MARGIN;
p->drawArc(-size_x/2,-size_y/2,size_x,size_y,0,5760);
//
// Segments
//
for(int i=0;i<edit_clock->size();i++) {
if(i==line) {
p->setBrush(edit_clocks_list->palette().
color(QPalette::Active,QColorGroup::Highlight));
p->drawPie(-size_x/2,-size_y/2,size_x,size_y,
-QTime().secsTo(edit_clock->eventLine(line)->startTime())*5760/3600,
-(edit_clock->eventLine(line)->length()/1000)*5760/3600);
}
else {
if(edit_clock->eventLine(i)->color().isValid()) {
p->setBrush(edit_clock->eventLine(i)->color());
}
else {
p->setBrush(palette().color(QPalette::Active,QColorGroup::Base));
}
p->drawPie(-size_x/2,-size_y/2,size_x,size_y,
-QTime().secsTo(edit_clock->eventLine(i)->startTime())*5760/3600,
-(edit_clock->eventLine(i)->length()/1000)*5760/3600);
}
}
p->end();
delete p;
edit_clock_label->setPixmap(*map);
delete map;
}
void EditClock::CopyClockPerms(QString old_name,QString new_name)
{
QString sql;
RDSqlQuery *q;
RDSqlQuery *q1;
sql=QString().sprintf("select SERVICE_NAME from CLOCK_PERMS where\
CLOCK_NAME=\"%s\"",
(const char *)RDEscapeString(old_name));
q=new RDSqlQuery(sql);
while(q->next()) {
sql=QString().sprintf("insert into CLOCK_PERMS set\
CLOCK_NAME=\"%s\",SERVICE_NAME=\"%s\"",
(const char *)RDEscapeString(new_name),
(const char *)RDEscapeString(q->value(0).toString()));
q1=new RDSqlQuery(sql);
delete q1;
}
delete q;
}
void EditClock::AbandonClock(QString name)
{
if(name==edit_name) {
return;
}
QString sql=QString().sprintf("delete from CLOCKS where NAME=\"%s\"",
(const char *)name);
RDSqlQuery *q=new RDSqlQuery(sql);
delete q;
sql=QString("drop table `")+RDClock::tableName(name)+"`";
q=new RDSqlQuery(sql);
delete q;
}
bool EditClock::ValidateCode()
{
if(edit_shortname_edit->text().isEmpty()) {
QMessageBox::information(this,tr("Invalid Code"),
tr("You must provide a clock code!"));
return false;
}
RDSqlQuery *q=
new RDSqlQuery(QString().
sprintf("select SHORT_NAME from CLOCKS\
where (SHORT_NAME=\"%s\")&&\
(NAME!=\"%s\")",
(const char *)
RDEscapeString(edit_shortname_edit->text()),
(const char *)RDEscapeString(edit_name)));
if(q->next()) {
QMessageBox::information(this,tr("Duplicate Code"),
tr("That code is already in use!"));
delete q;
return false;
}
delete q;
return true;
}