From 8f11c87b75ece5d2909e2434b0d07536dd83a600 Mon Sep 17 00:00:00 2001 From: Dirk H Bartley Date: Mon, 11 Feb 2008 03:13:02 +0000 Subject: [PATCH] Changes to add a status dir page. Still need to add some context sensitive commands. Should add a pref for how often to re-populate the tables. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6400 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/qt-console/bat.pro.in | 5 + bacula/src/qt-console/console/console.h | 1 + bacula/src/qt-console/main.ui | 18 +- bacula/src/qt-console/mainwin.cpp | 38 ++- bacula/src/qt-console/mainwin.h | 4 + bacula/src/qt-console/pages.h | 1 + bacula/src/qt-console/prefs.ui | 106 ++++++-- bacula/src/qt-console/status/dirstat.cpp | 318 +++++++++++++++++++++++ bacula/src/qt-console/status/dirstat.h | 73 ++++++ bacula/src/qt-console/status/dirstat.ui | 183 +++++++++++++ 10 files changed, 715 insertions(+), 32 deletions(-) create mode 100644 bacula/src/qt-console/status/dirstat.cpp create mode 100644 bacula/src/qt-console/status/dirstat.h create mode 100644 bacula/src/qt-console/status/dirstat.ui diff --git a/bacula/src/qt-console/bat.pro.in b/bacula/src/qt-console/bat.pro.in index acb80cf356..801169a288 100644 --- a/bacula/src/qt-console/bat.pro.in +++ b/bacula/src/qt-console/bat.pro.in @@ -43,6 +43,7 @@ FORMS += clients/clients.ui storage/storage.ui fileset/fileset.ui FORMS += joblog/joblog.ui jobs/jobs.ui FORMS += help/help.ui FORMS += jobgraphs/jobplotcontrols.ui +FORMS += status/dirstat.ui # Main directory HEADERS += mainwin.h bat.h bat_conf.h qstd.h pages.h @@ -124,6 +125,10 @@ SOURCES += jobgraphs/jobplot.cpp HEADERS += help/help.h SOURCES += help/help.cpp +## Status Dir +HEADERS += status/dirstat.h +SOURCES += status/dirstat.cpp + INSTALLS += bins INSTALLS += confs diff --git a/bacula/src/qt-console/console/console.h b/bacula/src/qt-console/console/console.h index 9c7ca74680..a2107dac04 100644 --- a/bacula/src/qt-console/console/console.h +++ b/bacula/src/qt-console/console/console.h @@ -83,6 +83,7 @@ public: bool authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons, char *buf, int buflen); bool is_connected() { return m_sock != NULL; }; + bool is_ready() { return is_connected() && m_at_prompt && m_at_main_prompt; }; bool is_connectedGui(); bool preventInUseConnect(); const QFont get_font(); diff --git a/bacula/src/qt-console/main.ui b/bacula/src/qt-console/main.ui index 9688b8ba25..8a127bf610 100644 --- a/bacula/src/qt-console/main.ui +++ b/bacula/src/qt-console/main.ui @@ -71,7 +71,7 @@ 0 0 882 - 26 + 28 @@ -135,6 +135,7 @@ + @@ -464,10 +465,10 @@ Status Dir - Query status of director + Query status of director in console - Query status of director + Query status of director in console true @@ -575,6 +576,17 @@ Plot Job Files and Bytes + + + images/joblog.svg + + + Status Dir Page + + + Director Status Page + + diff --git a/bacula/src/qt-console/mainwin.cpp b/bacula/src/qt-console/mainwin.cpp index 7add181b43..c81f286e50 100644 --- a/bacula/src/qt-console/mainwin.cpp +++ b/bacula/src/qt-console/mainwin.cpp @@ -50,6 +50,7 @@ #include "help/help.h" #include "jobs/jobs.h" #include "jobgraphs/jobplot.h" +#include "status/dirstat.h" /* * Daemon message callback @@ -145,10 +146,14 @@ void MainWin::createPages() createPageJobList("", "", "", "", NULL); JobPlotPass pass; pass.use = false; - new JobPlot(NULL, pass); + if (m_openPlot) + new JobPlot(NULL, pass); new MediaList(); new Storage(); - new restoreTree(); + if (m_openBrowser) + new restoreTree(); + if (m_openDirStat) + new DirStat(); treeWidget->expandItem(topItem); stackedWidget->setCurrentWidget(m_currentConsole); @@ -232,6 +237,7 @@ void MainWin::createConnections() connect(actionRun, SIGNAL(triggered()), this, SLOT(runButtonClicked())); connect(actionEstimate, SIGNAL(triggered()), this, SLOT(estimateButtonClicked())); connect(actionBrowse, SIGNAL(triggered()), this, SLOT(browseButtonClicked())); + connect(actionStatusDirPage, SIGNAL(triggered()), this, SLOT(statusPageButtonClicked())); connect(actionJobPlot, SIGNAL(triggered()), this, SLOT(jobPlotButtonClicked())); connect(actionRestore, SIGNAL(triggered()), this, SLOT(restoreButtonClicked())); connect(actionUndock, SIGNAL(triggered()), this, SLOT(undockWindowButton())); @@ -429,6 +435,22 @@ void MainWin::browseButtonClicked() new restoreTree(); } +void MainWin::statusPageButtonClicked() +{ + /* if one exists, then just set it current */ + bool found = false; + foreach(Pages *page, m_pagehash) { + if (m_currentConsole == page->console()) { + if (page->name() == "Director Status") { + found = true; + page->setCurrent(); + } + } + } + if (!found) + new DirStat(); +} + void MainWin::restoreButtonClicked() { new prerestorePage(); @@ -640,6 +662,9 @@ void MainWin::setPreferences() m_radioConvert = 2; prefs.radioConvertStandard->setChecked(Qt::Checked); } + prefs.openPlotCheckBox->setCheckState(m_openPlot ? Qt::Checked : Qt::Unchecked); + prefs.openBrowserCheckBox->setCheckState(m_openBrowser ? Qt::Checked : Qt::Unchecked); + prefs.openDirStatCheckBox->setCheckState(m_openDirStat ? Qt::Checked : Qt::Unchecked); prefs.exec(); } @@ -684,6 +709,9 @@ void prefsDialog::accept() } else { mainWin->m_radioConvert = 2; } + mainWin->m_openPlot = this->openPlotCheckBox->checkState() == Qt::Checked; + mainWin->m_openBrowser = this->openBrowserCheckBox->checkState() == Qt::Checked; + mainWin->m_openDirStat = this->openDirStatCheckBox->checkState() == Qt::Checked; QSettings settings("www.bacula.org", "bat"); settings.beginGroup("Debug"); @@ -706,6 +734,9 @@ void prefsDialog::accept() settings.beginGroup("Misc"); settings.setValue("longList", mainWin->m_longList); settings.setValue("byteConvert", mainWin->m_radioConvert); + settings.setValue("openplot", mainWin->m_openPlot); + settings.setValue("openbrowser", mainWin->m_openBrowser); + settings.setValue("opendirstat", mainWin->m_openDirStat); settings.endGroup(); settings.beginGroup("RestoreTree"); settings.setValue("rtPopDirDebug", mainWin->m_rtPopDirDebug); @@ -756,6 +787,9 @@ void MainWin::readPreferences() settings.beginGroup("Misc"); m_longList = settings.value("longList", false).toBool(); m_radioConvert = settings.value("byteConvert", false).toInt(); + m_openPlot = settings.value("openplot", false).toBool(); + m_openBrowser = settings.value("openbrowser", false).toBool(); + m_openDirStat = settings.value("opendirstat", false).toBool(); settings.endGroup(); settings.beginGroup("RestoreTree"); m_rtPopDirDebug = settings.value("rtPopDirDebug", false).toBool(); diff --git a/bacula/src/qt-console/mainwin.h b/bacula/src/qt-console/mainwin.h index 84fc76b5f4..2959afa15f 100644 --- a/bacula/src/qt-console/mainwin.h +++ b/bacula/src/qt-console/mainwin.h @@ -99,6 +99,9 @@ public: bool m_rtRestore2Debug; bool m_rtRestore3Debug; int m_radioConvert; + bool m_openBrowser; + bool m_openPlot; + bool m_openDirStat; public slots: void input_line(); @@ -109,6 +112,7 @@ public slots: void runButtonClicked(); void estimateButtonClicked(); void browseButtonClicked(); + void statusPageButtonClicked(); void jobPlotButtonClicked(); void restoreButtonClicked(); void undockWindowButton(); diff --git a/bacula/src/qt-console/pages.h b/bacula/src/qt-console/pages.h index 49d7ca7494..f472c0383d 100644 --- a/bacula/src/qt-console/pages.h +++ b/bacula/src/qt-console/pages.h @@ -71,6 +71,7 @@ public: void setTreeWidgetItemDockColor(); void consoleCommand(QString &); void consoleInput(QString &); + QString &name() { return m_name; }; public slots: /* closeEvent is a virtual function inherited from QWidget */ diff --git a/bacula/src/qt-console/prefs.ui b/bacula/src/qt-console/prefs.ui index cc4d8fb361..0079fd3e97 100644 --- a/bacula/src/qt-console/prefs.ui +++ b/bacula/src/qt-console/prefs.ui @@ -5,8 +5,8 @@ 0 0 - 361 - 452 + 360 + 485 @@ -182,11 +182,63 @@ Misc + + + + 30 + 220 + 271 + 111 + + + + Convert + + + + + 20 + 20 + 231 + 22 + + + + Convert Off + + + + + + 20 + 50 + 231 + 22 + + + + Convert Bytes with IEC 1000B = KB + + + + + + 20 + 80 + 231 + 22 + + + + Convert Bytes with 1024B = KB + + + - 40 - 40 + 30 + 10 190 55 @@ -210,55 +262,55 @@ - + - 40 - 160 - 261 - 131 + 30 + 80 + 271 + 121 - Convert + GroupBox - + - 20 - 20 - 231 - 22 + 10 + 30 + 241 + 20 - Convert Off + Open Plot page on startup - + - 20 + 10 60 - 231 - 22 + 241 + 20 - Convert Bytes with IEC 1000B = KB + Open Browser page on startup - + - 20 - 100 - 231 - 22 + 10 + 90 + 241 + 20 - Convert Bytes with 1024B = KB + Open Director Status page on startup diff --git a/bacula/src/qt-console/status/dirstat.cpp b/bacula/src/qt-console/status/dirstat.cpp new file mode 100644 index 0000000000..beac7fea94 --- /dev/null +++ b/bacula/src/qt-console/status/dirstat.cpp @@ -0,0 +1,318 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2007 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Version $Id: dirstat.cpp 5880 2007-11-09 01:20:40Z bartleyd2 $ + * + * Dirk Bartley, March 2007 + */ + +#include +#include +#include "bat.h" +#include "dirstat.h" + +/* + * Constructor for the class + */ +DirStat::DirStat() +{ + setupUi(this); + m_name = "Director Status"; + m_closeable = true; + pgInitialize(); + QTreeWidgetItem* thisitem = mainWin->getFromHash(this); + thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/joblog.png"))); + m_cursor = new QTextCursor(textEdit->document()); + + readSettings(); + dockPage(); + m_timer = new QTimer(this); + QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(timerTriggered())); + //m_timer->start(mainWin->m_checkMessagesInterval*1000); + m_timer->start(10*1000); +} + +void DirStat::getFont() +{ + QFont font = textEdit->font(); + + QString dirname; + m_console->getDirResName(dirname); + QSettings settings(dirname, "bat"); + settings.beginGroup("Console"); + font.setFamily(settings.value("consoleFont", "Courier").value()); + font.setPointSize(settings.value("consolePointSize", 10).toInt()); + font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool()); + settings.endGroup(); + textEdit->setFont(font); +} + +/* + * Write the m_splitter settings in the destructor + */ +DirStat::~DirStat() +{ + writeSettings(); +} + +/* + * Populate all tables and header widgets + */ +void DirStat::populateAll() +{ + if (!m_console->preventInUseConnect()) + return; + populateHeader(); + populateTerminated(); + populateScheduled(); + populateRunning(); +} + +/* + * Timer is triggered, see if is current and repopulate. + */ +void DirStat::timerTriggered() +{ + bool iscurrent = mainWin->stackedWidget->currentIndex() == mainWin->stackedWidget->indexOf(this); + if ((isDocked() && iscurrent) || (!isDocked())) { + if (m_console->is_ready()) + populateAll(); + } +} + +/* + * Populate header text widget + */ +void DirStat::populateHeader() +{ + QString command = QString(".status dir header"); + QStringList results; + textEdit->clear(); + + if (m_console->dir_cmd(command, results)) { + foreach (QString line, results) { + line += "\n"; + textEdit->insertPlainText(line); + } + } +} + +/* + * Populate teminated table + */ +void DirStat::populateTerminated() +{ + QString command = QString(".status dir terminated"); + QStringList results; + QBrush blackBrush(Qt::black); + + terminatedTable->clear(); + QStringList headerlist = (QStringList() + << "Job Id" << "Job Level" << "Job Files" << "Job Bytes" << "Job Status" + << "Job Time" << "Job Name"); + QStringList flaglist = (QStringList() + << "R" << "L" << "R" << "R" << "LC" + << "L" << "L"); + + terminatedTable->setColumnCount(headerlist.size()); + terminatedTable->setHorizontalHeaderLabels(headerlist); + + if (m_console->dir_cmd(command, results)) { + int row = 0; + QTableWidgetItem* p_tableitem; + terminatedTable->setRowCount(results.size()); + foreach (QString line, results) { + /* Iterate through the record returned from the query */ + QStringList fieldlist = line.split("\t"); + int column = 0; + QString statusCode(""); + /* Iterate through fields in the record */ + foreach (QString field, fieldlist) { + field = field.trimmed(); /* strip leading & trailing spaces */ + p_tableitem = new QTableWidgetItem(field, 1); + p_tableitem->setForeground(blackBrush); + p_tableitem->setFlags(0); + if (flaglist[column].contains("R")) + p_tableitem->setTextAlignment(Qt::AlignRight); + if (flaglist[column].contains("C")) + if (field == "OK") + p_tableitem->setBackground(Qt::green); + else + p_tableitem->setBackground(Qt::red); + terminatedTable->setItem(row, column, p_tableitem); + column += 1; + } + row += 1; + } + } + terminatedTable->resizeColumnsToContents(); + terminatedTable->resizeRowsToContents(); + terminatedTable->verticalHeader()->hide(); +} + +/* + * Populate scheduled table + */ +void DirStat::populateScheduled() +{ + QString command = QString(".status dir scheduled"); + QStringList results; + QBrush blackBrush(Qt::black); + + scheduledTable->clear(); + QStringList headerlist = (QStringList() + << "Job Level" << "Job Type" << "Priority" << "Job Time" << "Job Name" << "Volume"); + QStringList flaglist = (QStringList() + << "L" << "L" << "R" << "L" << "L" << "L"); + + scheduledTable->setColumnCount(headerlist.size()); + scheduledTable->setHorizontalHeaderLabels(headerlist); + + if (m_console->dir_cmd(command, results)) { + int row = 0; + QTableWidgetItem* p_tableitem; + scheduledTable->setRowCount(results.size()); + foreach (QString line, results) { + /* Iterate through the record returned from the query */ + QStringList fieldlist = line.split("\t"); + int column = 0; + QString statusCode(""); + /* Iterate through fields in the record */ + foreach (QString field, fieldlist) { + field = field.trimmed(); /* strip leading & trailing spaces */ + p_tableitem = new QTableWidgetItem(field, 1); + p_tableitem->setForeground(blackBrush); + p_tableitem->setFlags(0); + scheduledTable->setItem(row, column, p_tableitem); + column += 1; + } + row += 1; + } + } + scheduledTable->resizeColumnsToContents(); + scheduledTable->resizeRowsToContents(); + scheduledTable->verticalHeader()->hide(); +} + +/* + * Populate running table + */ +void DirStat::populateRunning() +{ + QString command = QString(".status dir running"); + QStringList results; + QBrush blackBrush(Qt::black); + + runningTable->clear(); + QStringList headerlist = (QStringList() + << "Job Id" << "Job Level" << "Job Data" << "Job Info"); + + runningTable->setColumnCount(headerlist.size()); + runningTable->setHorizontalHeaderLabels(headerlist); + + if (m_console->dir_cmd(command, results)) { + int row = 0; + QTableWidgetItem* p_tableitem; + runningTable->setRowCount(results.size()); + foreach (QString line, results) { + /* Iterate through the record returned from the query */ + QStringList fieldlist = line.split("\t"); + int column = 0; + QString statusCode(""); + /* Iterate through fields in the record */ + foreach (QString field, fieldlist) { + field = field.trimmed(); /* strip leading & trailing spaces */ + p_tableitem = new QTableWidgetItem(field, 1); + p_tableitem->setForeground(blackBrush); + p_tableitem->setFlags(0); + runningTable->setItem(row, column, p_tableitem); + column += 1; + } + row += 1; + } + } + runningTable->resizeColumnsToContents(); + runningTable->resizeRowsToContents(); + runningTable->verticalHeader()->hide(); +} + +/* + * When the treeWidgetItem in the page selector tree is singleclicked, Make sure + * The tree has been populated. + */ +void DirStat::PgSeltreeWidgetClicked() +{ + if (!m_populated) { + populateAll(); + m_populated=true; + } +} + +/* + * Virtual function override of pages function which is called when this page + * is visible on the stack + */ +void DirStat::currentStackItem() +{ + populateAll(); + if (!m_populated) { + m_populated=true; + } +} + +/* + * Function to create connections for context sensitive menu for this and + * the page selector + */ +void DirStat::createConnections() +{ +} + +/* + * Save user settings associated with this page + */ +void DirStat::writeSettings() +{ + QSettings settings(m_console->m_dir->name(), "bat"); + settings.beginGroup(m_groupText); + settings.setValue(m_splitText, splitter->saveState()); + settings.endGroup(); +} + +/* + * Read and restore user settings associated with this page + */ +void DirStat::readSettings() +{ + m_groupText = "DirStatPage"; + m_splitText = "splitterSizes_0"; + QSettings settings(m_console->m_dir->name(), "bat"); + settings.beginGroup(m_groupText); + splitter->restoreState(settings.value(m_splitText).toByteArray()); + settings.endGroup(); +} diff --git a/bacula/src/qt-console/status/dirstat.h b/bacula/src/qt-console/status/dirstat.h new file mode 100644 index 0000000000..cb4c2359b4 --- /dev/null +++ b/bacula/src/qt-console/status/dirstat.h @@ -0,0 +1,73 @@ +#ifndef _DIRSTAT_H_ +#define _DIRSTAT_H_ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2007 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Version $Id: dirstat.h 5372 2007-08-17 12:17:04Z kerns $ + * + * Dirk Bartley, March 2007 + */ + +#include +#include "ui_dirstat.h" +#include "console.h" +#include "pages.h" + +class DirStat : public Pages, public Ui::DirStatForm +{ + Q_OBJECT + +public: + DirStat(); + ~DirStat(); + virtual void PgSeltreeWidgetClicked(); + virtual void currentStackItem(); + +public slots: + void populateHeader(); + void populateTerminated(); + void populateScheduled(); + void populateRunning(); +// virtual void treeWidgetName(QString &); + void populateAll(); + +private slots: + void timerTriggered(); + +private: + void createConnections(); + void writeSettings(); + void readSettings(); + bool m_populated; + QTextCursor *m_cursor; + void getFont(); + QString m_groupText, m_splitText; + QTimer * m_timer; +}; + +#endif /* _DIRSTAT_H_ */ diff --git a/bacula/src/qt-console/status/dirstat.ui b/bacula/src/qt-console/status/dirstat.ui new file mode 100644 index 0000000000..c17270273c --- /dev/null +++ b/bacula/src/qt-console/status/dirstat.ui @@ -0,0 +1,183 @@ + + DirStatForm + + + + 0 + 0 + 537 + 458 + + + + Form + + + + 9 + + + 6 + + + + + Qt::Vertical + + + + + 7 + 7 + 200 + 0 + + + + + 0 + 0 + + + + + 16777215 + 100 + + + + + 1 + 0 + + + + Qt::StrongFocus + + + false + + + + + + + + + + + + Qt::ScrollBarAsNeeded + + + QTextEdit::AutoNone + + + false + + + + + + QTextEdit::NoWrap + + + true + + + + + + 0 + + + 6 + + + + + Qt::LeftToRight + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13pt; font-weight:600;">Scheduled Jobs</span></p></body></html> + + + Qt::AlignCenter + + + + + + + + + + + + 0 + + + 6 + + + + + Qt::LeftToRight + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13pt; font-weight:600;">Running Jobs</span></p></body></html> + + + Qt::AlignCenter + + + + + + + + + + + + 0 + + + 6 + + + + + Qt::LeftToRight + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:13pt; font-weight:600;">Terminated Jobs</span></p></body></html> + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + -- 2.39.5