⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 updateform.cpp

📁 Last change: 2008-02-03 This is the source code of KCeasy。
💻 CPP
字号:
/*
This file is part of KCeasy (http://www.kceasy.com)
Copyright (C) 2002-2004 Markus Kern <mkern@kceasy.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.
*/
//---------------------------------------------------------------------------
#include <vcl.h>
#include <KCeasy.h>
#pragma hdrstop

#include "UpdateForm.h"
#include "AboutDialog.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TAutoUpdate *AutoUpdate;
//---------------------------------------------------------------------------
// local path for storing update.conf
const char* UPDATE_FILE_PATH = "\\update.conf";
//---------------------------------------------------------------------------

__fastcall TAutoUpdate::TAutoUpdate(TComponent* AOwner, bool Silent)
:   TForm(AOwner),
    Download(NULL),
    UpdateConf(NULL),
    AutoStep(1),
    SilentIfCurrent(Silent)
{
    TranslateComponent(this);
    Caption = Brand->ReplaceAppName(Caption);
    HeadLbl->Caption = Brand->ReplaceAppName(HeadLbl->Caption);
    ManualDescrLbl->Caption = Brand->ReplaceAppName(ManualDescrLbl->Caption);
    AutoDescrLbl->Caption = Brand->ReplaceAppName(AutoDescrLbl->Caption);
    AutoStep2Lbl->Caption = Brand->ReplaceAppName(AutoStep2Lbl->Caption);
    AppLogoImage->Picture = Brand->GetLogo48Gray();
    HeadVersionLbl->Caption = AnsiString::Format(HeadVersionLbl->Caption,
                              ARRAYOFCONST((Brand->GetVersionString())));

    if(!StartUpdate()) {
        ModalResult = mrCancel;
        Close();
    }
}

__fastcall TAutoUpdate::~TAutoUpdate()
{
    // free download
    if(Download) {
        Download->Cancel();
        Download->Release();
    }
    // free config
    if(UpdateConf)
        delete UpdateConf;
}
//---------------------------------------------------------------------------

// WARNING: Accessing OpenFT.conf from here!
void TAutoUpdate::UpdateOpenft(TFileConfig* UpdateConf)
{
    string ConfPath = Application->ExeName.c_str();
    ConfPath.erase(ConfPath.rfind('\\'));
    ConfPath += OPENFT_CONF_PATH;
    TFileConfig* OpenFTConf = new TFileConfig(ConfPath);

    if(!OpenFTConf->Load(true))
        return;

    static const struct {
        char *UpdateName;
        char *OpenFTName;
    } Keys[] = {
        { "openft/promote_chance", "autopromote/promote_chance" },
        { "openft/demote_chance",  "autopromote/demote_chance" },
        { "openft/impoverish_min", "autopromote/impoverish_min" },
        { "openft/surplus_min",    "autopromote/surplus_min" },
        { NULL, NULL }
    };

    bool Dirty = false;
    for(int i=0; Keys[i].UpdateName; i++) {
        if (UpdateConf->ValueExists(Keys[i].UpdateName))
        {
            OpenFTConf->SetValue(Keys[i].OpenFTName, UpdateConf->GetValue(Keys[i].UpdateName));
            Dirty = true;
        }
    }

    if(Dirty)
        OpenFTConf->Save();
    delete OpenFTConf;
}

//---------------------------------------------------------------------------

bool TAutoUpdate::StartUpdate()
{
    if(Download)
        return false;

    // create url
    if(Brand->GetAutoUpdateUrl() == "")
        return false;

    string Url(Brand->GetAutoUpdateUrl());
    Url += string("?") + Brand->GetUrlSignature();

    // create save path
    string Path = Application->ExeName.c_str();
    Path.erase(Path.rfind('\\'));
    Path += UPDATE_FILE_PATH;

    // create and start http download
    Download = new THttpDownload(this->Handle, WM_UPDATE_CB);
    if(!Download->Start(Url, Path))
        return false;

    return true;
}

