TortoiseSVN2IDE.pas源代码

unit TortoiseSVN2IDE;

{$R 'icons.res'}

interface

uses ToolsAPI, SysUtils, Windows, Dialogs, Menus, Registry, ShellApi,
    Classes, Controls, Graphics, ImgList, ExtCtrls, ActnList,Forms;//增加了对Forms单元的引用

const
    SVN_PROJECT_EXPLORER = 0;
    SVN_LOG = 1;
    SVN_CHECK_MODIFICATIONS = 2;
    SVN_ADD = 3;
    SVN_UPDATE = 4;
    SVN_COMMIT = 5;
    SVN_DIFF = 6;
    SVN_REVERT = 7;
    SVN_REPOSITORY_BROWSER = 8;
    SVN_SETTINGS = 9;
    SVN_ABOUT = 10;
    SVN_VERB_COUNT = 11;

type TTortoiseSVN = class(TNotifierObject, IOTANotifier, IOTAWizard)
private
    timer: TTimer;
    tsvnMenu: TMenuItem;
    TSVNPath: string;
    procedure Tick( sender: tobject );
    procedure TSVNExec( params: string );
    function GetBitmapName(Index: Integer): string;
    function GetVerb(Index: Integer): string;
    function GetVerbState(Index: Integer): Word;
    procedure ExecuteVerb(Index: Integer);
    procedure CreateMenu;
    procedure UpdateAction( sender: TObject );
    procedure ExecuteAction( sender: TObject );
public
    constructor Create;
    destructor Destroy; override;
    function GetIDString: string;
    function GetName: string;
    function GetState: TWizardState;
    procedure Execute;
end;


{$IFNDEF DLL_MODE}

procedure Register;

{$ELSE}

function InitWizard(const BorlandIDEServices: IBorlandIDEServices;
  RegisterProc: TWizardRegisterProc;
  var Terminate: TWizardTerminateProc): Boolean; stdcall;

{$ENDIF}


implementation

function GetCurrentProject: IOTAProject;
var
  ModServices: IOTAModuleServices;
  Module: IOTAModule;
  Project: IOTAProject;
  ProjectGroup: IOTAProjectGroup;
  i: Integer;
begin
  Result := nil;
  ModServices := BorlandIDEServices as IOTAModuleServices;
  if ModServices <> nil then
      for i := 0 to ModServices.ModuleCount - 1 do
      begin
        Module := ModServices.Modules[i];
        if Supports(Module, IOTAProjectGroup, ProjectGroup) then
        begin
          Result := ProjectGroup.ActiveProject;
          Exit;
        end
        else if Supports(Module, IOTAProject, Project) then
        begin // In the case of unbound packages, return the 1st
          if Result = nil then
            Result := Project;
        end;
      end;
end;

function GetCurrentFileName: string;
var editor: IOTAEditorServices;
begin
    result:= '';
    editor:= BorlandIDEServices as IOTAEditorServices;
    if editor <> nil then begin
        if editor.TopBuffer <> nil then
            result:= editor.TopBuffer.FileName;
    end;
end;

constructor TTortoiseSVN.Create;
var reg: TRegistry;
begin
    Reg := TRegistry.Create;
    try
        Reg.RootKey := HKEY_LOCAL_MACHINE;
        if Reg.OpenKeyReadOnly( '\SOFTWARE\TortoiseSVN' ) then
            TSVNPath:= Reg.ReadString( 'ProcPath' );
    finally
        Reg.CloseKey;
        Reg.Free;
    end;

    tsvnMenu:= nil;

    timer:= TTimer.create(nil);
    timer.interval:= 200;
    timer.OnTimer:= tick;
    timer.enabled:= true;

end;

procedure TTortoiseSVN.Tick( sender: tobject );
var intf: INTAServices;
begin
    if BorlandIDEServices.QueryInterface( INTAServices, intf ) = s_OK then begin
        self.createMenu;
        timer.free;
        timer:= nil;
    end;
end;

procedure TTortoiseSVN.CreateMenu;
var mainMenu: TMainMenu;
    item: TMenuItem;
    i: integer;
    bmp: TBitmap;
    action: TAction;
