2018-12-13 Fred Gleason <fredg@paravelsystems.com>

* Added a 'PYPAD_INSTANCES' table to the database.
	* Incremented the database version to 303.
	* Added a 'PyPAD Instances' button to the 'Edit Station' dialog
	in rdadmin(1).
	* Added a 'ListPyPAD Instances' dialog in rdadmin(1).
	* Added an 'Edit PyPAD' Instance' dialog in rdadmin(1).
This commit is contained in:
Fred Gleason 2018-12-14 16:17:42 -05:00
parent d781b694fb
commit dfa8ed93b2
24 changed files with 864 additions and 3 deletions

View File

@ -18190,3 +18190,10 @@
'PyPAD.Update::shouldBeProcessed()' method.
* Updated the 'pypad_udp.py' script to use the
'PyPAD.Update::shouldBeProcessed()' method.
2018-12-13 Fred Gleason <fredg@paravelsystems.com>
* Added a 'PYPAD_INSTANCES' table to the database.
* Incremented the database version to 303.
* Added a 'PyPAD Instances' button to the 'Edit Station' dialog
in rdadmin(1).
* Added a 'ListPyPAD Instances' dialog in rdadmin(1).
* Added an 'Edit PyPAD' Instance' dialog in rdadmin(1).

View File

@ -24,15 +24,21 @@ install-exec-am:
mkdir -p $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD
../../../helpers/install_python.sh now_and_next.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/now_and_next.py
../../../helpers/install_python.sh pypad_filewrite.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_filewrite.py
cp pypad_filewrite.exemplar $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_filewrite.exemplar
../../../helpers/install_python.sh pypad_udp.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_udp.py
cp pypad_udp.exemplar $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_udp.exemplar
uninstall-local:
rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/now_and_next.py
rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_filewrite.exemplar
rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_filewrite.py
rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_udp.exemplar
rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_udp.py
EXTRA_DIST = now_and_next.py\
pypad_filewrite.exemplar\
pypad_filewrite.py\
pypad_udp.exemplar\
pypad_udp.py
CLEANFILES = *~\

View File

@ -0,0 +1,101 @@
; This is the sample configuration for the 'pypad_filewrite.py' PyPAD script
; for Rivendell, which can be used to write one or more files on the local
; system using Now & Next data.
;
; Section Header
;
; One section per file to be written should be configured, starting with
; 'File1' and working up consecutively
[File1]
; Filename
;
; The full path to the file to be written. The filename may contain filepath
; wildcards as defined in Appendix C of the Rivendell Operations and
; Administration Guide. The user running RDAirPlay must have write
; permissions for this location.
Filename=/tmp/rlm_filewrite.txt
; Append Mode
;
; If set to '0', the file will be completely overwritten with the contents
; of each PAD update. If set to '1', each update will be appended to the
; existing contents of the file.
Append=0
; Format String. The string to be output each time RDAirPlay changes
; play state, including any wildcards as placeholders for metadata values.
;
; The list of available wildcards can be found in the 'metadata_wildcards.txt'
; file in the Rivendell documentation directory.
;
FormatString=NOW: %d(ddd MMM d hh:mm:ss yyyy): %t - %a\nNEXT: %D(ddd MMM d hh:mm:ss yyyy): %T - %A\n
; Encoding. Defines the set of escapes to be applied to the PAD fields.
; The following options are available:
;
; 0 - Perform no character escaping.
; 1 - "XML" escaping: Escape reserved characters as per XML-v1.0
; 2 - "Web" escaping: Escape reserved characters as per RFC 2396 Section 2.4
Encoding=0
; Log Selection
;
; Set the status for each log to 'Yes', 'No' or 'Onair' to indicate whether
; state changes on that log should be output. If set to 'Onair', then
; output will be generated only if RDAirPlays OnAir flag is active.
MasterLog=Yes
Aux1Log=Yes
Aux2Log=Yes
VLog101=No
VLog102=No
VLog103=No
VLog104=No
VLog105=No
VLog106=No
VLog107=No
VLog108=No
VLog109=No
VLog110=No
VLog111=No
VLog112=No
VLog113=No
VLog114=No
VLog115=No
VLog116=No
VLog117=No
VLog118=No
VLog119=No
VLog120=No
; Additional files can be written by adding new sections...
;
;[File2]
;Filename=/home/rd/foo2.txt
;Append=1
;FormatString=%t by %a\r\n
;MasterLog=Yes
;Aux1Log=No
;Aux2Log=Onair
;VLog101=No
;VLog102=No
;VLog103=No
;VLog104=No
;VLog105=No
;VLog106=No
;VLog107=No
;VLog108=No
;VLog109=No
;VLog110=No
;VLog111=No
;VLog112=No
;VLog113=No
;VLog114=No
;VLog115=No
;VLog116=No
;VLog117=No
;VLog118=No
;VLog119=No
;VLog120=No

