diff --git a/ChangeLog b/ChangeLog index ea27bb2b..45035ea0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20957,3 +20957,7 @@ 2021-01-31 Fred Gleason * Refactored the 'SAS Switches' dialog in rdadmin(1) to use the model-based API. +2021-01-31 Fred Gleason + * Added 'RDNodeListModel'. + * Refactored the 'LivewireNode List' dialog in rdadmin(1) to use the + model-based API. diff --git a/lib/Makefile.am b/lib/Makefile.am index e7ff5526..1535d74a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -194,6 +194,7 @@ dist_librd_la_SOURCES = dbversion.h\ rdmonitor_config.cpp rdmonitor_config.h\ rdmp4.cpp rdmp4.h\ rdmulticaster.cpp rdmulticaster.h\ + rdnodelistmodel.cpp rdnodelistmodelh\ rdnotification.cpp rdnotification.h\ rdoneshot.cpp rdoneshot.h\ rdpam.cpp rdpam.h\ @@ -354,6 +355,7 @@ nodist_librd_la_SOURCES = moc_rd3emptycart.cpp\ moc_rdmatrixlistmodel.cpp\ moc_rdmblookup.cpp\ moc_rdmulticaster.cpp\ + moc_rdnodelistmodel.cpp\ moc_rdoneshot.cpp\ moc_rdpanel_button.cpp\ moc_rdpasswd.cpp\ diff --git a/lib/lib.pro b/lib/lib.pro index 199e09e8..b048d6c6 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -143,6 +143,7 @@ SOURCES += rdmatrix.cpp SOURCES += rdmatrixlistmodel.cpp SOURCES += rdmblookup.cpp SOURCES += rdmonitor_config.cpp +SOURCES += rdnodelistmodel.cpp SOURCES += rdnotification.cpp SOURCES += rdoneshot.cpp SOURCES += rdpanel_button.cpp @@ -310,6 +311,7 @@ HEADERS += rdmatrix.h HEADERS += rdmatrixlistmodel.h HEADERS += rdmblookup.h HEADERS += rdmonitor_config.h +HEADERS += rdnodelistmodel.h HEADERS += rdnotification.h HEADERS += rdoneshot.h HEADERS += rdpanel_button.h diff --git a/lib/librd_cs.ts b/lib/librd_cs.ts index 85a9ff92..b8bbf4e5 100644 --- a/lib/librd_cs.ts +++ b/lib/librd_cs.ts @@ -3372,6 +3372,21 @@ Bitte Kofiguration prüfen und erneut versuchen. + + RDNodeListModel + + Hostname + + + + Description + + + + First Output + + + RDPanelButton diff --git a/lib/librd_de.ts b/lib/librd_de.ts index f7a07807..9aff6b40 100644 --- a/lib/librd_de.ts +++ b/lib/librd_de.ts @@ -3353,6 +3353,21 @@ Bitte Kofiguration prüfen und erneut versuchen. + + RDNodeListModel + + Hostname + + + + Description + + + + First Output + + + RDPanelButton diff --git a/lib/librd_es.ts b/lib/librd_es.ts index 89c956ec..e37db3d1 100644 --- a/lib/librd_es.ts +++ b/lib/librd_es.ts @@ -3340,6 +3340,21 @@ Do you still want to proceed? + + RDNodeListModel + + Hostname + + + + Description + + + + First Output + + + RDPanelButton diff --git a/lib/librd_fr.ts b/lib/librd_fr.ts index 595ac2be..782abc7d 100644 --- a/lib/librd_fr.ts +++ b/lib/librd_fr.ts @@ -2776,6 +2776,21 @@ Do you want to overwrite it? + + RDNodeListModel + + Hostname + + + + Description + + + + First Output + + + RDPanelButton diff --git a/lib/librd_nb.ts b/lib/librd_nb.ts index 5c9b2db2..04924632 100644 --- a/lib/librd_nb.ts +++ b/lib/librd_nb.ts @@ -3307,6 +3307,21 @@ Sjekk eksportoppsettet ditt og prøv att. + + RDNodeListModel + + Hostname + + + + Description + + + + First Output + + + RDPanelButton diff --git a/lib/librd_nn.ts b/lib/librd_nn.ts index 5c9b2db2..04924632 100644 --- a/lib/librd_nn.ts +++ b/lib/librd_nn.ts @@ -3307,6 +3307,21 @@ Sjekk eksportoppsettet ditt og prøv att. + + RDNodeListModel + + Hostname + + + + Description + + + + First Output + + + RDPanelButton diff --git a/lib/librd_pt_BR.ts b/lib/librd_pt_BR.ts index 60ca5cfd..a3978843 100644 --- a/lib/librd_pt_BR.ts +++ b/lib/librd_pt_BR.ts @@ -3342,6 +3342,21 @@ Por Favor, cheque suas configurações e tenbte outra vez. + + RDNodeListModel + + Hostname + + + + Description + + + + First Output + + + RDPanelButton diff --git a/lib/rdnodelistmodel.cpp b/lib/rdnodelistmodel.cpp new file mode 100644 index 00000000..31de09c1 --- /dev/null +++ b/lib/rdnodelistmodel.cpp @@ -0,0 +1,285 @@ +// rdnodelistmodel.cpp +// +// Data model for Rivendell PyPAD instances +// +// (C) Copyright 2021 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 "rdapplication.h" +#include "rdescape_string.h" +#include "rdnodelistmodel.h" + +RDNodeListModel::RDNodeListModel(RDMatrix *mtx,QObject *parent) + : QAbstractTableModel(parent) +{ + d_mtx=mtx; + + // + // Column Attributes + // + unsigned left=Qt::AlignLeft|Qt::AlignVCenter; + // unsigned center=Qt::AlignCenter; + unsigned right=Qt::AlignRight|Qt::AlignVCenter; + + d_headers.push_back(tr("Description")); + d_alignments.push_back(left); + + d_headers.push_back(tr("Hostname")); + d_alignments.push_back(left); + + d_headers.push_back(tr("First Output")); + d_alignments.push_back(right); + + updateModel(); +} + + +RDNodeListModel::~RDNodeListModel() +{ +} + + +QPalette RDNodeListModel::palette() +{ + return d_palette; +} + + +void RDNodeListModel::setPalette(const QPalette &pal) +{ + d_palette=pal; +} + + +void RDNodeListModel::setFont(const QFont &font) +{ + d_font=font; + d_bold_font=font; + d_bold_font.setWeight(QFont::Bold); +} + + +int RDNodeListModel::columnCount(const QModelIndex &parent) const +{ + return d_headers.size(); +} + + +int RDNodeListModel::rowCount(const QModelIndex &parent) const +{ + return d_texts.size(); +} + + +QVariant RDNodeListModel::headerData(int section,Qt::Orientation orient, + int role) const +{ + if((orient==Qt::Horizontal)&&(role==Qt::DisplayRole)) { + return d_headers.at(section); + } + return QVariant(); +} + + +QVariant RDNodeListModel::data(const QModelIndex &index,int role) const +{ + QString str; + int col=index.column(); + int row=index.row(); + + if(row list; + for(int i=0;ifirst()) { + updateRow(row.row(),q); + emit dataChanged(createIndex(row.row(),0), + createIndex(row.row(),columnCount())); + } + delete q; + } +} + + +void RDNodeListModel::refresh(int id) +{ + for(int i=0;i texts; + + RDSqlQuery *q=NULL; + QString sql=sqlFields()+ + "where STATION_NAME=\""+RDEscapeString(d_mtx->station())+"\" && "+ + QString().sprintf("MATRIX=%d ",d_mtx->matrix())+ + "order by DESCRIPTION "; + beginResetModel(); + d_texts.clear(); + q=new RDSqlQuery(sql); + while(q->next()) { + d_ids.push_back(0); + d_texts.push_back(texts); + updateRow(d_texts.size()-1,q); + } + delete q; + endResetModel(); +} + + +void RDNodeListModel::updateRowLine(int line) +{ + if(linefirst()) { + updateRow(line,q); + } + delete q; + } +} + + +void RDNodeListModel::updateRow(int row,RDSqlQuery *q) +{ + QList texts; + + // Description + texts.push_back(q->value(1)); + + // Hostname + texts.push_back(q->value(2)); + + // Base Output + texts.push_back(QString().sprintf("%d",q->value(3).toInt())); + + d_ids[row]=q->value(0).toInt(); + d_texts[row]=texts; +} + + +QString RDNodeListModel::sqlFields() const +{ + QString sql=QString("select ")+ + "ID," // 00 + "DESCRIPTION,"+ // 01 + "HOSTNAME,"+ // 02 + "BASE_OUTPUT " // 03 + "from SWITCHER_NODES "; + + return sql; +} diff --git a/lib/rdnodelistmodel.h b/lib/rdnodelistmodel.h new file mode 100644 index 00000000..e7def1ae --- /dev/null +++ b/lib/rdnodelistmodel.h @@ -0,0 +1,74 @@ +// rdnodelistmodel.h +// +// Data model for Rivendell switcher nodes. +// +// (C) Copyright 2021 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 RDNODELISTMODEL_H +#define RDNODELISTMODEL_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class RDNodeListModel : public QAbstractTableModel +{ + Q_OBJECT + public: + RDNodeListModel(RDMatrix *mtx,QObject *parent=0); + ~RDNodeListModel(); + QPalette palette(); + void setPalette(const QPalette &pal); + void setFont(const QFont &font); + int columnCount(const QModelIndex &parent=QModelIndex()) const; + int rowCount(const QModelIndex &parent=QModelIndex()) const; + QVariant headerData(int section,Qt::Orientation orient, + int role=Qt::DisplayRole) const; + QVariant data(const QModelIndex &index,int role=Qt::DisplayRole) const; + int nodeId(const QModelIndex &row) const; + QModelIndex addNode(int id); + void removeNode(const QModelIndex &row); + void removeNode(int id); + void refresh(const QModelIndex &row); + void refresh(int id); + + protected: + void updateModel(); + void updateRowLine(int line); + void updateRow(int row,RDSqlQuery *q); + QString sqlFields() const; + + private: + QPalette d_palette; + QFont d_font; + QFont d_bold_font; + QList d_headers; + QList d_alignments; + QList > d_texts; + QList d_ids; + RDMatrix *d_mtx; +}; + + +#endif // RDNODELISTMODEL_H diff --git a/rdadmin/edit_node.cpp b/rdadmin/edit_node.cpp index 1dfebab9..47dd97dc 100644 --- a/rdadmin/edit_node.cpp +++ b/rdadmin/edit_node.cpp @@ -2,7 +2,7 @@ // // Edit a Rivendell LiveWire Node // -// (C) Copyright 2002-2019 Fred Gleason +// (C) Copyright 2002-2021 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 @@ -51,9 +51,9 @@ EditNode::EditNode(int *id,RDMatrix *matrix,QWidget *parent) // Node Hostname // edit_hostname_edit=new QLineEdit(this); - edit_hostname_edit->setGeometry(90,10,190,20); + edit_hostname_edit->setGeometry(100,10,180,20); QLabel *label=new QLabel(edit_hostname_edit,tr("Hostname: "),this); - label->setGeometry(10,10,80,20); + label->setGeometry(10,10,90,20); label->setFont(labelFont()); label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); @@ -72,9 +72,9 @@ EditNode::EditNode(int *id,RDMatrix *matrix,QWidget *parent) // Node Description // edit_description_edit=new QLineEdit(this); - edit_description_edit->setGeometry(90,32,sizeHint().width()-100,20); + edit_description_edit->setGeometry(100,32,sizeHint().width()-110,20); label=new QLabel(edit_description_edit,tr("Description: "),this); - label->setGeometry(10,32,80,20); + label->setGeometry(10,32,90,20); label->setFont(labelFont()); label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); @@ -82,11 +82,11 @@ EditNode::EditNode(int *id,RDMatrix *matrix,QWidget *parent) // Base Output // edit_output_spin=new QSpinBox(this); - edit_output_spin->setGeometry(90,54,60,20); + edit_output_spin->setGeometry(100,54,60,20); edit_output_spin->setRange(0,0x7FFF); edit_output_spin->setSpecialValueText(tr("None")); label=new QLabel(edit_output_spin,tr("First Output: "),this); - label->setGeometry(10,54,80,20); + label->setGeometry(10,54,90,20); label->setFont(labelFont()); label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); @@ -94,13 +94,13 @@ EditNode::EditNode(int *id,RDMatrix *matrix,QWidget *parent) // Node Password // edit_password_edit=new QLineEdit(this); - edit_password_edit->setGeometry(245,54,90,20); + edit_password_edit->setGeometry(255,54,90,20); edit_password_edit->setEchoMode(QLineEdit::Password); edit_password_edit->setText("********"); connect(edit_password_edit,SIGNAL(textChanged(const QString &)), this,SLOT(passwordChangedData(const QString &))); label=new QLabel(edit_password_edit,tr("Password: "),this); - label->setGeometry(160,54,80,20); + label->setGeometry(170,54,80,20); label->setFont(labelFont()); label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); @@ -246,11 +246,11 @@ void EditNode::okData() delete q; } - done(0); + done(true); } void EditNode::cancelData() { - done(1); + done(false); } diff --git a/rdadmin/list_nodes.cpp b/rdadmin/list_nodes.cpp index 9e6aa0c5..0e72c1ad 100644 --- a/rdadmin/list_nodes.cpp +++ b/rdadmin/list_nodes.cpp @@ -2,7 +2,7 @@ // // List Rivendell Livewire Nodes // -// (C) Copyright 2002-2018 Fred Gleason +// (C) Copyright 2002-2021 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 @@ -18,7 +18,7 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // -#include +#include #include #include @@ -32,8 +32,6 @@ ListNodes::ListNodes(RDMatrix *matrix,QWidget *parent) : RDDialog(parent) { - setModal(true); - list_matrix=matrix; setWindowTitle("RDAdmin - "+tr("Livewire Node List")); @@ -45,21 +43,16 @@ ListNodes::ListNodes(RDMatrix *matrix,QWidget *parent) // // Nodes List Box // - list_list_view=new RDListView(this); - list_list_view->setAllColumnsShowFocus(true); - list_list_view->setItemMargin(5); - list_list_view->addColumn(tr("HOSTNAME")); - list_list_view->setColumnAlignment(0,Qt::AlignLeft); - list_list_view->addColumn(tr("DESCRIPTION")); - list_list_view->setColumnAlignment(1,Qt::AlignLeft); - list_list_view->addColumn(tr("FIRST OUTPUT")); - list_list_view->setColumnAlignment(2,Qt::AlignLeft); - list_list_view->addColumn(tr("TCP PORT")); - list_list_view->setColumnAlignment(3,Qt::AlignCenter); - connect(list_list_view, - SIGNAL(doubleClicked(Q3ListViewItem *,const QPoint &,int)), - this, - SLOT(doubleClickedData(Q3ListViewItem *,const QPoint &,int))); + list_list_view=new RDTableView(this); + list_list_model=new RDNodeListModel(list_matrix,this); + list_list_model->setFont(defaultFont()); + list_list_model->setPalette(palette()); + list_list_view->setModel(list_list_model); + connect(list_list_view,SIGNAL(doubleClicked(const QModelIndex &)), + this,SLOT(doubleClickedData(const QModelIndex &))); + connect(list_list_model,SIGNAL(modelReset()), + list_list_view,SLOT(resizeColumnsToContents())); + list_list_view->resizeColumnsToContents(); // // Add Button @@ -93,11 +86,6 @@ ListNodes::ListNodes(RDMatrix *matrix,QWidget *parent) list_close_button->setFont(buttonFont()); list_close_button->setText(tr("&Close")); connect(list_close_button,SIGNAL(clicked()),this,SLOT(closeData())); - - // - // Load Values - // - RefreshList(); } @@ -115,60 +103,55 @@ QSizePolicy ListNodes::sizePolicy() const void ListNodes::addData() { - RDListViewItem *item; int id=-1; - EditNode *node=new EditNode(&id,list_matrix,this); - if(node->exec()==0) { - item=new RDListViewItem(list_list_view); - item->setId(id); - RefreshItem(item); - list_list_view->setSelected(item,true); - list_list_view->ensureItemVisible(item); + EditNode *d=new EditNode(&id,list_matrix,this); + if(d->exec()) { + QModelIndex row=list_list_model->addNode(id); + if(row.isValid()) { + list_list_view->selectRow(row.row()); + } } - delete node; -} + delete d; + } void ListNodes::editData() { - RDListViewItem *item; + QModelIndexList rows=list_list_view->selectionModel()->selectedRows(); - if((item=(RDListViewItem *)list_list_view->selectedItem())==NULL) { + if(rows.size()!=1) { return; } - int id=item->id(); - EditNode *node=new EditNode(&id,list_matrix,this); - if(node->exec()==0) { - RefreshItem(item); + int id=list_list_model->nodeId(rows.first()); + EditNode *d=new EditNode(&id,list_matrix,this); + if(d->exec()) { + list_list_model->refresh(rows.first()); } - delete node; + delete d; } void ListNodes::deleteData() { - QString sql; - RDSqlQuery *q; - RDListViewItem *item; + QModelIndexList rows=list_list_view->selectionModel()->selectedRows(); - if((item=(RDListViewItem *)list_list_view->selectedItem())==NULL) { + if(rows.size()!=1) { return; } + int id=list_list_model->nodeId(rows.first()); if(QMessageBox::question(this,tr("Delete Node"), tr("Are your sure you want to delete this node?"), - QMessageBox::Yes,QMessageBox::No)== - QMessageBox::No) { + QMessageBox::Yes,QMessageBox::No)!= + QMessageBox::Yes) { return; } - sql=QString().sprintf("delete from SWITCHER_NODES where ID=%d",item->id()); - q=new RDSqlQuery(sql); - delete q; - delete item; + QString sql=QString().sprintf("delete from SWITCHER_NODES where ID=%d",id); + RDSqlQuery::apply(sql); + list_list_model->removeNode(id); } -void ListNodes::doubleClickedData(Q3ListViewItem *item,const QPoint &pt, - int col) +void ListNodes::doubleClickedData(const QModelIndex &index) { editData(); } @@ -192,63 +175,33 @@ void ListNodes::resizeEvent(QResizeEvent *e) } -void ListNodes::RefreshList() +void ListNodes::PurgeEndpoints(const QString &tablename) { QString sql; RDSqlQuery *q; - RDListViewItem *item; - list_list_view->clear(); sql=QString("select ")+ - "ID,"+ - "HOSTNAME,"+ - "DESCRIPTION,"+ - "BASE_OUTPUT,"+ - "TCP_PORT "+ + "HOSTNAME,"+ // 00 + "TCP_PORT "+ // 01 "from SWITCHER_NODES where "+ "(STATION_NAME=\""+RDEscapeString(list_matrix->station())+"\")&&"+ QString().sprintf("(MATRIX=%d)",list_matrix->matrix()); q=new RDSqlQuery(sql); + sql=QString("delete from ")+tablename+" where "+ + "(STATION_NAME=\""+RDEscapeString(list_matrix->station())+"\")&&"+ + QString().sprintf("(MATRIX=%d)&&",list_matrix->matrix()); while(q->next()) { - item=new RDListViewItem(list_list_view); - item->setId(q->value(0).toInt()); - item->setText(0,q->value(1).toString()); - item->setText(1,q->value(2).toString()); - if(q->value(3).toInt()==0) { - item->setText(2,tr("[none]")); - } - else { - item->setText(2,QString().sprintf("%d",q->value(3).toInt())); - } - item->setText(3,q->value(4).toString()); - } - delete q; -} - - -void ListNodes::RefreshItem(RDListViewItem *item) -{ - QString sql; - RDSqlQuery *q; - - sql=QString().sprintf("select HOSTNAME,DESCRIPTION,BASE_OUTPUT,TCP_PORT \ - from SWITCHER_NODES where ID=%d",item->id()); - q=new RDSqlQuery(sql); - if(q->first()) { - item->setText(0,q->value(0).toString()); - item->setText(1,q->value(1).toString()); - if(q->value(2).toInt()==0) { - item->setText(2,tr("[none]")); - } - else { - item->setText(2,QString().sprintf("%d",q->value(2).toInt())); - } - item->setText(3,q->value(3).toString()); + sql+=QString("((NODE_HOSTNAME!=\"")+ + RDEscapeString(q->value(0).toString())+"\")&&"+ + QString().sprintf("(NODE_TCP_PORT!=%d))&&",q->value(1).toInt()); } + sql=sql.left(sql.length()-2); delete q; + RDSqlQuery::apply(sql); } +/* void ListNodes::PurgeEndpoints(const QString &tablename) { QString sql; @@ -267,3 +220,4 @@ void ListNodes::PurgeEndpoints(const QString &tablename) q=new RDSqlQuery(sql); delete q; } +*/ diff --git a/rdadmin/list_nodes.h b/rdadmin/list_nodes.h index cd996122..7aa96bfb 100644 --- a/rdadmin/list_nodes.h +++ b/rdadmin/list_nodes.h @@ -2,7 +2,7 @@ // // List Rivendell LiveWire Nodes // -// (C) Copyright 2002-2019 Fred Gleason +// (C) Copyright 2002-2021 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 @@ -21,13 +21,12 @@ #ifndef LIST_NODES_H #define LIST_NODES_H -#include +#include #include -#include -#include #include -#include +#include +#include class ListNodes : public RDDialog { @@ -41,18 +40,17 @@ class ListNodes : public RDDialog void addData(); void editData(); void deleteData(); - void doubleClickedData(Q3ListViewItem *item,const QPoint &pt,int col); + void doubleClickedData(const QModelIndex &index); void closeData(); protected: void resizeEvent(QResizeEvent *e); private: - void RefreshList(); - void RefreshItem(RDListViewItem *item); void PurgeEndpoints(const QString &tablename); RDMatrix *list_matrix; - RDListView *list_list_view; + RDTableView *list_list_view; + RDNodeListModel *list_list_model; QPushButton *list_add_button; QPushButton *list_edit_button; QPushButton *list_delete_button; @@ -60,5 +58,4 @@ class ListNodes : public RDDialog }; -#endif - +#endif // LIST_NODES_H