Rivendellaudio/rdlogmanager/generate_log.cpp
Fred Gleason e30fe2b0b7 2021-08-31 Fred Gleason <fredg@paravelsystems.com>
* Added a 'SERVICES.INCLUDE_MUS_IMPORT_MARKERS' field to the database.
	* Added a 'SERVICES.INCLUDE_TFC_IMPORT_MARKERS' field to the database.
	* Added a 'LOGS.INCLUDE_MUS_IMPORT_MARKERS' field to the database.
	* Added a 'LOGS.INCLUDE_TFC_IMPORT_MARKERS' field to the database.
	* Incremented the database version to 354.
	* Replaced the 'Include Import Marker in Finished Logs' checkbox
	with 'Include Music Import Markers in Finished Logs' and
	'Include Traffic Import Markers in Finished Logs' checkboxes in
	the 'Edit Service' dialog in rdadmin(1).

Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
2021-08-31 13:24:57 -04:00

649 lines
19 KiB
C++

// generate_log.cpp
//
// Generate a Rivendell Log
//
// (C) Copyright 2002-2021 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 <QMessageBox>
#include <rddatedecode.h>
#include <rddatedialog.h>
#include <rdlog.h>
#include <rdsvc.h>
#include <rdtextfile.h>
#include "edit_grid.h"
#include "generate_log.h"
#include "globals.h"
GenerateLog::GenerateLog(QWidget *parent,int cmd_switch,QString *cmd_service,
QDate *cmd_date)
: RDDialog(parent)
{
QStringList services_list;
bool cmdservicefit=false;
cmdswitch=cmd_switch;
cmdservice = cmd_service;
cmddate = cmd_date;
setWindowTitle("RDLogManager - "+tr("Generate Log"));
gen_music_enabled=false;
gen_traffic_enabled=false;
//
// Fix the Window Size
//
setMinimumSize(sizeHint());
setMaximumSize(sizeHint());
//
// Progress Dialog
//
gen_progress_dialog=
new QProgressDialog(tr("Generating Log..."),tr("Cancel"),0,24,this);
gen_progress_dialog->setWindowTitle("Progress");
gen_progress_dialog->setCancelButton(NULL);
gen_progress_dialog->setValue(24);
//
// Service Name
//
gen_service_box=new RDComboBox(this);
connect(gen_service_box,SIGNAL(activated(int)),
this,SLOT(serviceActivatedData(int)));
gen_service_label=new QLabel(tr("Service:"),this);
gen_service_label->setFont(labelFont());
gen_service_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
QString sql="select `NAME` from `SERVICES`";
RDSqlQuery *q=new RDSqlQuery(sql);
while(q->next()) {
services_list.append( q->value(0).toString() );
}
delete q;
for ( QStringList::Iterator it = services_list.begin();
it != services_list.end();
++it ) {
gen_service_box->insertItem(*it);
if (cmdswitch != 0 && *cmdservice == *it)
cmdservicefit=true;
}
//
// Date
//
gen_date_edit=new RDDateEdit(this);
gen_date_label=new QLabel(tr("Date:"),this);
gen_date_label->setFont(labelFont());
gen_date_label->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
if (cmdswitch==0)
gen_date_edit->setDate(QDate::currentDate().addDays(1));
else
gen_date_edit->setDate(*cmddate);
connect(gen_date_edit,SIGNAL(dateChanged(const QDate &)),
this,SLOT(dateChangedData(const QDate &)));
//
// Date Select Button
//
gen_select_button=new QPushButton(this);
gen_select_button->setFont(subButtonFont());
gen_select_button->setText(tr("Select"));
connect(gen_select_button,SIGNAL(clicked()),this,SLOT(selectDateData()));
//
// Create Log Button
//
gen_create_button=new QPushButton(this);
gen_create_button->setFont(buttonFont());
gen_create_button->setText(tr("Create New Log"));
connect(gen_create_button,SIGNAL(clicked()),this,SLOT(createData()));
//
// Merge Music Log Button
//
gen_music_button=new QPushButton(this);
gen_music_button->setFont(buttonFont());
gen_music_button->setText(tr("Merge Music"));
connect(gen_music_button,SIGNAL(clicked()),this,SLOT(musicData()));
//
// Merge Traffic Log Button
//
gen_traffic_button=new QPushButton(this);
gen_traffic_button->setFont(buttonFont());
gen_traffic_button->setText(tr("Merge Traffic"));
connect(gen_traffic_button,SIGNAL(clicked()),this,SLOT(trafficData()));
//
// Status Lights
//
// Headers
//
gen_import_label=new QLabel(tr("Import Data"),this);
gen_import_label->setFont(labelFont());
gen_import_label->setAlignment(Qt::AlignCenter);
gen_available_label=new QLabel(tr("Available"),this);
gen_available_label->setFont(subLabelFont());
gen_available_label->setAlignment(Qt::AlignCenter);
gen_merged_label=new QLabel(tr("Merged"),this);
gen_merged_label->setFont(subLabelFont());
gen_merged_label->setAlignment(Qt::AlignCenter);
//
// Music Indicators
//
gen_mus_avail_label=new QLabel(this);
gen_mus_avail_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
gen_mus_avail_label->setFont(subLabelFont());
gen_mus_avail_label->setAlignment(Qt::AlignCenter);
gen_mus_merged_label=new QLabel(this);
gen_mus_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
gen_mus_merged_label->setFont(subLabelFont());
gen_mus_merged_label->setAlignment(Qt::AlignCenter);
//
// Traffic Indicators
//
gen_tfc_avail_label=new QLabel(this);
gen_tfc_avail_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
gen_tfc_avail_label->setFont(subLabelFont());
gen_tfc_avail_label->setAlignment(Qt::AlignCenter);
gen_tfc_merged_label=new QLabel(this);
gen_tfc_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
gen_tfc_merged_label->setFont(subLabelFont());
gen_tfc_merged_label->setAlignment(Qt::AlignCenter);
//
// Close Button
//
gen_close_button=new QPushButton(this);
gen_close_button->setDefault(true);
gen_close_button->setFont(buttonFont());
gen_close_button->setText(tr("Close"));
connect(gen_close_button,SIGNAL(clicked()),this,SLOT(closeData()));
UpdateControls();
//
// File Scan Timer
//
QTimer *timer=new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(fileScanData()));
timer->start(GENERATE_LOG_FILESCAN_INTERVAL);
if(cmdswitch==1 && cmdservicefit)
{
gen_service_box->setCurrentText(*cmdservice);
createData();
}
if(cmdswitch==2 && cmdservicefit)
{
gen_service_box->setCurrentText(*cmdservice);
musicData();
}
if(cmdswitch==3 && cmdservicefit)
{
gen_service_box->setCurrentText(*cmdservice);
trafficData();
}
}
QSize GenerateLog::sizeHint() const
{
return QSize(240,270);
}
QSizePolicy GenerateLog::sizePolicy() const
{
return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
}
void GenerateLog::serviceActivatedData(int index)
{
UpdateControls();
}
void GenerateLog::dateChangedData(const QDate &date)
{
UpdateControls();
}
void GenerateLog::selectDateData()
{
QDate date=gen_date_edit->date();
QDate current_date=QDate::currentDate();
RDDateDialog *datedialog=
new RDDateDialog(current_date.year(),current_date.year()+1,this);
if(datedialog->exec(&date)<0) {
delete datedialog;
return;
}
gen_date_edit->setDate(date);
delete datedialog;
UpdateControls();
}
void GenerateLog::createData()
{
QString report;
QString unused_report;
unsigned tracks=0;
QString err_msg;
//
// Generate Log
//
RDSvc *svc=
new RDSvc(gen_service_box->currentText(),rda->station(),rda->config(),this);
QString logname=RDDateDecode(svc->nameTemplate(),gen_date_edit->date(),
rda->station(),rda->config(),svc->name());
RDLog *log=new RDLog(logname);
if(log->exists()) {
if(QMessageBox::question(this,"RDLogManager - "+tr("Log Exists"),
tr("The log for")+" "+
rda->shortDateString(gen_date_edit->date())+" "+
tr("already exists. Recreating it")+"\n"+
tr("will remove any merged Music or Traffic events.")+
"\n\n"+tr("Recreate?"),
QMessageBox::Yes,QMessageBox::No)!=
QMessageBox::Yes) {
delete log;
delete svc;
return;
}
if((tracks=log->completedTracks())>0) {
if(QMessageBox::warning(this,"RDLogManager - "+tr("Tracks Exist"),
tr("This will also delete the")+
QString().sprintf(" %u ",tracks)+
tr("voice tracks associated with this log.")+
"\n"+tr("Continue?"),
QMessageBox::Yes,QMessageBox::No)!=
QMessageBox::Yes) {
delete log;
delete svc;
return;
}
}
}
SendNotification(RDNotification::DeleteAction,log->name());
log->removeTracks(rda->station(),rda->user(),rda->config());
//
// Scheduler
//
srand(QTime::currentTime().msec());
connect(svc,SIGNAL(generationProgress(int)),
gen_progress_dialog,SLOT(setValue(int)));
if(!svc->generateLog(gen_date_edit->date(),
RDDateDecode(svc->nameTemplate(),gen_date_edit->date(),
rda->station(),rda->config(),svc->name()),
RDDateDecode(svc->nameTemplate(),gen_date_edit->date().
addDays(1),rda->station(),rda->config(),
svc->name()),
&unused_report,rda->user(),&err_msg)) {
QMessageBox::warning(this,"RDLogManager - "+tr("Error"),
tr("Unable to generate log")+": "+err_msg);
gen_progress_dialog->setValue(gen_progress_dialog->maximum());
delete svc;
delete log;
return;
}
log->updateTracks();
SendNotification(RDNotification::AddAction,log->name());
delete log;
delete svc;
//
// Generate Exception Report
//
RDLogModel *model=new RDLogModel(logname,false,this);
model->load();
if((model->validate(&report,gen_date_edit->date())==0)&&
unused_report.isEmpty()) {
QMessageBox::information(this,tr("No Errors"),\
tr("No broken rules or validation exceptions found."));
}
else {
int errs=unused_report.count("\n");
if(errs==1) {
unused_report+=QString().sprintf("\n%d broken rule.\n",errs);
}
else {
unused_report+=QString().sprintf("\n%d broken rules.\n",errs);
}
RDTextFile(report+"\n"+unused_report);
}
delete model;
UpdateControls();
}
void GenerateLog::musicData()
{
unsigned tracks=0;
QString err_msg;
RDSvc *svc=
new RDSvc(gen_service_box->currentText(),rda->station(),rda->config(),this);
QString logname=RDDateDecode(svc->nameTemplate(),gen_date_edit->date(),
rda->station(),rda->config(),svc->name());
RDLog *log=new RDLog(logname);
if(((log->linkState(RDLog::SourceMusic)==RDLog::LinkDone)||
(log->linkState(RDLog::SourceTraffic)==RDLog::LinkDone))) {
if(log->includeImportMarkers(RDLog::SourceMusic)) {
if(QMessageBox::question(this,"RDLogManager - "+tr("Music Exists"),
tr("The log for")+" "+
rda->shortDateString(gen_date_edit->date())+" "+
tr("already contains merged music and/or traffic data.")+"\n"+
tr("Remerging it will remove this data. Remerge?"),
QMessageBox::Yes,QMessageBox::No)!=
QMessageBox::Yes) {
delete log;
delete svc;
return;
}
if((tracks=log->completedTracks())>0) {
if(QMessageBox::warning(this,"RDLogManager - "+tr("Tracks Exist"),
tr("This will also delete the")+
QString().sprintf(" %u ",tracks)+
tr("voice tracks associated with this log.")+
"\n"+tr("Continue?"),
QMessageBox::Yes,QMessageBox::No)!=
QMessageBox::Yes) {
delete log;
delete svc;
return;
}
}
}
else {
QMessageBox::warning(this,"RDLogManager - "+tr("Error"),
tr("The log for")+" "+
rda->shortDateString(gen_date_edit->date())+" "+
tr("cannot be relinked."));
return;
}
log->removeTracks(rda->station(),rda->user(),rda->config());
if(!svc->clearLogLinks(RDSvc::Traffic,logname,rda->user(),&err_msg)) {
QMessageBox::warning(this,"RDLogManager - "+tr("Error"),
tr("Unable to clear traffic links")+": "+err_msg);
delete log;
delete svc;
return;
}
if(!svc->clearLogLinks(RDSvc::Music,logname,rda->user(),&err_msg)) {
QMessageBox::warning(this,"RDLogManager - "+tr("Error"),
tr("Unable to clear music links")+": "+err_msg);
delete log;
delete svc;
return;
}
}
connect(svc,SIGNAL(generationProgress(int)),
gen_progress_dialog,SLOT(setValue(int)));
QString report;
if(!svc->linkLog(RDSvc::Music,gen_date_edit->date(),logname,&report,
rda->user(),&err_msg)) {
gen_progress_dialog->setValue(gen_progress_dialog->maximum());
RDTextFile(tr("RDLogManager Error Report")+"\n\n"+
tr("Music schedule import failed!")+"\n\n"+err_msg);
delete log;
delete svc;
UpdateControls();
return;
}
SendNotification(RDNotification::ModifyAction,log->name());
delete log;
delete svc;
if(!report.isEmpty()) {
RDTextFile(report);
}
UpdateControls();
}
void GenerateLog::trafficData()
{
QString err_msg;
RDSvc *svc=
new RDSvc(gen_service_box->currentText(),rda->station(),rda->config(),this);
QString logname=RDDateDecode(svc->nameTemplate(),gen_date_edit->date(),
rda->station(),rda->config(),svc->name());
RDLog *log=new RDLog(logname);
if((log->linkState(RDLog::SourceTraffic)==RDLog::LinkDone)) {
if(log->includeImportMarkers(RDLog::SourceTraffic)) {
if(QMessageBox::question(this,"RDLogManager - "+tr("Traffic Exists"),
tr("The log for")+" "+
rda->shortDateString(gen_date_edit->date())+" "+
tr("already contains merged traffic data.")+"\n"+
tr("Remerging it will remove this data. Remerge?"),
QMessageBox::Yes,QMessageBox::No)!=
QMessageBox::Yes) {
delete log;
delete svc;
return;
}
}
else {
QMessageBox::warning(this,"RDLogManager - "+tr("Error"),
tr("The log for")+" "+
rda->shortDateString(gen_date_edit->date())+" "+
tr("cannot be relinked."));
return;
}
if(!svc->clearLogLinks(RDSvc::Traffic,logname,rda->user(),&err_msg)) {
QMessageBox::warning(this,"RDLogManager - "+tr("Error"),
tr("Unable to clear traffic links")+": "+err_msg);
delete log;
delete svc;
return;
}
}
connect(svc,SIGNAL(generationProgress(int)),
gen_progress_dialog,SLOT(setValue(int)));
QString report;
if(!svc->linkLog(RDSvc::Traffic,gen_date_edit->date(),logname,&report,rda->user(),
&err_msg)) {
gen_progress_dialog->setValue(gen_progress_dialog->maximum());
RDTextFile(tr("RDLogManager Error Report")+"\n\n"+
tr("Traffic schedule import failed!")+"\n\n"+err_msg);
delete log;
delete svc;
UpdateControls();
return;
}
SendNotification(RDNotification::ModifyAction,log->name());
delete log;
delete svc;
if(!report.isEmpty()) {
RDTextFile(report);
}
UpdateControls();
}
void GenerateLog::fileScanData()
{
RDSvc *svc=
new RDSvc(gen_service_box->currentText(),rda->station(),rda->config(),this);
QString logname=RDDateDecode(svc->nameTemplate(),gen_date_edit->date(),
rda->station(),rda->config(),svc->name());
RDLog *log=new RDLog(logname);
if(gen_music_enabled) {
if(QFile::exists(svc->
importFilename(RDSvc::Music,gen_date_edit->date()))) {
gen_music_button->
setEnabled(log->includeImportMarkers(RDLog::SourceMusic)||
(log->linkState(RDLog::SourceMusic)==RDLog::LinkMissing));
gen_mus_avail_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::GreenBall));
}
else {
gen_music_button->setDisabled(true);
gen_mus_avail_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::RedBall));
}
}
else {
gen_mus_avail_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
}
if(gen_traffic_enabled) {
if(QFile::exists(svc->
importFilename(RDSvc::Traffic,gen_date_edit->date()))) {
gen_traffic_button->
setEnabled(((!gen_music_enabled)||
(log->linkState(RDLog::SourceMusic)==RDLog::LinkDone))&&
(log->includeImportMarkers(RDLog::SourceTraffic)||
(log->linkState(RDLog::SourceTraffic)==
RDLog::LinkMissing)));
gen_tfc_avail_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::GreenBall));
}
else {
gen_traffic_button->setDisabled(true);
gen_tfc_avail_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::RedBall));
}
}
else {
gen_tfc_avail_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
}
delete log;
delete svc;
}
void GenerateLog::closeData()
{
done(0);
}
void GenerateLog::resizeEvent(QResizeEvent *e)
{
gen_service_box->setGeometry(70,10,sizeHint().width()-80,20);
gen_service_label->setGeometry(10,10,55,20);
gen_date_edit->setGeometry(70,38,100,20);
gen_date_label->setGeometry(10,38,55,20);
gen_select_button->setGeometry(180,33,50,30);
gen_create_button->setGeometry(10,70,sizeHint().width()-20,30);
gen_music_button->setGeometry(10,130,100,30);
gen_traffic_button->setGeometry(10,170,100,30);
gen_import_label->setGeometry(120,105,120,14);
gen_available_label->setGeometry(120,119,60,14);
gen_merged_label->setGeometry(180,119,60,14);
gen_mus_avail_label->setGeometry(120,139,60,14);
gen_mus_merged_label->setGeometry(180,139,60,14);
gen_tfc_avail_label->setGeometry(120,179,60,14);
gen_tfc_merged_label->setGeometry(180,179,60,14);
gen_close_button->
setGeometry(10,sizeHint().height()-60,sizeHint().width()-20,50);
}
void GenerateLog::UpdateControls()
{
RDSvc *svc=
new RDSvc(gen_service_box->currentText(),rda->station(),rda->config(),this);
QString logname=RDDateDecode(svc->nameTemplate(),gen_date_edit->date(),
rda->station(),rda->config(),svc->name());
RDLog *log=new RDLog(logname);
if(log->exists()) {
if(log->linkQuantity(RDLog::SourceMusic)>0) {
gen_music_enabled=true;
if(log->linkState(RDLog::SourceMusic)==RDLog::LinkDone) {
gen_mus_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::GreenBall));
}
else {
gen_mus_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::RedBall));
}
}
else {
gen_music_enabled=false;
gen_music_button->setDisabled(true);
gen_mus_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
}
if(log->linkQuantity(RDLog::SourceTraffic)>0) {
gen_traffic_enabled=true;
if(log->linkState(RDLog::SourceTraffic)==RDLog::LinkDone) {
gen_tfc_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::GreenBall));
}
else {
gen_tfc_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::RedBall));
}
}
else {
gen_traffic_enabled=false;
gen_traffic_button->setDisabled(true);
gen_tfc_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
}
}
else {
gen_music_button->setDisabled(true);
gen_mus_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
gen_traffic_button->setDisabled(true);
gen_tfc_merged_label->
setPixmap(rda->iconEngine()->listIcon(RDIconEngine::WhiteBall));
gen_music_enabled=false;
gen_traffic_enabled=false;
}
delete log;
delete svc;
fileScanData();
}
void GenerateLog::SendNotification(RDNotification::Action action,
const QString &logname)
{
RDNotification *notify=new RDNotification(RDNotification::LogType,
action,QVariant(logname));
rda->ripc()->sendNotification(*notify);
delete notify;
}