View File

@ -0,0 +1,105 @@
; This is the sample configuration for the 'pypad_udp.py' PyPAD script for
; Rivendell, which can be used to output Now & Next data to one or more
; remote UDP ports.
; Section Header
;
; One section per remote UDP port is configured, starting with 'Udp1' and
; working up consecutively
[Udp1]
; IP Address
;
; The IP address of the remote UDP port, in dotted-quad notation.
IpAddress=127.0.0.1
; UDP Port
;
; The UDP port number of the remote UDP port, in the range 0 - 65,535.
UdpPort=1234
; Format String. The string to be output each time RDAirPlay changes
; play state, including any wildcards as placeholders for metadata values.
;
; The list of available wildcards can be found in the 'metadata_wildcards.txt'
; file in the Rivendell documentation directory.
;
FormatString=NOW: %d(ddd MMM d hh:mm:ss yyyy): %t - %a\nNEXT: %D(ddd MMM d hh:mm:ss yyyy): %T - %A\n
; Encoding. Defines the set of escapes to be applied to the PAD fields.
; The following options are available:
;
; 0 - Perform no character escaping.
; 1 - "XML" escaping: Escape reserved characters as per XML-v1.0
; 2 - "Web" escaping: Escape reserved characters as per RFC 2396 Section 2.4
Encoding=0
; Null Update Handling. Defines how 'null' updates --i.e. those with a cart
; number of '0' -- should be handled.
;
; 0 - Process all updates regardless of cart values.
; 1 - Process update only if the 'now' cart is not null.
; 2 - Process update only if the 'next' cart is not null.
; 3 - Process update only if both the 'now' and 'next' carts are not null.
ProcessNullUpdates=0
; Log Selection
;
; Set the status for each log to 'Yes', 'No' or 'Onair' to indicate whether
; state changes on that log should be output on this udp port. If set
; to 'Onair', then output will be generated only if RDAirPlays OnAir flag
; is active.
MasterLog=Yes
Aux1Log=Yes
Aux2Log=Yes
VLog101=No
VLog102=No
VLog103=No
VLog104=No
VLog105=No
VLog106=No
VLog107=No
VLog108=No
VLog109=No
VLog110=No
VLog111=No
VLog112=No
VLog113=No
VLog114=No
VLog115=No
VLog116=No
VLog117=No
VLog118=No
VLog119=No
VLog120=No
; Additional UDP destinations can be configured by adding new sections...
;[Udp2]
;FormatString=Artist: %a%r
;IpAddress=192.168.10.22
;UdpPort=6789
;ProcessNullUpdates=0
;MasterLog=Yes
;Aux1Log=No
;Aux2Log=Onair
;VLog101=No
;VLog102=No
;VLog103=No
;VLog104=No
;VLog105=No
;VLog106=No
;VLog107=No
;VLog108=No
;VLog109=No
;VLog110=No
;VLog111=No
;VLog112=No
;VLog113=No
;VLog114=No
;VLog115=No
;VLog116=No
;VLog117=No
;VLog118=No
;VLog119=No
;VLog120=No

View File