begin
    if tsvnMenu <> nil then exit;

    tsvnMenu:= TMenuItem.Create(nil);
    tsvnMenu.Caption:= 'TortoiseSVN';


    for i:= 0 to SVN_VERB_COUNT-1 do begin

        bmp:= TBitmap.create;
        try
          bmp.LoadFromResourceName( HInstance, getBitmapName(i) );
        except end;

        action:= TAction.Create(nil);
        action.ActionList:= (BorlandIDEServices as INTAServices).ActionList;
        action.Caption:= getVerb(i);
        action.Hint:= getVerb(i);
        if (bmp.Width = 16) and (bmp.height = 16) then
            action.ImageIndex:= (BorlandIDEServices as INTAServices).AddMasked( bmp, clBlack );
        bmp.free;
        action.OnUpdate:= updateAction;
        action.OnExecute:= executeAction;
        action.Tag:= i;

        item:= TMenuItem.Create( tsvnMenu );
        item.action:= action;

        tsvnMenu.add( item );
    end;

    mainMenu:= (BorlandIDEServices as INTAServices).MainMenu;
    mainMenu.Items.Insert( mainMenu.Items.Count-1, tsvnMenu );
end;

destructor TTortoiseSVN.Destroy;
begin
    if tsvnMenu <> nil then begin
        tsvnMenu.free;
    end;
    inherited;
end;

function TTortoiseSVN.GetBitmapName(Index: Integer): string;
begin
    case index of
        SVN_PROJECT_EXPLORER:
            Result:= 'explorer';
        SVN_LOG:
            Result:= 'log';
        SVN_CHECK_MODIFICATIONS:
            Result:= 'check';
        SVN_ADD:
            Result:= 'add';
        SVN_UPDATE:
            Result:= 'update';
        SVN_COMMIT:
            Result:= 'commit';
        SVN_DIFF:
            Result:= 'diff';
        SVN_REVERT:
            Result:= 'revert';
        SVN_REPOSITORY_BROWSER:
            Result:= 'repository';
        SVN_SETTINGS:
            Result:= 'settings';
        SVN_ABOUT:
            Result:= 'about';
    end;
end;

function TTortoiseSVN.GetVerb(Index: Integer): string;
begin
    case index of
        SVN_PROJECT_EXPLORER:
            Result:= '浏览项目文件夹[&P]...';//'&Project explorer...';
        SVN_LOG:
            Result:= '日志[&L]...';//'&Log...';
        SVN_CHECK_MODIFICATIONS:
            Result:= '检查更新[&M]...';//'Check &modifications...';
        SVN_ADD:
            Result:= '添加[&A]...';//'&Add...';
        SVN_UPDATE:
            Result:= '更新为某一版本[&U]...';//'&Update to revision...';
        SVN_COMMIT:
            Result:= '提交[&C]...';//'&Commit...';
        SVN_DIFF:
            Result:= '差异比较[&D]...';//'&Diff...';
        SVN_REVERT:
            Result:= '还原[&R]...';//'&Revert...';
        SVN_REPOSITORY_BROWSER:
            Result:= '浏览版本库[&B]...';//'Repository &browser...';
        SVN_SETTINGS:
            Result:= '设置[&S]...';//'&Settings...';
        SVN_ABOUT:
            Result:= '关于[&A]...';//'&About...';
    end;
end;

const vsEnabled = 1;

function TTortoiseSVN.GetVerbState(Index: Integer): Word;
begin
    Result:= 0;
    case index of
        SVN_PROJECT_EXPLORER:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_LOG:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_CHECK_MODIFICATIONS:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_ADD:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_UPDATE:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_COMMIT:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_DIFF:
            if GetCurrentFileName <> '' then
                Result:= vsEnabled;
        SVN_REVERT:
            if GetCurrentProject <> nil then
                Result:= vsEnabled;
        SVN_REPOSITORY_BROWSER:
            Result:= vsEnabled;
        SVN_SETTINGS:
            Result:= vsEnabled;
        SVN_ABOUT:
            Result:= vsEnabled;
    end;
end;

procedure TTortoiseSVN.TSVNExec( params: string );
begin
    WinExec( pchar( TSVNPath + ' ' + params ), SW_SHOW );
end;

procedure TTortoiseSVN.ExecuteVerb(Index: Integer);
var project: IOTAProject;
    filename: string;
