# # # add_file "guitone/res/forms/application_update.ui" # content [cfb6889da734fdfa20f68943c73d93983951ce5a] # # add_file "guitone/src/view/dialogs/ApplicationUpdate.cpp" # content [eaf85075d1a7efa6517061e099a28b4b90beb22a] # # add_file "guitone/src/view/dialogs/ApplicationUpdate.h" # content [5f42159d23f734674a94869ad9ed1f52d51ca9b6] # # patch "guitone/guitone.pro" # from [385a99b8d611c6c3eece333dd1e8add6438d9f33] # to [25e4e5caf9d2f4b8c6771f0826f74efd9a84b766] # # patch "guitone/src/monotone/Monotone.cpp" # from [c022744d0e1f616a544f8702e9bb4ff2b72a4dc6] # to [eecfb2cd2d994160207be138cce8dbfcc1a2fd97] # # patch "guitone/src/monotone/Monotone.h" # from [8ed8e4851e892adfd5c8d445ff798f39a6a0019b] # to [213aa23621ca345b374b3f6ef790f09dd69b3cf0] # # patch "guitone/src/view/MainWindow.cpp" # from [e80f15193271437547c136a59a25e9d29bc37f40] # to [9ef3c4f865905bad693c01929f732595f3a222ca] # ============================================================ --- guitone/res/forms/application_update.ui cfb6889da734fdfa20f68943c73d93983951ce5a +++ guitone/res/forms/application_update.ui cfb6889da734fdfa20f68943c73d93983951ce5a @@ -0,0 +1,98 @@ + + ApplicationUpdateDialog + + + + 0 + 0 + 541 + 376 + + + + A new version of guitone is available! + + + :/icons/guitone.png + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Visit website + + + + + + + Close + + + + + + + + + + + + + + + close + clicked() + ApplicationUpdateDialog + accept() + + + 222 + 263 + + + 199 + 149 + + + + + ============================================================ --- guitone/src/view/dialogs/ApplicationUpdate.cpp eaf85075d1a7efa6517061e099a28b4b90beb22a +++ guitone/src/view/dialogs/ApplicationUpdate.cpp eaf85075d1a7efa6517061e099a28b4b90beb22a @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2006 by Thomas Keller * + * address@hidden * + * * + * 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "ApplicationUpdate.h" +#include "SignalWaiter.h" +#include "Guitone.h" +#include "Platform.h" + +#include +#include + +ApplicationUpdate::ApplicationUpdate(QWidget * parent) + : Dialog(parent), update_available(false) +{ + setupUi(this); + Dialog::init(); + + connect( + visitWebsite, SIGNAL(clicked()), + this, SLOT(openWebsite()) + ); + + QHttp http; + http.setHost("guitone.thomaskeller.biz"); + http.get("/appcast.xml"); + + SignalWaiter waiter(&http, SIGNAL(done(bool))); + + // TODO: we definitely should display some status window here + // while waiting for a response on slow connections + waiter.wait(); + + QDomDocument doc; + QString err; + int line, col; + + if (!doc.setContent(http.readAll(), true, &err, &line, &col)) + { + W(QString("Cannot parse document: %1 (line %2, col %3)") + .arg(err).arg(line).arg(col)); + return; + } + + QDomElement channel = doc.documentElement().firstChild().toElement(); + Q_ASSERT(!channel.isNull()); + + QDomNodeList items = channel.elementsByTagName("item"); + + QPair latest(GUITONE_VERSION, ""); + + for (int i=0, j=items.size(); i 0) + { + latest.first = version; + QDomNodeList descs = item.elementsByTagName("description"); + Q_ASSERT(descs.size() == 1); + QDomElement desc = descs.item(0).toElement(); + Q_ASSERT(!desc.isNull()); + latest.second = desc.text(); + } + } + } + + if (latest.first != GUITONE_VERSION) + { + textBrowser->setHtml(latest.second); + update_available = true; + } +} + +ApplicationUpdate::~ApplicationUpdate() {} + +void ApplicationUpdate::openWebsite() +{ + Platform::openFile(this, "http://guitone.thomaskeller.biz"); + accept(); +} + ============================================================ --- guitone/src/view/dialogs/ApplicationUpdate.h 5f42159d23f734674a94869ad9ed1f52d51ca9b6 +++ guitone/src/view/dialogs/ApplicationUpdate.h 5f42159d23f734674a94869ad9ed1f52d51ca9b6 @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2007 by Thomas Keller * + * address@hidden * + * * + * 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef APPLICATION_UPDATE_H +#define APPLICATION_UPDATE_H + +#include "ui_application_update.h" +#include "Dialog.h" + +class ApplicationUpdate : public Dialog, private Ui::ApplicationUpdateDialog +{ + Q_OBJECT + +public: + ApplicationUpdate(QWidget*); + ~ApplicationUpdate(); + inline bool updateAvailable() { return update_available; }; + +private: + bool update_available; + +private slots: + void openWebsite(); +}; + +#endif ============================================================ --- guitone/guitone.pro 385a99b8d611c6c3eece333dd1e8add6438d9f33 +++ guitone/guitone.pro 25e4e5caf9d2f4b8c6771f0826f74efd9a84b766 @@ -1,11 +1,12 @@ # # Common configuration # -GUITONE_VERSION = "0.6-dev" +GUITONE_VERSION = "0.6" TEMPLATE = app TARGET = guitone CONFIG += qt debug +QT += xml network DEFINES += GUITONE_VERSION=\\\"$${GUITONE_VERSION}\\\" INCLUDEPATH = src/ \ @@ -35,6 +36,7 @@ HEADERS += src/view/MainWindow.h \ src/view/dialogs/ChangesetBrowser.h \ src/view/dialogs/RevisionManifest.h \ src/view/dialogs/CommitRevision.h \ + src/view/dialogs/ApplicationUpdate.h \ src/monotone/Monotone.h \ src/monotone/MonotoneDelegate.h \ src/monotone/FileExporter.h \ @@ -89,6 +91,7 @@ SOURCES += src/view/MainWindow.cpp \ src/view/dialogs/ChangesetBrowser.cpp \ src/view/dialogs/RevisionManifest.cpp \ src/view/dialogs/CommitRevision.cpp \ + src/view/dialogs/ApplicationUpdate.cpp \ src/monotone/Monotone.cpp \ src/monotone/MonotoneDelegate.cpp \ src/monotone/FileExporter.cpp \ @@ -136,7 +139,8 @@ FORMS += res/forms/select_revision.ui res/forms/main_window.ui \ res/forms/changeset_browser.ui \ res/forms/manifest.ui \ - res/forms/commit_revision.ui + res/forms/commit_revision.ui \ + res/forms/application_update.ui UI_DIR = tmp OBJECTS_DIR = tmp ============================================================ --- guitone/src/monotone/Monotone.cpp c022744d0e1f616a544f8702e9bb4ff2b72a4dc6 +++ guitone/src/monotone/Monotone.cpp eecfb2cd2d994160207be138cce8dbfcc1a2fd97 @@ -577,7 +577,7 @@ bool Monotone::checkProgramVersion(const return false; } - QRegExp regex("^monotone (\\d+).(\\d+)"); + QRegExp regex("^monotone (\\d+(?:\\.\\d+))"); if (regex.indexIn(output) == -1) { @@ -585,22 +585,14 @@ bool Monotone::checkProgramVersion(const return false; } - QStringList curVersion = regex.capturedTexts(); - curVersion.pop_front(); - QStringList needVersion = RequiredProgramVersion.split("."); - + QString curVersion = regex.cap(1); + D(QString("monotone version: %1, need: %2") - .arg(curVersion.join(".")) + .arg(curVersion) .arg(RequiredProgramVersion) ); - unsigned int curMajor = curVersion.at(0).toUInt(); - unsigned int curMinor = curVersion.at(1).toUInt(); - - unsigned int needMajor = needVersion.at(0).toUInt(); - unsigned int needMinor = needVersion.at(1).toUInt(); - - return curMajor > needMajor || curMajor == needMajor && curMinor >= needMinor; + return versionCompare(curVersion, RequiredProgramVersion) >= 0; } bool Monotone::checkInterfaceVersion(const QString & path) @@ -614,7 +606,7 @@ bool Monotone::checkInterfaceVersion(con return false; } - QRegExp regex("^(\\d+).(\\d+)"); + QRegExp regex("^(\\d+(?:\\.\\d+))"); if (regex.indexIn(output) == -1) { @@ -622,22 +614,15 @@ bool Monotone::checkInterfaceVersion(con return false; } - QStringList curVersion = regex.capturedTexts(); - curVersion.pop_front(); + QString curVersion = regex.cap(1); QStringList needVersion = RequiredInterfaceVersion.split("."); D(QString("interface version: %1, need: %2") - .arg(curVersion.join(".")) + .arg(curVersion) .arg(RequiredInterfaceVersion) ); - unsigned int curMajor = curVersion.at(0).toUInt(); - unsigned int curMinor = curVersion.at(1).toUInt(); - - unsigned int needMajor = needVersion.at(0).toUInt(); - unsigned int needMinor = needVersion.at(1).toUInt(); - - return curMajor > needMajor || curMajor == needMajor && curMinor >= needMinor; + return versionCompare(curVersion, RequiredInterfaceVersion) >= 0; } // strip mtn: warning: and alike from error strings coming from mtn @@ -663,3 +648,32 @@ QString Monotone::stripMtnPrefix(const Q return output.trimmed(); } +// Returns +// -1 if right is greater +// 0 if both are equal +// 1 if left is greater +// FIXME: this should be moved somewhere else +int Monotone::versionCompare(const QString & left, const QString & right) +{ + QStringList leftParts = left.split("."); + QStringList rightParts = right.split("."); + + int leftCount = leftParts.size(); + int rightCount = rightParts.size(); + int maxCount = leftCount > rightCount ? leftCount : rightCount; + + for (int i=0, j=maxCount; i r) return 1; + return -1; + } + + return 0; +} + ============================================================ --- guitone/src/monotone/Monotone.h 8ed8e4851e892adfd5c8d445ff798f39a6a0019b +++ guitone/src/monotone/Monotone.h 213aa23621ca345b374b3f6ef790f09dd69b3cf0 @@ -35,6 +35,7 @@ class Monotone : public QObject static bool checkProgramVersion(const QString &); static bool checkInterfaceVersion(const QString &); static QString stripMtnPrefix(const QString &); + static int versionCompare(const QString &, const QString &); static const QString RequiredProgramVersion; static const QString RequiredInterfaceVersion; static const int StdioBufferSize; ============================================================ --- guitone/src/view/MainWindow.cpp e80f15193271437547c136a59a25e9d29bc37f40 +++ guitone/src/view/MainWindow.cpp 9ef3c4f865905bad693c01929f732595f3a222ca @@ -30,6 +30,7 @@ #include "UpdateWorkspace.h" #include "CommitRevision.h" #include "CheckoutRevision.h" +#include "ApplicationUpdate.h" #include "Platform.h" #include "Preferences.h" #include "KeyManagement.h" @@ -614,7 +615,19 @@ void MainWindow::on_actionCheck_for_upda #ifdef Q_WS_MAC CocoaUtil::checkForUpdates(); #else - Platform::openFile(this, "http://guitone.thomaskeller.biz"); + ApplicationUpdate dlg(this); + if (!dlg.updateAvailable()) + { + QMessageBox::information( + this, + tr("No updates available"), + tr("Your version of guitone (%1) is already up-to-date.") + .arg(GUITONE_VERSION), + QMessageBox::Ok + ); + return; + } + dlg.exec(); #endif }