@ -73,6 +73,7 @@ EXTRA_DIST = audio_cards.txt\
panels.txt\
panel_names.txt\
podcasts.txt\
pypad_instances.txt\
rdairplay_channels.txt\
rd_airplay.txt\
rd_catch.txt\

View File

@ -0,0 +1,12 @@
PYPAD_INSTANCES Table Layout for Rivendell
The PYPAD_INSTANCES table holds information about PyPAD script instances
being managed by rdpadengined(8).
FIELD NAME TYPE REMARKS
------------------------------------------------------------------------------
ID int(10) unsigned * Primary key, Auto Increment
STATION_NAME varchar(64) From STATIONS.NAME
SCRIPT_PATH varchar(191)
DESCRIPTION varchar(191)
CONFIG text

View File

@ -24,7 +24,7 @@
/*
* Current Database Version
*/
#define RD_VERSION_DATABASE 302
#define RD_VERSION_DATABASE 303
#endif // DBVERSION_H

View File

@ -73,6 +73,7 @@ dist_rdadmin_SOURCES = add_feed.cpp add_feed.h\
edit_node.cpp edit_node.h\
edit_now_next.cpp edit_now_next.h\
edit_nownextplugin.cpp edit_nownextplugin.h\
edit_pypad.cpp edit_pypad.h\
edit_rdairplay.cpp edit_rdairplay.h\
edit_rdlibrary.cpp edit_rdlibrary.h\
edit_rdlogedit.cpp edit_rdlogedit.h\
@ -103,6 +104,7 @@ dist_rdadmin_SOURCES = add_feed.cpp add_feed.h\
list_livewiregpios.cpp list_livewiregpios.h\
list_matrices.cpp list_matrices.h\
list_nodes.cpp list_nodes.h\
list_pypads.cpp list_pypads.h\
list_replicator_carts.cpp list_replicator_carts.h\
list_replicators.cpp list_replicators.h\
list_reports.cpp list_reports.h\
@ -149,6 +151,7 @@ nodist_rdadmin_SOURCES = moc_add_feed.cpp\
moc_edit_node.cpp\
moc_edit_now_next.cpp\
moc_edit_nownextplugin.cpp\
moc_edit_pypad.cpp\
moc_edit_rdairplay.cpp\
moc_edit_rdlibrary.cpp\
moc_edit_rdlogedit.cpp\
@ -178,6 +181,7 @@ nodist_rdadmin_SOURCES = moc_add_feed.cpp\
moc_list_livewiregpios.cpp\
moc_list_matrices.cpp\
moc_list_nodes.cpp\
moc_list_pypads.cpp\
moc_list_replicator_carts.cpp\
moc_list_replicators.cpp\
moc_list_reports.cpp\

144
rdadmin/edit_pypad.cpp Normal file
View File

