/*************************************************************************** * Copyright (C) 2006-2012 by Thomas Schweitzer * * thomas-schweitzer(at)arcor.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2.0 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 in the file LICENSE.GPL; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "UpdateCheckDialog.h" #include "ui_UpdateCheckDialog.h" #include "UiGuiSettings.h" #include "UiGuiVersion.h" #include #include #include #include #include #include #include #include #include #include /*! \class UpdateCheckDialog \ingroup grp_MainWindow \brief UpdateCheckDialog is a dialog widget that contains functions for online checking for a new version of UniversalIndentGUI. */ /*! \brief Initializes member variables and stores the version of UiGui and a pointer to the _settings object. */ UpdateCheckDialog::UpdateCheckDialog(TQSharedPointer settings, TQWidget *parent) : TQDialog(parent), _manualUpdateRequested(false), _currentNetworkReply(NULL), _roleOfClickedButton(TQDialogButtonBox::InvalidRole) { _updateCheckDialogForm = new Ui::UpdateCheckDialog(); _updateCheckDialogForm->setupUi(this); // Create object for _networkAccessManager request and connect it with the request return handler. _networkAccessManager = new TQNetworkAccessManager(this); connect(_networkAccessManager, SIGNAL(finished(TQNetworkReply*)), this, SLOT(checkResultsOfFetchedPadXMLFile(TQNetworkReply*))); // Create a timer object used for the progress bar. _updateCheckProgressTimer = new TQTimer(this); _updateCheckProgressTimer->setInterval(5); connect(_updateCheckProgressTimer, SIGNAL(timeout()), this, SLOT(updateUpdateCheckProgressBar())); _updateCheckProgressCounter = 0; // Connect the dialogs buttonbox with a button click handler. connect(_updateCheckDialogForm->buttonBox, SIGNAL(clicked(TQAbstractButton*)), this, SLOT(handleUpdateCheckDialogButtonClicked(TQAbstractButton*))); settings->registerObjectSlot(this, "initProxySettings()", "ProxyEnabled"); settings->registerObjectSlot(this, "initProxySettings()", "ProxyHostName"); settings->registerObjectSlot(this, "initProxySettings()", "ProxyPort"); settings->registerObjectSlot(this, "initProxySettings()", "ProxyUserName"); settings->registerObjectSlot(this, "initProxySettings()", "ProxyPassword"); _settings = settings; initProxySettings(); // This dialog is always modal. setModal(true); } /*! \brief On destroy cancels any currently running network request. */ UpdateCheckDialog::~UpdateCheckDialog() { disconnect(_networkAccessManager, SIGNAL(finished(TQNetworkReply*)), this, SLOT(checkResultsOfFetchedPadXMLFile(TQNetworkReply*))); if (_currentNetworkReply != NULL) { _currentNetworkReply->abort(); } } /*! \brief This slot should be called, if an update check is manually invoked. In difference to the automatic update check, during manual update check request a modal progress indicator dialog will be shown. */ void UpdateCheckDialog::checkForUpdateAndShowDialog() { _manualUpdateRequested = true; getPadXMLFile(); showCheckingForUpdateDialog(); } /*! \brief This slot should be called, if an update check is automatically invoked. An automatic invoked update check should run in background, so the user gets not interrupted by a dialog box. */ void UpdateCheckDialog::checkForUpdate() { _manualUpdateRequested = false; getPadXMLFile(); } /*! \brief This function tries to download the UniversalIndentGui pad file from the SourceForge server. */ void UpdateCheckDialog::getPadXMLFile() { //_networkAccessManager->setHost("universalindent.sourceforge.net"); //_networkAccessManager->get("/universalindentgui_pad.xml"); _currentNetworkReply = _networkAccessManager->get(TQNetworkRequest(TQUrl( "http://universalindent.sourceforge.net/universalindentgui_pad.xml"))); } /*! \brief This slot is called after the update check has returned, either by successfully retrieving the pad file, or on any kind of network error. Shows a message if check was successful or not. Offers the user to go to the download page if a newer version exists. In case of an error during update check, a message box with the error will be displayed. */ void UpdateCheckDialog::checkResultsOfFetchedPadXMLFile(TQNetworkReply *networkReply) { Q_ASSERT(_currentNetworkReply == networkReply); // Stop the progress bar timer. _updateCheckProgressTimer->stop(); if (networkReply->error() == TQNetworkReply::NoError) { // Try to find the version string. TQString returnedString = networkReply->readAll(); int leftPosition = returnedString.indexOf(""); int rightPosition = returnedString.indexOf(""); // If the version string could be found in the returned string, show an update dialog and set // last update check date. if (leftPosition != -1 && rightPosition != -1) { // Get the pure version string from returned string. returnedString = returnedString.mid(leftPosition + 17, rightPosition - (leftPosition + 17)); // Create integer values from the version strings. int versionOnServerInt = convertVersionStringToNumber(returnedString); int currentVersionInt = convertVersionStringToNumber(PROGRAM_VERSION_STRING); // Only show update dialog, if the current version number is lower than the one received from // the server. if (versionOnServerInt > currentVersionInt && currentVersionInt >= 0 && versionOnServerInt >= 0) { // Show message box whether to download the new version. showNewVersionAvailableDialog(returnedString); // If yes clicked, open the download url in the default browser. if (_roleOfClickedButton == TQDialogButtonBox::YesRole) { TQDesktopServices::openUrl(TQUrl( "_networkAccessManager://sourceforge.net/project/showfiles.php?group_id=167482")); } } else if (_manualUpdateRequested) { showNoNewVersionAvailableDialog(); } // Set last update check date. _settings->setValueByName("LastUpdateCheck", TQDate::currentDate()); } // In the returned string, the version string could not be found. else { TQMessageBox::warning(this, tr("Update check error"), tr( "There was an error while trying to check for an update! The retrieved file did not contain expected content.")); } } // If there was some error while trying to retrieve the update info from server and not cancel was // pressed. else if (_roleOfClickedButton != TQDialogButtonBox::RejectRole) { TQMessageBox::warning(this, tr("Update check error"), tr("There was an error while trying to check for an update! Error was : %1").arg( networkReply->errorString())); hide(); } _manualUpdateRequested = false; networkReply->deleteLater(); _currentNetworkReply = NULL; } /*! \brief Displays the progress bar during update check. For displaying activity during update check, a timer is started to updated the progress bar. The user can press a cancel button to stop the update check. */ void UpdateCheckDialog::showCheckingForUpdateDialog() { // Reset the progress bar. _updateCheckProgressCounter = 0; _updateCheckDialogForm->progressBar->setValue(_updateCheckProgressCounter); _updateCheckDialogForm->progressBar->setInvertedAppearance(false); _updateCheckProgressTimer->start(); _updateCheckDialogForm->progressBar->show(); setWindowTitle(tr("Checking for update...")); _updateCheckDialogForm->label->setText(tr("Checking whether a newer version is available")); _updateCheckDialogForm->buttonBox->setStandardButtons(TQDialogButtonBox::Cancel); show(); } /*! \brief Displays the dialog with info about the new available version. */ void UpdateCheckDialog::showNewVersionAvailableDialog(TQString newVersion) { _updateCheckDialogForm->progressBar->hide(); setWindowTitle(tr("Update available")); _updateCheckDialogForm->label->setText(tr( "A newer version of UniversalIndentGUI is available.\nYour version is %1. New version is %2.\nDo you want to go to the download website?").arg( PROGRAM_VERSION_STRING).arg(newVersion)); _updateCheckDialogForm->buttonBox->setStandardButtons( TQDialogButtonBox::No | TQDialogButtonBox::NoButton | TQDialogButtonBox::Yes); exec(); } /*! \brief Displays the dialog, that no new version is available. */ void UpdateCheckDialog::showNoNewVersionAvailableDialog() { _updateCheckDialogForm->progressBar->hide(); setWindowTitle(tr("No new update available")); _updateCheckDialogForm->label->setText(tr( "You already have the latest version of UniversalIndentGUI.")); _updateCheckDialogForm->buttonBox->setStandardButtons(TQDialogButtonBox::Ok); exec(); } /*! \brief This slot is called, when a button in the dialog is clicked. If the clicked button was the cancel button, the user wants to cancel the update check. So the _networkAccessManager request is aborted and the timer for the progress bar animation is stopped. In any case if a button is clicked, the dialog box will be closed. */ void UpdateCheckDialog::handleUpdateCheckDialogButtonClicked(TQAbstractButton *clickedButton) { _roleOfClickedButton = _updateCheckDialogForm->buttonBox->buttonRole(clickedButton); if (_roleOfClickedButton == TQDialogButtonBox::RejectRole) { // Abort the _networkAccessManager request. _currentNetworkReply->abort(); // Stop the progress bar timer. _updateCheckProgressTimer->stop(); } accept(); } /*! \brief This slot is responsible for the animation of the update check progress bar. */ void UpdateCheckDialog::updateUpdateCheckProgressBar() { // Depending on the progress bar direction, decrease or increase the progressbar value. if (_updateCheckDialogForm->progressBar->invertedAppearance()) { _updateCheckProgressCounter--; } else { _updateCheckProgressCounter++; } // If the progress bar reaches 0 or 100 as value, swap the animation direction. if (_updateCheckProgressCounter == 0 || _updateCheckProgressCounter == 100) { _updateCheckDialogForm->progressBar->setInvertedAppearance( !_updateCheckDialogForm->progressBar->invertedAppearance()); } // Update the progress bar value. _updateCheckDialogForm->progressBar->setValue(_updateCheckProgressCounter); } /*! \brief Converts the as string given version \a versionString to an integer number. The \a versionString must have the format x.x.x where each x represents a number of a maximum of 999. If the input format is wrong, -1 will be returned.The first number will be multiplied by 1000000 the second by 1000 and then all three will be summarized. Thus for example 12.5.170 will result in 12005170. */ int UpdateCheckDialog::convertVersionStringToNumber(TQString versionString) { int versionInteger = 0; int pos = 0; TQRegExp regEx("\\d{1,3}.\\d{1,3}.\\d{1,3}"); TQRegExpValidator validator(regEx, NULL); if (validator.validate(versionString, pos) == TQValidator::Acceptable) { TQStringList versionNumberStringList = versionString.split("."); versionInteger = versionNumberStringList.at(0).toInt() * 1000000; versionInteger += versionNumberStringList.at(1).toInt() * 1000; versionInteger += versionNumberStringList.at(2).toInt(); } else { versionInteger = -1; } return versionInteger; } void UpdateCheckDialog::initProxySettings() { if (_settings->getValueByName("ProxyEnabled") == true) { TQString proxyHostName = _settings->getValueByName("ProxyHostName").toString(); int proxyPort = _settings->getValueByName("ProxyPort").toInt(); TQString proxyUserName = _settings->getValueByName("ProxyUserName").toString(); TQString proxyPassword = _settings->getValueByName("ProxyPassword").toString(); _networkAccessManager->setProxy(TQNetworkProxy(TQNetworkProxy::Socks5Proxy, proxyHostName, proxyPort, proxyUserName, proxyPassword)); } else { _networkAccessManager->setProxy(TQNetworkProxy()); } }