You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ksystemlog/ksystemlog/src/logManager.cpp

601 lines
15 KiB

/***************************************************************************
* Copyright (C) 2005 by Nicolas Ternisien *
* nicolas.ternisien@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* 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. *
***************************************************************************/
//TQt includes
#include <tqclipboard.h>
//KDE includes
#include <tdepopupmenu.h>
#include <kdebug.h>
#include <tdelocale.h>
#include <tdeapplication.h>
#include <tdeio/netaccess.h>
#include <kfilterdev.h>
#include <tdefiledialog.h>
#include <tdemessagebox.h>
//Project includes
#include "logManager.h"
#include "reader.h"
#include "view.h"
#include "ksystemlog.h"
#include "readerFactory.h"
#include "loadingDialog.h"
LogManager::LogManager(KSystemLog* m, LoadingDialog* progress) :
main(m),
loadingDialog(progress),
reader(NULL),
view(NULL),
groupBy(NO_GROUP_BY),
groupByColumn(-1),
columns(NULL),
sortOrder(TQt::Ascending),
sortColumn(0),
tooltipEnabled(true),
newLinesDisplayed(true),
parsingPaused(false),
logFiles(),
current(false),
newLinesSinceLastSelection(0),
lastUpdate(TQTime::currentTime()),
logMode(Globals::noMode) {
//TODO Create the view from a factory for example
view=new View(main);
view->setLogManager(this);
connect(view, TQ_SIGNAL(changeStatusbar(const TQString&)), this, TQ_SLOT(slotChangeStatusbar(const TQString&)));
connect(view, TQ_SIGNAL(changeCaption(const TQString&)), this, TQ_SLOT(slotChangeCaption(const TQString&)));
connect(view->getLogList(), TQ_SIGNAL(doubleClicked(TQListViewItem *, const TQPoint&, int)), this, TQ_SLOT(slotDetails(TQListViewItem *, const TQPoint&, int)));
connect(view->getLogList(), TQ_SIGNAL(selectionChanged()), this, TQ_SLOT(slotSelectionChanged()));
connect(view->getLogList(), TQ_SIGNAL(rightButtonPressed(TQListViewItem*, const TQPoint&, int)), this, TQ_SLOT(slotOpenContextualMenu(TQListViewItem*, const TQPoint&, int)));
}
LogManager::~LogManager() {
//TODO Delete all used object (view and reader)
delete view;
delete reader;
}
View* LogManager::getView() {
return(view);
}
void LogManager::saveConfig() {
view->saveConfig();
}
void LogManager::slotSelectionChanged() {
emit selectionChanged();
}
Reader* LogManager::getReader() {
return(reader);
}
int LogManager::getIndex() {
return(main->getIndex(this));
}
void LogManager::initView() {
if (columns!=NULL)
delete columns;
//Construct columns list
columns=new LogViewColumns();
//Initialize columns list from Reader class
reader->initColumns(columns);
//If groupBy feature is activated, we must draw the tree lines in the view
if (groupBy!=NO_GROUP_BY)
view->getLogList()->setRootIsDecorated(true);
else
view->getLogList()->setRootIsDecorated(false);
view->setColumns(columns);
}
void LogManager::reload() {
loadingDialog->show();
loadingDialog->progressBar()->setProgress(0);
loadingDialog->setLoadingLog(logMode->name);
emit changeStatusbar(i18n("Loading log..."));
kdDebug() << "Reloading " << logMode->name << "..." << endl;
//Change part of the main interface
emit changeTitle(view, logMode->pixmap, logMode->name);
emit changeCaption(logMode->name);
//Empty the current list, to better fill it
clearView();
//Init the Log View
initView();
//Read the log files
reader->readLog();
emit changeStatusbar(i18n("Log successfully loaded."));
//Emit this signal only when the Log List has been totally reloaded
emit reloaded();
loadingDialog->progressBar()->setProgress(100);
loadingDialog->hide();
}
void LogManager::openingProgress(int percent) {
loadingDialog->progressBar()->setProgress(percent);
//Move this signal to Loading Dialog class
emit GUIUpdated();
//((KSystemLog*)( view->parent()))->kapp->processEvents();
}
void LogManager::toggleFilterBar() {
view->toggleFilterBar();
}
void LogManager::slotDetails(TQListViewItem *, const TQPoint &, int) {
emit detailsCalled();
}
void LogManager::slotChangeCaption(const TQString& message) {
emit changeCaption(message);
}
void LogManager::slotChangeStatusbar(const TQString& message) {
emit changeStatusbar(message);
}
LogViewColumns* LogManager::getColumns() {
return(columns);
}
void LogManager::clearView() {
view->clearLogList();
}
void LogManager::setLogFiles(LogFiles* files) {
//We first clear the previous list
//TODO Also delete pointers in this list before empty it
logFiles.clear();
LogFiles::Iterator it;
for(it=files->begin(); it!=files->end(); ++it) {
logFiles.append(*it);
}
//The list is (normally) no longer used after that.
delete files;
}
LogFiles& LogManager::getLogFiles() {
return(logFiles);
}
LogMode* LogManager::getLogMode() {
return(logMode);
}
TQTime& LogManager::getLastUpdate() {
return(lastUpdate);
}
void LogManager::slotLogUpdated(int lineCount) {
kdDebug() << "Log is updated (from LogManager) : " << lineCount << " current=" << isCurrent() << endl;
if (lineCount==0)
return;
newLinesSinceLastSelection+=lineCount;
lastUpdate=TQTime::currentTime();
//Emit this signal even if the current LogManager is selected
emit logUpdated(newLinesSinceLastSelection);
//If the user is in this log manager, he does have to see that some new log lines have appeared
if (isCurrent()==false) {
TQString title(i18n("%1 (%2)").arg(logMode->name).arg(newLinesSinceLastSelection));
//This signal is emitted only if the selected tab is not this one
emit changeTitle(view, title);
}
}
void LogManager::slotExpandAll() {
//If this LogManager is the currently displayed one
if (isCurrent()) {
TQListViewItem* item=view->getLogList()->firstChild();
while (item!=NULL) {
item->setOpen(true);
item=item->nextSibling();
}
}
}
void LogManager::slotCollapseAll() {
//If this LogManager is the currently displayed one
if (isCurrent()) {
TQListViewItem* item=view->getLogList()->firstChild();
while (item!=NULL) {
item->setOpen(false);
item=item->nextSibling();
}
}
}
void LogManager::slotFileSave() {
//If this LogManager is the currently displayed one
if (isCurrent()) {
TQListViewItemIterator it(view->getLogList(), TQListViewItemIterator::Selected);
//No item selected
if (it.current()==NULL) {
emit changeStatusbar(i18n("No items selected. Please select items to be able to save them."));
return;
}
TQString filename = KFileDialog::getSaveFileName(TQString(), TQString(), main);
if (!filename.isEmpty()) {
TQIODevice* ioDev = KFilterDev::deviceForFile( filename );
if (ioDev->open(IO_WriteOnly)) {
TQTextStream stream(ioDev);
int nbCopied=0;
TQListViewItem* qtItem=it.current();
while (qtItem!=NULL) {
LogListItem* item=static_cast<LogListItem*> (qtItem);
//Copy the item content to the stream
stream << item->exportToText();
//Retrieve the next item
it++;
qtItem=it.current();
nbCopied++;
}
ioDev->close();
emit changeStatusbar(i18n("1 log line saved to '%1'.", "%n log lines saved to '%1'.", nbCopied).arg(filename));
}
else {
TQString message(i18n("Unable to save file '%1': Permission Denied.").arg(filename));
KMessageBox::error(main, message, i18n("Unable to save file."), KMessageBox::Notify);
}
delete ioDev;
}
}
}
void LogManager::reinitialize() {
//Reinitialize groupBy
groupBy=NO_GROUP_BY;
groupByColumn=-1;
//TODO Reinitialize sorting, order, column order...
}
void LogManager::initialize(LogMode* mode) {
//If this LogManager has already been initialized
//with another LogMode, then it needs to be reinitialized
if (this->logMode!=Globals::noMode)
reinitialize();
//Use now the new mode
this->logMode=mode;
//Find the reader instance used for this new mode
reader=ReaderFactory::createReader(mode);
connect(reader, TQ_SIGNAL(statusbarChanged(const TQString&)), this, TQ_SLOT(slotChangeStatusbar(const TQString&)));
connect(reader, TQ_SIGNAL(logUpdated(int)), this, TQ_SLOT(slotLogUpdated(int)));
connect(reader, TQ_SIGNAL(openingProgressed(int)), this, TQ_SLOT(openingProgress(int)));
connect(reader, TQ_SIGNAL(readingBegin()), this, TQ_SLOT(readingBegun()));
connect(reader, TQ_SIGNAL(readingFile(int)), this, TQ_SLOT(readingFile(int)));
connect(reader, TQ_SIGNAL(readingEnd()), this, TQ_SLOT(readingEnded()));
//Inform this reader that this LogManager is now its parent
reader->setLogManager(this);
//Find the log files used for this kind of mode, and set them to our log manager
setLogFiles(ReaderFactory::createLogFiles(mode));
}
void LogManager::readingBegun() {
//Inform the Loading Dialog on how many Files we have to load
loadingDialog->setFileCount(logFiles.count());
}
void LogManager::readingFile(int currentFile) {
//Inform the Loading Dialog that there is a new file loading
loadingDialog->setCurrentFile(currentFile);
//Update the Progress Dialog label
loadingDialog->show();
loadingDialog->progressBar()->setProgress(0);
loadingDialog->setLoadingLog(logMode->name);
}
void LogManager::readingEnded() {
//Reposition the count total to its default value
loadingDialog->setFileCount(0);
}
void LogManager::setParsingPaused(bool paused) {
parsingPaused=paused;
//If we resume the parsing, then we reparse the files to know if new lines has append
if (parsingPaused==false) {
if (reader!=NULL) {
reader->relaunchLogChanged();
}
}
}
bool LogManager::isParsingPaused() {
return(parsingPaused);
}
void LogManager::setTooltipEnabled(bool enabled) {
tooltipEnabled=enabled;
}
bool LogManager::isTooltipEnabled() {
return(tooltipEnabled);
}
void LogManager::setCurrent(bool cur) {
current=cur;
//Reinitialize the new line count
newLinesSinceLastSelection=0;
}
bool LogManager::isCurrent() {
return(current);
}
void LogManager::setNewLinesDisplayed(bool displayed) {
newLinesDisplayed=displayed;
}
bool LogManager::isNewLinesDisplayed() {
return(newLinesDisplayed);
}
void LogManager::setGroupBy(groupByType group, int column) {
this->groupBy=group;
this->groupByColumn=column;
}
groupByType LogManager::getGroupBy() {
return(groupBy);
}
int LogManager::getGroupByColumn() {
return(groupByColumn);
}
void LogManager::slotSendMail() {
//If this LogManager is the currently displayed one
if (isCurrent()) {
TQString body(i18n("Here are my logs:\n"));
body+=i18n("---------------------------------------\n");
TQListViewItemIterator it(view->getLogList(), TQListViewItemIterator::Selected);
int i=0;
TQListViewItem* qtItem=it.current();
while (qtItem!=NULL) {
LogListItem* item=static_cast<LogListItem*> (qtItem);
body+= item->exportToText();
body+='\n';
++it;
qtItem=it.current();
++i;
}
body+=i18n("---------------------------------------\n");
//Too much lines selected
if (i>1000) {
KMessageBox::sorry(main, i18n("You have selected too many lines. Please only select important log lines."), i18n("Too Many Lines Selected"));
return;
}
/* Parameters list of this method
const TQString & to,
const TQString & cc,
const TQString & bcc,
const TQString & subject,
const TQString & body,
const TQString & messageFile,
const TQStringList & attachURLs,
const TQCString & startup_id
*/
kapp->invokeMailer("", "", "", i18n("Log Lines of my problem"), body, "", TQStringList(), kapp->startupId());
}
}
void LogManager::slotCopyToClipboard() {
//If this LogManager is the currently displayed one
if (isCurrent()) {
kdDebug() << "Copy to the clipboard" << endl;
TQListView* listView=view->getLogList();
TQListViewItemIterator it(listView, TQListViewItemIterator::Selected);
int nbCopied=0;
LogListItem* item=static_cast<LogListItem*> (it.current());
TQString text;
while (item!=NULL) {
//Copy the item content to the text string
text.append(item->exportToText());
text.append('\n');
//Retrieve the next value
it++;
item=static_cast<LogListItem*> (it.current());
nbCopied++;
}
//Copy text value only if it is not empty
if (nbCopied==0) {
emit changeStatusbar(i18n("No items selected. Nothing copied to clipboard."));
}
else {
//Copy both to clipboard and X11-selection
TQApplication::clipboard()->setText(text, TQClipboard::Clipboard);
TQApplication::clipboard()->setText(text, TQClipboard::Selection);
emit changeStatusbar(i18n("1 log line copied to clipboard.", "%n log lines copied to clipboard.", nbCopied));
}
}
}
void LogManager::synchronize(LogLineList* buffer) {
kdDebug() << "Synchronizing the buffer..." << endl;
//Here to find a bug
if (buffer==NULL)
kdDebug() << "ERROR! Buffer NULL" << endl;
else
kdDebug() << "Buffer not NULL" << endl;
//Here to find a bug
if (view==NULL)
kdDebug() << "ERROR! View NULL" << endl;
else
kdDebug() << "View not NULL" << endl;
//Synchronize the buffer returned by the reader and get the last added line
LogLine* line=buffer->synchronize(view);
//Here to find a bug
if (line==NULL)
kdDebug() << "ERROR! Line NULL" << endl;
else
kdDebug() << "Line not NULL" << endl;
//Here to find a bug
if (view->getLogList()==NULL)
kdDebug() << "ERROR! TDEListView NULL" << endl;
else
kdDebug() << "TDEListView not NULL" << endl;
if (isNewLinesDisplayed()==true) {
if (line!=NULL) {
line->ensureItemVisible(view->getLogList());
}
}
kdDebug() << "Buffer synchronized." << endl;
}
//TODO Change the method name
void LogManager::slotOpenContextualMenu(TQListViewItem* /*item*/, const TQPoint& pos, int /*other*/) {
TQPopupMenu menu(main);
main->actionCollection()->action("reload")->plug(&menu);
main->actionCollection()->action("select_all")->plug(&menu);
menu.insertSeparator();
main->actionCollection()->action("copy")->plug(&menu);
main->actionCollection()->action("file_save")->plug(&menu);
menu.insertSeparator();
main->actionCollection()->action("enable_tooltip")->plug(&menu);
main->actionCollection()->action("display_new_line")->plug(&menu);
main->actionCollection()->action("group_by")->plug(&menu);
menu.insertSeparator();
main->actionCollection()->action("details")->plug(&menu);
menu.exec(pos);
}
#include "logManager.moc"