@ -0,0 +1,144 @@
// edit_pypad.cpp
//
// Edit a PyPAD Instance Configuration
//
// (C) Copyright 2018 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 <rdapplication.h>
#include <rdescape_string.h>
#include "edit_pypad.h"
EditPypad::EditPypad(int id,QWidget *parent)
: QDialog(parent)
{
edit_id=id;
setWindowTitle(tr("Edit ByPAD Instance")+
" ["+tr("ID")+QString().sprintf(": %u]",id));
//
// Fonts
//
QFont label_font(font().family(),font().pointSize(),QFont::Bold);
//
// Script Path
//
edit_script_path_label=new QLabel(tr("Script Path")+":",this);
edit_script_path_label->setFont(label_font);
edit_script_path_label->setAlignment(Qt::AlignVCenter|Qt::AlignRight);
edit_script_path_edit=new QLineEdit(this);
edit_script_path_edit->setReadOnly(true);
//
// Description
//
edit_description_label=new QLabel(tr("Description")+":",this);
edit_description_label->setFont(label_font);
edit_description_label->setAlignment(Qt::AlignVCenter|Qt::AlignRight);
edit_description_edit=new QLineEdit(this);
//
// Configuration
//
edit_config_label=new QLabel(tr("Configuration"),this);
edit_config_label->setFont(label_font);
edit_config_label->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);
edit_config_text=new QTextEdit(this);
edit_config_text->setAcceptRichText(false);
edit_config_text->setWordWrapMode(QTextOption::WrapAnywhere);
//
// OK Button
//
edit_ok_button=new QPushButton(tr("OK"),this);
edit_ok_button->setFont(label_font);
connect(edit_ok_button,SIGNAL(clicked()),this,SLOT(okData()));
//
// Cancel Button
//
edit_cancel_button=new QPushButton(tr("Cancel"),this);
edit_cancel_button->setFont(label_font);
connect(edit_cancel_button,SIGNAL(clicked()),this,SLOT(cancelData()));
//
// Load Values
//
QString sql=QString("select ")+
"SCRIPT_PATH,"+ // 00
"DESCRIPTION,"+ // 01
"CONFIG "+ // 02
"from PYPAD_INSTANCES where "+
QString().sprintf("ID=%u",edit_id);
RDSqlQuery *q=new RDSqlQuery(sql);
if(q->first()) {
edit_script_path_edit->setText(q->value(0).toString());
edit_description_edit->setText(q->value(1).toString());
edit_config_text->insertPlainText(q->value(2).toString());
edit_config_text->moveCursor(QTextCursor::Start);
}
delete q;
}
QSize EditPypad::sizeHint() const
{
return QSize(600,800);
}
QSizePolicy EditPypad::sizePolicy() const
{
return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
}
void EditPypad::okData()
{
QString sql=QString("update PYPAD_INSTANCES set ")+
"DESCRIPTION=\""+RDEscapeString(edit_description_edit->text())+"\","+
"CONFIG=\""+RDEscapeString(edit_config_text->toPlainText())+"\" where "+
QString().sprintf("ID=%u",edit_id);
RDSqlQuery::apply(sql);
done(true);
}
void EditPypad::cancelData()
{
done(false);
}
void EditPypad::resizeEvent(QResizeEvent *e)
{
edit_script_path_label->setGeometry(10,10,100,20);
edit_script_path_edit->setGeometry(115,10,size().width()-135,20);
edit_description_label->setGeometry(10,32,100,20);
edit_description_edit->setGeometry(115,32,size().width()-135,20);
edit_config_label->setGeometry(10,54,150,20);
edit_config_text->setGeometry(10,76,size().width()-20,size().height()-146);
edit_ok_button->setGeometry(size().width()-180,size().height()-60,80,50);
edit_cancel_button->setGeometry(size().width()-90,size().height()-60,80,50);
}

58
rdadmin/edit_pypad.h Normal file
View File

@ -0,0 +1,58 @@
// edit_pypad.h
//
// Edit a PyPAD Instance Configuration
//
// (C) Copyright 2018 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.
//
#ifndef EDIT_PYPAD_H
#define EDIT_PYPAD_H
#include <qdialog.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qtextedit.h>
class EditPypad : public QDialog
{
Q_OBJECT
public:
EditPypad(int id,QWidget *parent=0);
QSize sizeHint() const;
QSizePolicy sizePolicy() const;
private slots:
void okData();
void cancelData();
protected:
void resizeEvent(QResizeEvent *e);
private:
QLabel *edit_script_path_label;
QLineEdit *edit_script_path_edit;
QLabel *edit_description_label;
QLineEdit *edit_description_edit;
QLabel *edit_config_label;
QTextEdit *edit_config_text;
QPushButton *edit_ok_button;
QPushButton *edit_cancel_button;
int edit_id;
};
#endif // EDIT_PYPAD_H

View File

