aheinecke@0: #include "mainwindow.h" aheinecke@0: aheinecke@0: #include aheinecke@0: #include aheinecke@0: #include aheinecke@0: #include aheinecke@0: #include aheinecke@0: #include aheinecke@2: #include aheinecke@16: #include aheinecke@19: #include aheinecke@19: aheinecke@19: // The amount of time in minutes stay silent if we have aheinecke@19: // something to say aheinecke@19: #define NAG_INTERVAL_MINUTES 2 aheinecke@0: aheinecke@7: #include "certificatelist.h" aheinecke@10: #include "downloader.h" aheinecke@7: aheinecke@0: MainWindow::MainWindow() { aheinecke@0: createActions(); aheinecke@0: createTrayIcon(); andre@27: qRegisterMetaType("Downloader::ErrorCode"); aheinecke@0: aheinecke@0: connect(mTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), aheinecke@0: this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); aheinecke@19: aheinecke@19: mMessageTimer = new QTimer(this); aheinecke@19: connect(mMessageTimer, SIGNAL(timeout()), this, SLOT(showMessage())); aheinecke@19: mMessageTimer->setInterval(NAG_INTERVAL_MINUTES * 60 * 1000); aheinecke@19: mMessageTimer->start(); aheinecke@0: } aheinecke@0: aheinecke@0: void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) aheinecke@0: { aheinecke@0: switch (reason) { aheinecke@0: case QSystemTrayIcon::Trigger: aheinecke@0: case QSystemTrayIcon::MiddleClick: aheinecke@0: showMessage(); aheinecke@0: break; aheinecke@16: case QSystemTrayIcon::DoubleClick: aheinecke@16: // TODO show menu aheinecke@16: break; aheinecke@0: default: aheinecke@0: ; aheinecke@0: } aheinecke@0: } aheinecke@0: aheinecke@0: void MainWindow::showMessage() aheinecke@0: { aheinecke@16: if (!mCurMessage.isEmpty()) { aheinecke@16: mTrayIcon->showMessage(QApplication::applicationName(), mCurMessage, aheinecke@16: QSystemTrayIcon::Information, 5000); aheinecke@19: mMessageTimer->start(); // Restart the timer so that we don't spam aheinecke@16: } aheinecke@0: } aheinecke@16: aheinecke@16: /** @brief check the integrity of available files. aheinecke@16: * aheinecke@16: * Do not use this as a trust check as this only works on aheinecke@16: * FileNames where the underlying files can change. This aheinecke@16: * is just meant to check if the downloaded data was somehow aheinecke@16: * removed or corrupted. aheinecke@16: * aheinecke@16: */ aheinecke@16: void MainWindow::verifyAvailableData() aheinecke@0: { aheinecke@16: QString listFileName = mSettings.value("List/available").toString(); aheinecke@16: QString swFileName = mSettings.value("Software/available").toString(); aheinecke@16: aheinecke@16: if (!listFileName.isEmpty()) { aheinecke@16: const char *cFileName = listFileName.toLocal8Bit().constData(); aheinecke@16: char *data = NULL; aheinecke@16: size_t size; aheinecke@16: aheinecke@16: if (readAndVerifyList(cFileName, &data, &size) != Valid) { aheinecke@16: // Probably a bug when Qt fileName is encoded and cFileName aheinecke@16: // fails because of this. This needs a unit test! aheinecke@16: // Maybe check that the file is in our data directory aheinecke@16: QFile::remove(listFileName); aheinecke@16: mSettings.remove("List/available"); aheinecke@16: mSettings.remove("List/availableDate"); aheinecke@16: } aheinecke@16: aheinecke@16: free(data); // We only needed verify aheinecke@16: } else { aheinecke@16: // Make sure the available notation is also removed aheinecke@16: mSettings.remove("List/available"); aheinecke@16: mSettings.remove("List/availableDate"); aheinecke@16: } aheinecke@16: aheinecke@16: if (!swFileName.isEmpty()) { aheinecke@16: // TODO aheinecke@16: } else { aheinecke@16: mSettings.remove("Software/available"); aheinecke@16: mSettings.remove("Software/availableDate"); aheinecke@16: } aheinecke@16: } aheinecke@16: aheinecke@16: void MainWindow::handleNewList(const QString& fileName, const QDateTime& modDate) { aheinecke@16: aheinecke@16: mCurMessage = tr("An updated certificate list is available. Click here to install."); aheinecke@16: setState(NewListAvailable); aheinecke@16: mSettings.setValue("List/available", fileName); aheinecke@16: mSettings.setValue("List/availableDate", modDate); aheinecke@16: showMessage(); aheinecke@16: } aheinecke@16: aheinecke@16: void MainWindow::handleNewSW(const QString& fileName, const QDateTime& modDate) { aheinecke@16: mCurMessage = tr("An update for %1 is available. Click here to install.").arg( aheinecke@16: QApplication::applicationName()); aheinecke@16: setState(NewSoftwareAvailable); aheinecke@16: mSettings.setValue("Software/available", fileName); aheinecke@16: mSettings.setValue("Software/availableDate", modDate); aheinecke@16: aheinecke@16: mSettings.sync(); aheinecke@16: showMessage(); aheinecke@16: } aheinecke@16: aheinecke@16: void MainWindow::checkUpdates() aheinecke@16: { aheinecke@16: verifyAvailableData(); aheinecke@16: aheinecke@17: QDateTime listInstalledLastMod = mSettings.value("List/installedDate").toDateTime(); aheinecke@17: QDateTime swInstalledLastMod = mSettings.value("Software/installedDate").toDateTime(); aheinecke@16: andre@27: Downloader* downloader = new Downloader(this, QString::fromLatin1("https://files.kolab.org"), aheinecke@17: QByteArray(), swInstalledLastMod, listInstalledLastMod); aheinecke@17: aheinecke@16: connect(downloader, SIGNAL(newListAvailable(const QString&, const QDateTime&)), aheinecke@16: this, SLOT(handleNewList(const QString&, const QDateTime&))); aheinecke@16: connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)), aheinecke@16: this, SLOT(handleNewSW(const QString&, const QDateTime&))); aheinecke@16: connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater())); aheinecke@16: connect(downloader, SIGNAL(error(const QString &, Downloader::ErrorCode)), aheinecke@16: this, SLOT(downloaderError(const QString &, Downloader::ErrorCode))); aheinecke@10: downloader->start(); aheinecke@0: } aheinecke@0: aheinecke@16: aheinecke@16: void MainWindow::downloaderError(const QString &message, Downloader::ErrorCode error) aheinecke@16: { aheinecke@16: mCurMessage = message; andre@27: showMessage(); aheinecke@16: } aheinecke@16: aheinecke@16: aheinecke@0: void MainWindow::createActions() aheinecke@0: { aheinecke@0: mCheckUpdates = new QAction(tr("Check for Updates"), this); aheinecke@16: connect(mCheckUpdates, SIGNAL(triggered()), this, SLOT(checkUpdates())); aheinecke@2: mQuitAction = new QAction(tr("Quit"), this); aheinecke@2: connect(mQuitAction, SIGNAL(triggered()), qApp, SLOT(quit())); aheinecke@0: } aheinecke@0: aheinecke@0: void MainWindow::createTrayIcon() aheinecke@0: { aheinecke@11: QIcon trayImg(":/img/tray_22.png"); aheinecke@0: aheinecke@0: mTrayMenu = new QMenu(this); aheinecke@0: mTrayMenu->addAction(mCheckUpdates); aheinecke@2: mTrayMenu->addAction(mQuitAction); aheinecke@0: aheinecke@0: mTrayIcon = new QSystemTrayIcon(this); aheinecke@0: mTrayIcon->setContextMenu(mTrayMenu); aheinecke@0: aheinecke@0: mTrayIcon->setIcon(trayImg); aheinecke@0: setWindowIcon(trayImg); aheinecke@0: mTrayIcon->show(); aheinecke@0: mTrayIcon->setToolTip(tr("m13ui")); aheinecke@0: }