begin
    project:= GetCurrentProject();
    filename:= getCurrentFileName();
    case index of
        SVN_PROJECT_EXPLORER:
            if project <> nil then
                ShellExecute( 0, 'open', pchar( ExtractFilePath(project.GetFileName) ), '', '', SW_SHOWNORMAL );
        SVN_LOG:
            if project <> nil then
                TSVNExec( '/command:log /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
        SVN_CHECK_MODIFICATIONS:
            if project <> nil then
                TSVNExec( '/command:repostatus /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
        SVN_ADD:
            if project <> nil then
                TSVNExec( '/command:add /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
        SVN_UPDATE:
            if project <> nil then

                if Application.MessageBox('更新之前,所有的项目文件都将被保存。继续吗?  ', '提示',MB_YESNO + MB_ICONQUESTION) = IDYES then begin
                //if MessageDlg( '更新之前,所有的项目文件都将被保存。继续吗?', mtConfirmation, [mbYes, mbNo], 0 ) = mrYes then begin
                    (BorlandIDEServices as IOTAModuleServices).saveAll;
                    TSVNExec( '/command:update /rev /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
                end;
        SVN_COMMIT:
            if project <> nil then
                if Application.MessageBox('提交之前,所有的项目文件都将被保存。继续吗?  ', '提示',MB_YESNO + MB_ICONQUESTION) = IDYES then begin
                //if MessageDlg( '提交之前,所有的项目文件都将被保存。继续吗?', mtConfirmation, [mbYes, mbNo], 0 ) = mrYes then begin
                    (BorlandIDEServices as IOTAModuleServices).saveAll;
                    TSVNExec( '/command:commit /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
                end;
        SVN_DIFF:
            if filename <> '' then
                TSVNExec( '/command:diff /notempfile /path:' + AnsiQuotedStr( filename, '"' ) );
        SVN_REVERT:
            if project <> nil then
                TSVNExec( '/command:revert /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) );
        SVN_REPOSITORY_BROWSER:
            if project <> nil then
                TSVNExec( '/command:repobrowser /notempfile /path:' + AnsiQuotedStr( ExtractFilePath(project.GetFileName), '"' ) )
            else
                TSVNExec( '/command:repobrowser' );
        SVN_SETTINGS:
            TSVNExec( '/command:settings' );
        SVN_ABOUT:
            TSVNExec( '/command:about' );
    end;
end;

procedure TTortoiseSVN.UpdateAction( sender: TObject );
var action: TAction;
begin
    action:= sender as TAction;
    action.Enabled:= getVerbState( action.tag ) = vsEnabled;
end;

procedure TTortoiseSVN.ExecuteAction( sender: TObject );
var action: TAction;
begin
    action:= sender as TAction;
    executeVerb( action.tag );
end;


function TTortoiseSVN.GetIDString: string;
begin
    result:= 'Subversion.TortoiseSVN';
end;

function TTortoiseSVN.GetName: string;
begin
    result:= 'TortoiseSVN add-in';
end;

function TTortoiseSVN.GetState: TWizardState;
begin
    result:= [wsEnabled];
end;

procedure TTortoiseSVN.Execute;
begin
end;

 

{$IFNDEF DLL_MODE}

procedure Register;
begin
    RegisterPackageWizard(TTortoiseSVN.create);
end;

{$ELSE}

var wizardID: integer;

procedure FinalizeWizard;
var
  WizardServices: IOTAWizardServices;
begin
    Assert(Assigned(BorlandIDEServices));

    WizardServices := BorlandIDEServices as IOTAWizardServices;
    Assert(Assigned(WizardServices));

    WizardServices.RemoveWizard( wizardID );

end;

function InitWizard(const BorlandIDEServices: IBorlandIDEServices;
  RegisterProc: TWizardRegisterProc;
  var Terminate: TWizardTerminateProc): Boolean; stdcall;
var
  WizardServices: IOTAWizardServices;
begin
    Assert(BorlandIDEServices <> nil);
    Assert(ToolsAPI.BorlandIDEServices = BorlandIDEServices);

    Terminate := FinalizeWizard;

    WizardServices := BorlandIDEServices as IOTAWizardServices;
    Assert(Assigned(WizardServices));

    wizardID:= WizardServices.AddWizard(TTortoiseSVN.Create as IOTAWizard);

    result:= wizardID >= 0;
end;


exports
  InitWizard name WizardEntryPoint;

{$ENDIF}

 

end.

posted @ 2010-04-09 22:47  Max Woods  阅读(481)  评论(0编辑  收藏  举报