@ -45,6 +45,7 @@
#include "list_hostvars.h"
#include "edit_jack.h"
#include "list_matrices.h"
#include "list_pypads.h"
#include "edit_rdairplay.h"
#include "edit_rdlibrary.h"
@ -441,6 +442,15 @@ EditStation::EditStation(QString sname,QWidget *parent)
station_jack_button->setText(tr("JACK\nSettings"));
connect(station_jack_button,SIGNAL(clicked()),this,SLOT(jackSettingsData()));
//
// PyPAD Instances Button
//
station_pypad_button=new QPushButton(this);
station_pypad_button->setFont(font);
station_pypad_button->setText(tr("PyPAD\nInstances"));
connect(station_pypad_button,SIGNAL(clicked()),
this,SLOT(pypadInstancesData()));
//
// Ok Button
//
@ -858,6 +868,14 @@ void EditStation::jackSettingsData()
}
void EditStation::pypadInstancesData()
{
ListPypads *d=new ListPypads(station_station,this);
d->exec();
delete d;
}
void EditStation::startCartClickedData()
{
int cartnum=station_start_cart_edit->text().toUInt();
@ -976,7 +994,9 @@ void EditStation::resizeEvent(QResizeEvent *e)
station_adapters_button->setGeometry(290,554,80,50);
station_jack_button->setGeometry(155,614,80,50);
station_jack_button->setGeometry(110,614,80,50);
station_pypad_button->setGeometry(200,614,80,50);
station_ok_button->setGeometry(size().width()-180,size().height()-60,80,50);
station_cancel_button->

View File

@ -68,6 +68,7 @@ class EditStation : public QDialog
void editHostvarsData();
void editDropboxesData();
void jackSettingsData();
void pypadInstancesData();
void startCartClickedData();
void stopCartClickedData();
@ -143,6 +144,7 @@ class EditStation : public QDialog
QPushButton *station_ttys_button;
QPushButton *station_adapters_button;
QPushButton *station_jack_button;
QPushButton *station_pypad_button;
QPushButton *station_ok_button;
QPushButton *station_cancel_button;
};

278
rdadmin/list_pypads.cpp Normal file
View File

