diff options
Diffstat (limited to 'klinkstatus/src/ui/sessionwidget.cpp')
-rw-r--r-- | klinkstatus/src/ui/sessionwidget.cpp | 723 |
1 files changed, 723 insertions, 0 deletions
diff --git a/klinkstatus/src/ui/sessionwidget.cpp b/klinkstatus/src/ui/sessionwidget.cpp new file mode 100644 index 00000000..da128070 --- /dev/null +++ b/klinkstatus/src/ui/sessionwidget.cpp @@ -0,0 +1,723 @@ +/*************************************************************************** + * Copyright (C) 2004 by Paulo Moura Guedes * + * [email protected] * + * * + * 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. * + ***************************************************************************/ + +#include <kapplication.h> +#include <kurl.h> +#include <kcombobox.h> +#include <ksqueezedtextlabel.h> +#include <kprogress.h> +#include <kmessagebox.h> +#include <kconfig.h> +#include <kiconloader.h> +#include <kglobal.h> +#include <kpushbutton.h> +#include <kfiledialog.h> +#include <kactionclasses.h> +#include <ktempfile.h> +#include <ksavefile.h> +#include <kstandarddirs.h> +#include <kio/netaccess.h> + +#include <qevent.h> +#include <qlineedit.h> +#include <qspinbox.h> +#include <qcheckbox.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qlistbox.h> +#include <qstringlist.h> +#include <qbuttongroup.h> +#include <qtoolbutton.h> +#include <qregexp.h> + +#include "sessionwidget.h" +#include "tablelinkstatus.h" +#include "treeview.h" +#include "documentrootdialog.h" +#include "klshistorycombo.h" +#include "klsconfig.h" +#include "resultview.h" +#include "../global.h" +#include "../engine/linkstatus.h" +#include "../engine/linkchecker.h" +#include "../engine/searchmanager.h" +#include "resultssearchbar.h" +#include "../actionmanager.h" +#include "../utils/utils.h" +#include "../utils/xsl.h" + + +SessionWidget::SessionWidget(int max_simultaneous_connections, int time_out, + QWidget* parent, const char* name, WFlags f) + : SessionWidgetBase(parent, name, f), search_manager_(0), + action_manager_(ActionManager::getInstance()), + ready_(true), to_start_(false), to_pause_(false), to_stop_(false), + in_progress_(false), paused_(false), stopped_(true), + bottom_status_timer_(this, "bottom_status_timer"), + max_simultaneous_connections_(max_simultaneous_connections), + time_out_(time_out), tree_display_(false), follow_last_link_checked_(KLSConfig::followLastLinkChecked()), + start_search_action_(0) +{ + newSearchManager(); + + init(); + slotLoadSettings(); + + connect(combobox_url, SIGNAL( textChanged ( const QString & ) ), + this, SLOT( slotEnableCheckButton( const QString & ) ) ); + + connect(tree_view, SIGNAL( clicked ( QListViewItem * ) ), + this, SLOT( showBottomStatusLabel( QListViewItem * ) ) ); + + connect(&bottom_status_timer_, SIGNAL(timeout()), this, SLOT(clearBottomStatusLabel()) ); +} + +SessionWidget::~SessionWidget() +{ + //combobox_url->saveItems(); This is done every time a URL is checked + + if(KLSConfig::rememberCheckSettings()) + saveCurrentCheckSettings(); +} + +void SessionWidget::init() +{ + combobox_url->init(); + + toolButton_clear_combo->setIconSet(SmallIconSet("locationbar_erase")); + + pushbutton_url->setIconSet(KGlobal::iconLoader()->loadIconSet("fileopen", KIcon::Small)); + QPixmap pixMap = KGlobal::iconLoader()->loadIcon("fileopen", KIcon::Small); + pushbutton_url->setFixedSize(pixMap.width() + 8, pixMap.height() + 8); + connect(pushbutton_url, SIGNAL(clicked()), this, SLOT(slotChooseUrlDialog())); + + resultsSearchBar->hide(); + + start_search_action_ = static_cast<KToggleAction*> (action_manager_->action("start_search")); + + connect(resultsSearchBar, SIGNAL(signalSearch(LinkMatcher)), + this, SLOT(slotApplyFilter(LinkMatcher))); +} + +void SessionWidget::slotLoadSettings(bool modify_current_widget_settings) +{ + if(modify_current_widget_settings) + { + checkbox_recursively->setChecked(KLSConfig::recursiveCheck()); + spinbox_depth->setValue(KLSConfig::depth()); + checkbox_subdirs_only->setChecked(!KLSConfig::checkParentFolders()); + checkbox_external_links->setChecked(KLSConfig::checkExternalLinks()); + tree_display_ = KLSConfig::displayTreeView(); + tree_view->setTreeDisplay(tree_display_); + } + + search_manager_->setTimeOut(KLSConfig::timeOut()); + + //kdDebug(23100) << "tree_display_: " << tree_display_ << endl; +} + +void SessionWidget::saveCurrentCheckSettings() +{ + KLSConfig::setRecursiveCheck(checkbox_recursively->isChecked()); + KLSConfig::setDepth(spinbox_depth->value()); + KLSConfig::setCheckParentFolders(!checkbox_subdirs_only->isChecked()); + KLSConfig::setCheckExternalLinks(checkbox_external_links->isChecked()); + + KLSConfig::writeConfig(); +} + +void SessionWidget::newSearchManager() +{ + if(search_manager_) + delete search_manager_; + + search_manager_ = new SearchManager(KLSConfig::maxConnectionsNumber(), + KLSConfig::timeOut(), + this, "search_manager"); + Q_ASSERT(search_manager_); + + connect(search_manager_, SIGNAL(signalRootChecked(const LinkStatus *, LinkChecker *)), + this, SLOT(slotRootChecked(const LinkStatus *, LinkChecker *))); + connect(search_manager_, SIGNAL(signalLinkChecked(const LinkStatus *, LinkChecker *)), + this, SLOT(slotLinkChecked(const LinkStatus *, LinkChecker *))); + connect(search_manager_, SIGNAL(signalSearchFinished()), + this, SLOT(slotSearchFinished())); + connect(search_manager_, SIGNAL(signalSearchPaused()), + this, SLOT(slotSearchPaused())); + connect(search_manager_, SIGNAL(signalAddingLevelTotalSteps(uint)), + this, SLOT(slotAddingLevelTotalSteps(uint))); + connect(search_manager_, SIGNAL(signalAddingLevelProgress()), + this, SLOT(slotAddingLevelProgress())); + connect(search_manager_, SIGNAL(signalLinksToCheckTotalSteps(uint)), + this, SLOT(slotLinksToCheckTotalSteps(uint))); +} + +void SessionWidget::setColumns(QStringList const& colunas) +{ + tree_view->setColumns(colunas); +} + +void SessionWidget::setUrl(KURL const& url) +{ + combobox_url->setCurrentText(url.prettyURL()); + combobox_url->setFocus(); +} + +bool SessionWidget::isEmpty() const +{ + Q_ASSERT(tree_view); + return tree_view->isEmpty(); +} + +SearchManager const* SessionWidget::getSearchManager() const +{ + return search_manager_; +} + +void SessionWidget::slotEnableCheckButton(const QString & s) +{ + if(!(stopped_ && !pendingActions())) + return; + + if(!s.isEmpty() && !search_manager_->searching()) + { + start_search_action_->setEnabled(true); + } + else + { + start_search_action_->setEnabled(false); + } +} + +void SessionWidget::slotCheck() +{ + Q_ASSERT(to_start_); + Q_ASSERT(!in_progress_); + Q_ASSERT(!paused_); + Q_ASSERT(stopped_); + + ready_ = false; + if(!validFields()) + { + ready_ = true; + KApplication::beep(); + return; + } + + emit signalSearchStarted(); + + in_progress_ = true; + paused_ = false; + stopped_ = false; + + slotLoadSettings(false); // it seems that KConfigDialogManager is not trigering this slot + + newSearchManager(); + + insertUrlAtCombobox(combobox_url->currentText()); + combobox_url->saveItems(); + progressbar_checker->reset(); + progressbar_checker->setPercentageVisible(true); + progressbar_checker->setTotalSteps(1); // check root page + progressbar_checker->setProgress(0); + textlabel_progressbar->setText(i18n( "Checking..." )); + + textlabel_elapsed_time->setEnabled(true); + //textlabel_elapsed_time_value->setText(""); + textlabel_elapsed_time_value->setEnabled(true); + + //table_linkstatus->clear(); + tree_view->clear(); + + KURL url = Url::normalizeUrl(combobox_url->currentText()); + + if(!url.protocol().startsWith("http")) + { + QString documentRootHint = url.directory().isEmpty() ? "/" : url.directory(); + DocumentRootDialog dialog(this, documentRootHint); + dialog.exec(); + search_manager_->setDocumentRoot(KURL::fromPathOrURL(dialog.url())); + } + + if(KLSConfig::useQuantaUrlPreviewPrefix() && Global::isKLinkStatusEmbeddedInQuanta()) + { + KURL url_aux = Global::urlWithQuantaPreviewPrefix(url); + if(url_aux.isValid() && !url_aux.isEmpty()) + url = url_aux; + } + + if(!checkbox_recursively->isChecked()) + { + search_manager_->setSearchMode(SearchManager::depth); + search_manager_->setDepth(0); + } + + else if(checkbox_recursively->isChecked()) + { + if(spinbox_depth->value() == 0) + { + search_manager_->setSearchMode(SearchManager::domain); + } + else + { + search_manager_->setSearchMode(SearchManager::depth_and_domain); + search_manager_->setDepth(spinbox_depth->value()); + } + + if(checkbox_subdirs_only->isChecked()) + { + search_manager_->setCheckParentDirs(false); + + if(url.hasHost()) + search_manager_->setDomain(url.host() + url.directory(true, false)); + } + else + { + search_manager_->setCheckParentDirs(true); + + if(url.hasHost()) + search_manager_->setDomain(url.host()); + } + if(checkbox_external_links->isChecked()) + { + search_manager_->setCheckExternalLinks(true); + search_manager_->setExternalDomainDepth(1); + } + else + { + search_manager_->setCheckExternalLinks(false); + search_manager_->setExternalDomainDepth(0); + } + } + if(!lineedit_reg_exp->text().isEmpty()) + { + search_manager_->setCheckRegularExpressions(true); + search_manager_->setRegularExpression(lineedit_reg_exp->text(), false); + } + + kdDebug(23100) << "URI: " << url.prettyURL() << endl; + combobox_url->setCurrentText(url.prettyURL()); + search_manager_->startSearch(url); + slotSetTimeElapsed(); +} + +void SessionWidget::keyPressEvent ( QKeyEvent* e ) +{ + if( e->key() == Qt::Key_Return && + ( combobox_url->hasFocus() || + //lineedit_domain->hasFocus() || + //checkbox_depth->hasFocus() || + spinbox_depth->hasFocus() || + //checkbox_domain->hasFocus() || + //spinbox_external_domain->hasFocus() + checkbox_recursively->hasFocus() || + checkbox_external_links->hasFocus() || + checkbox_subdirs_only->hasFocus() ) ) + { + if(validFields()) + { + slotStartSearch(); + } + } + + else if(e->key() == Qt::Key_F6) + { + combobox_url->lineEdit()->selectAll(); + } +} + +bool SessionWidget::validFields() +{ + if(combobox_url->currentText().isEmpty()) + { + KMessageBox::sorry(this, i18n("Cowardly refusing to check an empty URL.")); + return false; + } + + else + return true; +} + +void SessionWidget::slotRootChecked(LinkStatus const* linkstatus, LinkChecker * anal) +{ + slotSetTimeElapsed(); + emit signalUpdateTabLabel(search_manager_->linkStatusRoot(), this); + + Q_ASSERT(textlabel_progressbar->text() == i18n("Checking...") || + textlabel_progressbar->text() == i18n("Stopped")); + + progressbar_checker->setProgress(1); + + //table_linkstatus->insertResult(linkstatus); + TreeViewItem* tree_view_item = new TreeViewItem(tree_view, tree_view->lastItem(), linkstatus); + LinkStatus* ls = const_cast<LinkStatus*> (linkstatus); + ls->setTreeViewItem(tree_view_item); + + if(linkstatus->isRedirection() && linkstatus->redirection()) + slotLinkChecked(linkstatus->redirection(), anal); + + resultsSearchBar->show(); + ActionManager::getInstance()->action("file_export_html")->setEnabled(!isEmpty()); +} + +void SessionWidget::slotLinkChecked(LinkStatus const* linkstatus, LinkChecker * anal) +{ + slotSetTimeElapsed(); + + kdDebug(23100) << textlabel_progressbar->text() << endl; + + Q_ASSERT(textlabel_progressbar->text() == i18n("Checking...") || + textlabel_progressbar->text() == i18n("Stopped")); + + progressbar_checker->setProgress(progressbar_checker->progress() + 1); + + if(linkstatus->checked()) + { + TreeViewItem* tree_view_item = 0; + TreeViewItem* parent_item = linkstatus->parent()->treeViewItem(); + bool match = resultsSearchBar->currentLinkMatcher().matches(*linkstatus); + + if(tree_display_) + { + //kdDebug(23100) << "TREE!!!!!" << endl; + tree_view_item = new TreeViewItem(tree_view, parent_item, parent_item->lastChild(), linkstatus); + + parent_item->setLastChild(tree_view_item); + if(follow_last_link_checked_) + tree_view->ensureRowVisible(tree_view_item, tree_display_); + + tree_view_item->setEnabled(match); + } + else + { + //kdDebug(23100) << "FLAT!!!!!" << endl; + tree_view_item = new TreeViewItem(tree_view, tree_view->lastItem(), linkstatus); + if(follow_last_link_checked_) + tree_view->ensureRowVisible(tree_view_item, tree_display_); + + tree_view_item->setVisible(match); + } + + LinkStatus* ls = const_cast<LinkStatus*> (linkstatus); + ls->setTreeViewItem(tree_view_item); + + if(linkstatus->isRedirection() && linkstatus->redirection()) + slotLinkChecked(linkstatus->redirection(), anal); + } +} + +void SessionWidget::slotSearchFinished() +{ + Q_ASSERT(in_progress_); + Q_ASSERT(!paused_); + Q_ASSERT(!stopped_); + + KApplication::beep (); + + textlabel_progressbar->setText(i18n( "Ready" )); + progressbar_checker->reset(); + progressbar_checker->setPercentageVisible(false); + progressbar_checker->setTotalSteps(1); + progressbar_checker->setProgress(0); + + ready_ = true; + + textlabel_elapsed_time->setEnabled(true); + textlabel_elapsed_time_value->setEnabled(true); + textlabel_elapsed_time_value->setText(search_manager_->timeElapsed().toString("hh:mm:ss")); + + in_progress_ = false; + paused_ = false; + stopped_ = true; + resetPendingActions(); + action_manager_->slotUpdateSessionWidgetActions(this); + + emit signalSearchFinnished(); +} + +void SessionWidget::slotSearchPaused() +{ + Q_ASSERT(pendingActions()); + Q_ASSERT(in_progress_); + + KApplication::beep(); + + textlabel_progressbar->setText(i18n("Stopped")); + + ready_ = true; + + if(to_stop_) + { + in_progress_ = false; + paused_ = false; + stopped_ = true; + } + else + { + Q_ASSERT(to_pause_); + Q_ASSERT(!stopped_); + + paused_ = true; + } + + textlabel_elapsed_time->setEnabled(true); + textlabel_elapsed_time_value->setEnabled(true); + textlabel_elapsed_time_value->setText(search_manager_->timeElapsed().toString("hh:mm:ss")); + + resetPendingActions(); + action_manager_->slotUpdateSessionWidgetActions(this); + + emit signalSearchPaused(); +} + +void SessionWidget::insertUrlAtCombobox(QString const& url) +{ + combobox_url->addToHistory(url); +} + +void SessionWidget::showBottomStatusLabel(QListViewItem* item) +{ + kdDebug(23100) << "SessionWidget::showBottomStatusLabel" << endl; + + if(!item) + return; + + TreeViewItem* _item = tree_view->myItem(item); + if(_item) + { + QString status = _item->linkStatus()->statusText(); + textlabel_status->setText(status); + + if(textlabel_status->sizeHint().width() > textlabel_status->maximumWidth()) + QToolTip::add(textlabel_status, status); + else + QToolTip::remove(textlabel_status); + + bottom_status_timer_.stop(); + bottom_status_timer_.start(5 * 1000, true); + } +} + +void SessionWidget::clearBottomStatusLabel() +{ + textlabel_status->clear(); +} + +void SessionWidget::slotSetTimeElapsed() +{ + textlabel_elapsed_time_value->setText(search_manager_->timeElapsed().toString("hh:mm:ss")); +} + +void SessionWidget::slotAddingLevelTotalSteps(uint steps) +{ + textlabel_progressbar->setText(i18n( "Adding level..." )); + progressbar_checker->reset(); + progressbar_checker->setTotalSteps(steps); + progressbar_checker->setProgress(0); +} + +void SessionWidget::slotAddingLevelProgress() +{ + Q_ASSERT(textlabel_progressbar->text() == i18n( "Adding level..." )); + progressbar_checker->setProgress(progressbar_checker->progress() + 1); +} + +void SessionWidget::slotLinksToCheckTotalSteps(uint steps) +{ + textlabel_progressbar->setText(i18n( "Checking..." )); + progressbar_checker->reset(); + progressbar_checker->setTotalSteps(steps); + progressbar_checker->setProgress(0); +} + +void SessionWidget::slotClearComboUrl() +{ + combobox_url->setCurrentText(""); +} + +void SessionWidget::slotChooseUrlDialog() +{ + setUrl(KFileDialog::getOpenURL()); +} + +void SessionWidget::slotHideSearchPanel() +{ + if(buttongroup_search->isHidden()) + buttongroup_search->show(); + else + buttongroup_search->hide(); +} + +void SessionWidget::setFollowLastLinkChecked(bool follow) +{ + kdDebug(23100) << "setFollowLastLinkChecked: " << follow << endl; + follow_last_link_checked_ = follow; +} + +void SessionWidget::slotFollowLastLinkChecked() +{ + follow_last_link_checked_ = !follow_last_link_checked_; +} + +void SessionWidget::slotResetSearchOptions() +{ + slotLoadSettings(true); + + combobox_url->clear(); + lineedit_reg_exp->clear(); +} + +void SessionWidget::slotStartSearch() +{ + if(in_progress_) + { + start_search_action_->setChecked(true); // do not toggle + Q_ASSERT(!stopped_); + KApplication::beep(); + return; + } + + to_start_ = true; + slotLoadSettings(false); + slotCheck(); + resetPendingActions(); + + action_manager_->slotUpdateSessionWidgetActions(this); +} + +void SessionWidget::slotPauseSearch() +{ + Q_ASSERT(in_progress_); + Q_ASSERT(!stopped_); + + if(pendingActions()) + return; + + to_pause_ = true; + + if(!paused_) + { + Q_ASSERT(!ready_); + Q_ASSERT(search_manager_->searching()); + + search_manager_->cancelSearch(); + } + else + { + Q_ASSERT(ready_); + + paused_ = false; + + textlabel_progressbar->setText(i18n("Checking...")); + ready_ = false; + search_manager_->resume(); + + emit signalSearchStarted(); + slotLoadSettings(isEmpty()); // it seems that KConfigDialogManager is not trigering this slot + + resetPendingActions(); + } +} + +void SessionWidget::slotStopSearch() +{ + Q_ASSERT(in_progress_); + Q_ASSERT(!stopped_); + + if(pendingActions()) + return; + + to_stop_ = true; + + if(!paused_) + { + Q_ASSERT(!ready_); + Q_ASSERT(search_manager_->searching()); + + search_manager_->cancelSearch(); + } + else + { + in_progress_ = false; + paused_ = false; + stopped_ = true; + + action_manager_->slotUpdateSessionWidgetActions(this); + } +} + +bool SessionWidget::pendingActions() const +{ + return (to_start_ || to_pause_ || to_stop_); +} + +void SessionWidget::resetPendingActions() +{ + to_start_ = false; + to_pause_ = false; + to_stop_ = false; +} + +void SessionWidget::slotApplyFilter(LinkMatcher link_matcher) +{ + tree_view->show(link_matcher); +} + +void SessionWidget::slotExportAsHTML( ) +{ + KURL url = KFileDialog::getSaveURL(QString::null,"text/html", 0, i18n("Export Results as HTML")); + + if(url.isEmpty()) + return; + + QString filename; + KTempFile tmp; // ### only used for network export + + if(url.isLocalFile()) + filename = url.path(); + else + filename = tmp.name(); + + KSaveFile *savefile = new KSaveFile(filename); + if(savefile->status() == 0) // ok + { + QTextStream *outputStream = savefile->textStream(); + outputStream->setEncoding(QTextStream::UnicodeUTF8); + + QString xslt_doc = FileManager::read(locate("appdata", "styles/results_stylesheet.xsl")); + XSLT xslt(xslt_doc); +// kdDebug(23100) << search_manager_->toXML() << endl; + QString html_ouptut = xslt.transform(search_manager_->toXML()); + (*outputStream) << html_ouptut << endl; + + savefile->close(); + } + + delete savefile; + + if (url.isLocalFile()) + return; + + KIO::NetAccess::upload(filename, url, 0); +} + + +#include "sessionwidget.moc" |