From dfa8ed93b268596429de1b806d041749cca0b146 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Fri, 14 Dec 2018 16:17:42 -0500 Subject: [PATCH] 2018-12-13 Fred Gleason * 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). --- ChangeLog | 7 + apis/PyPAD/examples/Makefile.am | 6 + apis/PyPAD/examples/pypad_filewrite.exemplar | 101 +++++++ apis/PyPAD/examples/pypad_udp.exemplar | 105 +++++++ docs/tables/Makefile.am | 1 + docs/tables/pypad_instances.txt | 12 + lib/dbversion.h | 2 +- rdadmin/Makefile.am | 4 + rdadmin/edit_pypad.cpp | 144 ++++++++++ rdadmin/edit_pypad.h | 58 ++++ rdadmin/edit_station.cpp | 22 +- rdadmin/edit_station.h | 2 + rdadmin/list_pypads.cpp | 278 +++++++++++++++++++ rdadmin/list_pypads.h | 61 ++++ rdadmin/rdadmin_cs.ts | 5 + rdadmin/rdadmin_de.ts | 5 + rdadmin/rdadmin_es.ts | 5 + rdadmin/rdadmin_fr.ts | 5 + rdadmin/rdadmin_nb.ts | 5 + rdadmin/rdadmin_nn.ts | 5 + rdadmin/rdadmin_pt_BR.ts | 5 + utils/rddbmgr/revertschema.cpp | 9 + utils/rddbmgr/schemamap.cpp | 2 +- utils/rddbmgr/updateschema.cpp | 18 ++ 24 files changed, 864 insertions(+), 3 deletions(-) create mode 100644 apis/PyPAD/examples/pypad_filewrite.exemplar create mode 100644 apis/PyPAD/examples/pypad_udp.exemplar create mode 100644 docs/tables/pypad_instances.txt create mode 100644 rdadmin/edit_pypad.cpp create mode 100644 rdadmin/edit_pypad.h create mode 100644 rdadmin/list_pypads.cpp create mode 100644 rdadmin/list_pypads.h diff --git a/ChangeLog b/ChangeLog index 72adfdff..0d4fc6d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 + * 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). diff --git a/apis/PyPAD/examples/Makefile.am b/apis/PyPAD/examples/Makefile.am index b983c146..ee741e64 100644 --- a/apis/PyPAD/examples/Makefile.am +++ b/apis/PyPAD/examples/Makefile.am @@ -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 = *~\ diff --git a/apis/PyPAD/examples/pypad_filewrite.exemplar b/apis/PyPAD/examples/pypad_filewrite.exemplar new file mode 100644 index 00000000..5b8ca4bc --- /dev/null +++ b/apis/PyPAD/examples/pypad_filewrite.exemplar @@ -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 diff --git a/apis/PyPAD/examples/pypad_udp.exemplar b/apis/PyPAD/examples/pypad_udp.exemplar new file mode 100644 index 00000000..11c17840 --- /dev/null +++ b/apis/PyPAD/examples/pypad_udp.exemplar @@ -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 diff --git a/docs/tables/Makefile.am b/docs/tables/Makefile.am index 1d94a0da..42c3154b 100644 --- a/docs/tables/Makefile.am +++ b/docs/tables/Makefile.am @@ -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\ diff --git a/docs/tables/pypad_instances.txt b/docs/tables/pypad_instances.txt new file mode 100644 index 00000000..7bc68ea6 --- /dev/null +++ b/docs/tables/pypad_instances.txt @@ -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 diff --git a/lib/dbversion.h b/lib/dbversion.h index 172e654c..1d23dd35 100644 --- a/lib/dbversion.h +++ b/lib/dbversion.h @@ -24,7 +24,7 @@ /* * Current Database Version */ -#define RD_VERSION_DATABASE 302 +#define RD_VERSION_DATABASE 303 #endif // DBVERSION_H diff --git a/rdadmin/Makefile.am b/rdadmin/Makefile.am index 1dfdf72e..ddefb05a 100644 --- a/rdadmin/Makefile.am +++ b/rdadmin/Makefile.am @@ -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\ diff --git a/rdadmin/edit_pypad.cpp b/rdadmin/edit_pypad.cpp new file mode 100644 index 00000000..70e0d60c --- /dev/null +++ b/rdadmin/edit_pypad.cpp @@ -0,0 +1,144 @@ +// edit_pypad.cpp +// +// Edit a PyPAD Instance Configuration +// +// (C) Copyright 2018 Fred Gleason +// +// 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 +#include + +#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); +} diff --git a/rdadmin/edit_pypad.h b/rdadmin/edit_pypad.h new file mode 100644 index 00000000..104503f7 --- /dev/null +++ b/rdadmin/edit_pypad.h @@ -0,0 +1,58 @@ +// edit_pypad.h +// +// Edit a PyPAD Instance Configuration +// +// (C) Copyright 2018 Fred Gleason +// +// 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 +#include +#include +#include +#include + +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 diff --git a/rdadmin/edit_station.cpp b/rdadmin/edit_station.cpp index 8e39054c..c3e99764 100644 --- a/rdadmin/edit_station.cpp +++ b/rdadmin/edit_station.cpp @@ -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-> diff --git a/rdadmin/edit_station.h b/rdadmin/edit_station.h index 546a3dea..6162b775 100644 --- a/rdadmin/edit_station.h +++ b/rdadmin/edit_station.h @@ -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; }; diff --git a/rdadmin/list_pypads.cpp b/rdadmin/list_pypads.cpp new file mode 100644 index 00000000..f264d50d --- /dev/null +++ b/rdadmin/list_pypads.cpp @@ -0,0 +1,278 @@ +// list_pypads.cpp +// +// List PyPAD Instances +// +// (C) Copyright 2018 Fred Gleason +// +// 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#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; +} diff --git a/rdadmin/list_pypads.h b/rdadmin/list_pypads.h new file mode 100644 index 00000000..fb94fa5b --- /dev/null +++ b/rdadmin/list_pypads.h @@ -0,0 +1,61 @@ +// list_pypads.h +// +// List PyPAD Instances +// +// (C) Copyright 2018 Fred Gleason +// +// 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 +#include + +#include +#include +#include + +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 diff --git a/rdadmin/rdadmin_cs.ts b/rdadmin/rdadmin_cs.ts index f3c0d177..5f4e4ab2 100644 --- a/rdadmin/rdadmin_cs.ts +++ b/rdadmin/rdadmin_cs.ts @@ -3820,6 +3820,11 @@ Ports Report Editor + + PyPAD +Instances + + EditSvc diff --git a/rdadmin/rdadmin_de.ts b/rdadmin/rdadmin_de.ts index 9d63d308..b31ffc25 100644 --- a/rdadmin/rdadmin_de.ts +++ b/rdadmin/rdadmin_de.ts @@ -3705,6 +3705,11 @@ Ports Report Editor + + PyPAD +Instances + + EditSvc diff --git a/rdadmin/rdadmin_es.ts b/rdadmin/rdadmin_es.ts index 151df141..409725bb 100644 --- a/rdadmin/rdadmin_es.ts +++ b/rdadmin/rdadmin_es.ts @@ -3829,6 +3829,11 @@ Ports Report Editor + + PyPAD +Instances + + EditSvc diff --git a/rdadmin/rdadmin_fr.ts b/rdadmin/rdadmin_fr.ts index 4b021dbe..11548db2 100644 --- a/rdadmin/rdadmin_fr.ts +++ b/rdadmin/rdadmin_fr.ts @@ -3234,6 +3234,11 @@ Ports Report Editor + + PyPAD +Instances + + EditSvc diff --git a/rdadmin/rdadmin_nb.ts b/rdadmin/rdadmin_nb.ts index bc0dd723..363f2b71 100644 --- a/rdadmin/rdadmin_nb.ts +++ b/rdadmin/rdadmin_nb.ts @@ -3670,6 +3670,11 @@ Ports Report Editor + + PyPAD +Instances + + EditSvc diff --git a/rdadmin/rdadmin_nn.ts b/rdadmin/rdadmin_nn.ts index bc0dd723..363f2b71 100644 --- a/rdadmin/rdadmin_nn.ts +++ b/rdadmin/rdadmin_nn.ts @@ -3670,6 +3670,11 @@ Ports Report Editor + + PyPAD +Instances + + EditSvc diff --git a/rdadmin/rdadmin_pt_BR.ts b/rdadmin/rdadmin_pt_BR.ts index 98505192..7af78b98 100644 --- a/rdadmin/rdadmin_pt_BR.ts +++ b/rdadmin/rdadmin_pt_BR.ts @@ -3693,6 +3693,11 @@ Ports Report Editor + + PyPAD +Instances + + EditSvc diff --git a/utils/rddbmgr/revertschema.cpp b/utils/rddbmgr/revertschema.cpp index 6b9eedc6..36644ca4 100644 --- a/utils/rddbmgr/revertschema.cpp +++ b/utils/rddbmgr/revertschema.cpp @@ -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_schemacur_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...