void __fastcall TAutoUpdate::WMUpdateCb(TMessage& Msg)
{
    if(!Download || UpdateConf)
        return; // can't happen

    switch(Download->GetState()) {
    case HttpDownloadCancelled:
    case HttpDownloadFailed:
        // release download
        Download->Release();
        Download = NULL;
        // close form
        ModalResult = mrCancel;
        Close();
        break;
    case HttpDownloadCompleted: {
        UpdateConf = new TFileConfig(Download->GetSavePath());
        // release download
        Download->Release();
        Download = NULL;

        if(!UpdateConf->Load()) {
            ModalResult = mrCancel;
            Close();
            break;
        }

        // Updated OpenFT auto promotion parameters
        UpdateOpenft(UpdateConf);

        int MajorVersion = UpdateConf->GetValueInt("kceasy/major_version");
        int MinorVersion = UpdateConf->GetValueInt("kceasy/minor_version");

        if((MajorVersion < Brand->GetMajorVersion() ||
           (MajorVersion == Brand->GetMajorVersion() &&
            MinorVersion <= Brand->GetMinorVersion())) &&
            !UpdateConf->GetValueInt("kceasy/should_update"))
        {
            // tell user that he has the current version
            if (!SilentIfCurrent) {
                MessageDlg(_("You are using the latest stable version of {AppName}.\n") +
                           _("There are no new updates at this time." ),
                           mtInformation, TMsgDlgButtons() << mbOK,0);
            }

            ModalResult = mrCancel;
            Close();
            break;
        }

        NewVersionGrp->Caption = AnsiString::Format(NewVersionGrp->Caption,
                                 ARRAYOFCONST((MajorVersion, MinorVersion)));
        // insert lines into decription memo
        list<string> Lines = string_split(UpdateConf->GetValue("kceasy/description"), "|");
        DescrMemo->Clear();
        for(list<string>::iterator itr=Lines.begin(); itr != Lines.end(); ++itr)
            DescrMemo->Lines->Add((*itr).c_str());
        // set manual update url
        ManualUrlLbl->Caption = UpdateConf->GetValue("kceasy/manual_url").c_str();
        ManualSizeLbl->Caption = AnsiString("[") + FormatNumber(UpdateConf->GetValueInt("kceasy/filesize"),"B",2).c_str() + "]";

        // show the dialog
        MessageBeep(MB_ICONEXCLAMATION);
        Show();
        break;
    }
    }
}
//---------------------------------------------------------------------------

bool TAutoUpdate::StartDownload()
{
    if(Download || !UpdateConf)
        return false; // erm?

    // create save path
    string Path = Application->ExeName.c_str();
    Path.erase(Path.rfind('\\'));
    Path += string("\\") + UpdateConf->GetValue("kceasy/filename");
    // create url
    string Url = UpdateConf->GetValue("kceasy/auto_url");

    // create and start http download
    Download = new THttpDownload(this->Handle, WM_DOWNLOAD_CB);
    if(!Download->Start(Url, Path))
        return false;

    return true;
}