@ -0,0 +1,278 @@
// list_pypads.cpp
//
// List PyPAD Instances
//
// (C) Copyright 2018 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 <qfile.h>
#include <qfiledialog.h>
#include <qmessagebox.h>
#include <qstringlist.h>
#include <rd.h>
#include <rdapplication.h>
#include <rddb.h>
#include <rdescape_string.h>
#include <rdpasswd.h>
#include "list_pypads.h"
#include "edit_pypad.h"
ListPypads::ListPypads(RDStation *station,QWidget *parent)
: QDialog(parent)
{
list_station=station;
setModal(true);
setWindowTitle("RDAdmin - "+tr("PyPAD Instances on")+" "+
rda->station()->name());
//
// Fix the Window Size
//
setMinimumWidth(sizeHint().width());
setMinimumHeight(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);
//
// Instances List Box
//
list_list_view=new RDListView(this);
list_list_view->setAllColumnsShowFocus(true);
list_list_view->setItemMargin(5);
list_list_view->addColumn(tr("Id"));
list_list_view->setColumnAlignment(0,Qt::AlignRight);
list_list_view->addColumn(tr("Description"));
list_list_view->setColumnAlignment(1,Qt::AlignLeft);
list_list_view->addColumn(tr("Script Path"));
list_list_view->setColumnAlignment(2,Qt::AlignLeft);
connect(list_list_view,
SIGNAL(doubleClicked(Q3ListViewItem *,const QPoint &,int)),
this,
SLOT(doubleClickedData(Q3ListViewItem *,const QPoint &,int)));
//
// Add Button
//
list_add_button=new QPushButton(this);
list_add_button->setFont(bold_font);
list_add_button->setText(tr("&Add"));
connect(list_add_button,SIGNAL(clicked()),this,SLOT(addData()));
//
// Edit Button
//
list_edit_button=new QPushButton(this);
list_edit_button->setFont(bold_font);
list_edit_button->setText(tr("&Edit"));
connect(list_edit_button,SIGNAL(clicked()),this,SLOT(editData()));
//
// Delete Button
//
list_delete_button=new QPushButton(this);
list_delete_button->setFont(bold_font);
list_delete_button->setText(tr("&Delete"));
connect(list_delete_button,SIGNAL(clicked()),this,SLOT(deleteData()));
//
// Close Button
//
list_close_button=new QPushButton(this);
list_close_button->setDefault(true);
list_close_button->setFont(bold_font);
list_close_button->setText(tr("&Close"));
connect(list_close_button,SIGNAL(clicked()),this,SLOT(closeData()));
//
// Load Values
//
RefreshList();
}
QSize ListPypads::sizeHint() const
{
return QSize(400,250);
}
QSizePolicy ListPypads::sizePolicy() const
{
return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
}
void ListPypads::addData()
{
//
// Get Script Name
//
QString script=
QFileDialog::getOpenFileName(this,tr("Select PyPAD Script"),
"/usr/lib64/rivendell/PyPAD",
"Python Scripts (*.py)");
if(script.isNull()) {
return;
}
//
// Get Exemplar
//
QString exemplar="";
QStringList f0=script.split(".");
f0.last()="exemplar";
QFile *file=new QFile(f0.join("."));
if(file->open(QIODevice::ReadOnly)) {
exemplar=file->readAll();
file->close();
}
delete file;
QString sql=QString("insert into PYPAD_INSTANCES set ")+
"STATION_NAME=\""+RDEscapeString(list_station->name())+"\","+
"SCRIPT_PATH=\""+RDEscapeString(script)+"\","+
"DESCRIPTION=\""+
RDEscapeString("new "+script.split("/").last()+" instance")+"\","+
"CONFIG=\""+RDEscapeString(exemplar)+"\"";
int id=RDSqlQuery::run(sql).toInt();
EditPypad *d=new EditPypad(id,this);
if(d->exec()) {
RDListViewItem *item=new RDListViewItem(list_list_view);
item->setId(id);
RefreshItem(item);
list_list_view->ensureItemVisible(item);
item->setSelected(true);
}
else {
sql=QString("delete from PYPAD_INSTANCES where ")+
QString().sprintf("ID=%u",id);
RDSqlQuery::apply(sql);
}
delete d;
}
void ListPypads::editData()
{
RDListViewItem *item;
if((item=(RDListViewItem *)list_list_view->selectedItem())==NULL) {
return;
}
EditPypad *d=new EditPypad(item->id(),this);
if(d->exec()) {
RefreshItem(item);
}
delete d;
}
void ListPypads::deleteData()
{
QString sql;
RDListViewItem *item;
if((item=(RDListViewItem *)list_list_view->selectedItem())==NULL) {
return;
}
if(QMessageBox::question(this,tr("Delete Instance"),
tr("Are your sure you want to delete this instance?"),
QMessageBox::Yes,QMessageBox::No)==
QMessageBox::No) {
return;
}
sql=QString("delete from PYPAD_INSTANCES where ")+
QString().sprintf("ID=%d",item->id());
RDSqlQuery::apply(sql);
delete item;
}
void ListPypads::doubleClickedData(Q3ListViewItem *item,const QPoint &pt,
int col)
{
editData();
}
void ListPypads::closeData()
{
done(0);
}
void ListPypads::resizeEvent(QResizeEvent *e)
{
list_list_view->setGeometry(10,10,size().width()-20,size().height()-80);
list_add_button->setGeometry(10,size().height()-60,80,50);
list_edit_button->setGeometry(100,size().height()-60,80,50);
list_delete_button->setGeometry(190,size().height()-60,80,50);
list_close_button->setGeometry(size().width()-90,size().height()-60,80,50);
}
void ListPypads::RefreshList()
{
QString sql;
RDSqlQuery *q;
RDListViewItem *item;
list_list_view->clear();
sql=QString("select ")+
"ID,"+ // 00
"DESCRIPTION,"+ // 01
"SCRIPT_PATH "+ // 02
"from PYPAD_INSTANCES where "+
"STATION_NAME=\""+RDEscapeString(list_station->name())+"\"";
q=new RDSqlQuery(sql);
while(q->next()) {
item=new RDListViewItem(list_list_view);
item->setId(q->value(0).toInt());
item->setText(0,QString().sprintf("%u",q->value(0).toUInt()));
item->setText(1,q->value(1).toString());
item->setText(2,q->value(2).toString());
}
delete q;
}
void ListPypads::RefreshItem(RDListViewItem *item)
{
QString sql;
RDSqlQuery *q;
sql=QString("select DESCRIPTION,SCRIPT_PATH from PYPAD_INSTANCES where ")+
QString().sprintf("ID=%u",item->id());
q=new RDSqlQuery(sql);
if(q->first()) {
item->setText(0,QString().sprintf("%u",item->id()));
item->setText(1,q->value(0).toString());
item->setText(2,q->value(1).toString());
}
delete q;
}

61
rdadmin/list_pypads.h Normal file
View File

@ -0,0 +1,61 @@
// list_pypads.h
//
// List PyPAD Instances
//
// (C) Copyright 2018 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.
//
#ifndef LIST_PYPADS_H
#define LIST_PYPADS_H
#include <qdialog.h>
#include <qpushbutton.h>
#include <rdlistview.h>
#include <rdlistviewitem.h>
#include <rdstation.h>
class ListPypads : public QDialog
{
Q_OBJECT
public:
ListPypads(RDStation *station,QWidget *parent=0);
QSize sizeHint() const;
QSizePolicy sizePolicy() const;
private slots:
void addData();
void editData();
void deleteData();
void doubleClickedData(Q3ListViewItem *item,const QPoint &pt,int col);
void closeData();
protected:
void resizeEvent(QResizeEvent *e);
private:
void RefreshList();
void RefreshItem(RDListViewItem *item);
RDListView *list_list_view;
QPushButton *list_add_button;
QPushButton *list_edit_button;
QPushButton *list_delete_button;
QPushButton *list_close_button;
RDStation *list_station;
};
#endif // LIST_PYPADS_H

View File

@ -3820,6 +3820,11 @@ Ports</source>
<source>Report Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PyPAD
Instances</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditSvc</name>

View File

@ -3705,6 +3705,11 @@ Ports</source>
<source>Report Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PyPAD
Instances</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditSvc</name>

View File

@ -3829,6 +3829,11 @@ Ports</source>
<source>Report Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PyPAD
Instances</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditSvc</name>

View File

@ -3234,6 +3234,11 @@ Ports</source>
<source>Report Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PyPAD
Instances</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditSvc</name>

View File

@ -3670,6 +3670,11 @@ Ports</source>
<source>Report Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PyPAD
Instances</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditSvc</name>

View File

@ -3670,6 +3670,11 @@ Ports</source>
<source>Report Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PyPAD
Instances</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditSvc</name>

View File

@ -3693,6 +3693,11 @@ Ports</source>
<source>Report Editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>PyPAD
Instances</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditSvc</name>

View File

@ -40,6 +40,15 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg)
// NEW SCHEMA REVERSIONS GO HERE...
//
// Revert 303
//
if((cur_schema==303)&&(set_schema<cur_schema)) {
DropTable("PYPAD_INSTANCES",err_msg);
WriteSchemaVersion(--cur_schema);
}
//
// Revert 302
//

View File

@ -140,7 +140,7 @@ void MainObject::InitializeSchemaMap() {
global_version_map["2.17"]=268;
global_version_map["2.18"]=272;
global_version_map["2.19"]=275;
global_version_map["3.0"]=302;
global_version_map["3.0"]=303;
}

View File

@ -9624,6 +9624,24 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg)
WriteSchemaVersion(++cur_schema);
}
if((cur_schema<303)&&(set_schema>cur_schema)) {
sql=QString("create table if not exists PYPAD_INSTANCES (")+
"ID int auto_increment not null primary key,"+
"STATION_NAME varchar(64) not null,"+
"SCRIPT_PATH varchar(191) not null,"+
"DESCRIPTION varchar(191) default '[new]',"+
"CONFIG text not null,"+
"index STATION_NAME_IDX(STATION_NAME))"+
" charset utf8mb4 collate utf8mb4_general_ci"+
db_table_create_postfix;
if(!RDSqlQuery::apply(sql,err_msg)) {
return false;
}
WriteSchemaVersion(++cur_schema);
}
// NEW SCHEMA UPDATES GO HERE...