void __fastcall TAutoUpdate::WMDownloadCb(TMessage& Msg)
{
    if(!Download || !UpdateConf)
        return; // can't happen

    switch(Download->GetState()) {
    case HttpDownloadActive:
        // update progress bar
        if(Download->GetProgressMax() > 0)
            AutoProgressBar->Position = Download->GetProgress() * 100 / Download->GetProgressMax();
        else
            AutoProgressBar->Position = 0;
        break;
    case HttpDownloadCancelling:
        break;
    case HttpDownloadCancelled:
        break;
    case HttpDownloadFailed:
        // release download
        Download->Release();
        Download = NULL;
        // TRANSLATOR: Error when automatic download of update failed.
        AutoStep1Lbl->Caption = _("Error: Automatic download failed. Please update manually.");
        AutoStep1Lbl->Font->Color = clRed;
        break;
    case HttpDownloadCompleted: {
        // check that size of download is correct
        DWORD FileSize = 0xFFFFFFFF;
        HANDLE hFile = CreateFile(Download->GetSavePath().c_str(),GENERIC_READ,
                       FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
        if(hFile != INVALID_HANDLE_VALUE) {
            FileSize = GetFileSize(hFile, NULL);
            CloseHandle(hFile);
        }

        if((int)FileSize != UpdateConf->GetValueInt("kceasy/filesize")) {
            // something went wrong with the download
            // TRANSLATOR: Error when automatic download of update failed.
            AutoStep1Lbl->Caption = _("Error: Automatic download failed. Please update manually.");
            AutoStep1Lbl->Font->Color = clRed;
        } else {
            // next step
            AutoStep = 2;
            // update UI
            AutoStep1Lbl->Font->Color = clWindowText;
            AutoStep1Lbl->Font->Style = TFontStyles();
            AutoStep2Lbl->Font->Color = clBlue;
            AutoStep2Lbl->Font->Style = TFontStyles() << fsBold;
            // TRANSLATOR: Auto update button caption after file is downloaded and ready to be installed.
            UpdateBtn->Caption = _("Install");
            UpdateBtn->Enabled = true;
            UpdateBtn->Default = true;
        }

        // notify user and wait for install confirmation
        if(WindowState == wsMinimized)
            WindowState = wsNormal;
        MessageBeep(MB_ICONEXCLAMATION);
        Show();
        break;
    }
    }
}
//---------------------------------------------------------------------------
void __fastcall TAutoUpdate::FormCloseQuery(TObject *Sender,
      bool &CanClose)
{
    if(ModalResult == mrNone) {
        // user tried to close via system menu
        // TRANSLATOR: message box when user tries to close update dialog via the X at the top right
        AnsiString Msg = _("Not so fast!\n\n{AppName} is constantly under development and using "
                           "old versions will hurt the networks it uses.\nYou should really "
                           "update. It will only take a minute and all your downloads and "
                           "settings will remain unchanged.");
        MessageDlg(Brand->ReplaceAppName(Msg),mtWarning,TMsgDlgButtons() << mbOK,0);

        CanClose = false;
    }
}

void __fastcall TAutoUpdate::FormClose(TObject *Sender,
      TCloseAction &Action)
{
    Action = caFree;
}
//---------------------------------------------------------------------------

void __fastcall TAutoUpdate::UpdateBtnClick(TObject *Sender)
{
    // handle launch case
    switch(AutoStep) {
    case 1: {
        UpdateBtn->Enabled = false;
        // start download
        if(!StartDownload()) {
            // TRANSLATOR: Error when automatic download of update failed.
            AutoStep1Lbl->Caption = _("Error: Automatic download failed. Please update manually.");
            AutoStep1Lbl->Font->Color = clRed;
        }
        break;
    }
    case 2: {
        UpdateBtn->Enabled = false;
        // launch installer
        string Path = Download->GetSavePath();
        string Dir = Path.substr(0,Path.rfind('\\'));
        if((int)ShellExecute(0,"open",Path.c_str(),"/autoupdate",Dir.c_str(),SW_SHOWNORMAL) <= 32) {
            // launching installer failed
            // TRANSLATOR: Auto update error when start of downloaded update failed.
            AutoStep2Lbl->Caption = _("Error: Automatic installation failed. Please update manually.");
            AutoStep2Lbl->Font->Color = clRed;
            break;
        }
        // close kceasy
        ::PostMessage (MainForm->MessageTarget->GetWndHandle(),
                       WM_KCEASY_EXTERNAL_SHUTDOWN,0,0);
        // close this dialog
        ModalResult = mrOk;
        Close();
        break;
    }
    default:
        // cannot happen
        break;
    }
}

void __fastcall TAutoUpdate::CancelBtnClick(TObject *Sender)
{
    ModalResult = mrCancel;
    Close();
}
//---------------------------------------------------------------------------

void __fastcall TAutoUpdate::ManualUrlLblMouseEnter(TObject *Sender)
{
    ManualUrlLbl->Font->Style = TFontStyles() << fsUnderline;
}

void __fastcall TAutoUpdate::ManualUrlLblMouseLeave(TObject *Sender)
{
    ManualUrlLbl->Font->Style = TFontStyles();
}

void __fastcall TAutoUpdate::ManualUrlLblClick(TObject *Sender)
{
    ShellExecute(0,"open",ManualUrlLbl->Caption.c_str(),NULL,NULL,SW_SHOWNORMAL);
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -