OSDN Git Service

ログ窓リストビュー右クリックでゴースト名コピー
[winbottle/winbottle.git] / bottleclient / LogForm.pas
index a504a93..25cffc8 100755 (executable)
@@ -6,7 +6,8 @@ uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
   ComCtrls, ToolWin, StdCtrls, ExtCtrls, SsParser, BottleDef, Menus,
   Clipbrd, Logs, ShellAPI, Commctrl, DirectSstp, Contnrs, StrUtils,
-  TalkShowFrame, SppList, HtmlOutputConfig, HtmlOutputProgress;
+  TalkShowFrame, SppList, HtmlOutputConfig, HtmlOutputProgress,
+  SearchLog, IniFiles, BRegExp;
 
 type
   // \83\8d\83O\82Ì\95Û\91\95û\96@
@@ -76,6 +77,7 @@ type
     mnDeleteLogItem: TMenuItem;
     mnTabSaveXMLLog: TMenuItem;
     mnSaveHTML: TMenuItem;
+    mnPopupCopyGhost: TMenuItem;
     procedure tbtnClearClick(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure lvwLogChange(Sender: TObject; Item: TListItem;
@@ -126,6 +128,7 @@ type
     procedure lvwLogEndDrag(Sender, Target: TObject; X, Y: Integer);
     procedure mnTabSaveXMLLogClick(Sender: TObject);
     procedure mnSaveHTMLClick(Sender: TObject);
+    procedure mnPopupCopyGhostClick(Sender: TObject);
   private
     { Private \90é\8c¾ }
     FLastScript: String; //\83X\83N\83\8a\83v\83g\8dÄ\95`\89æ\97}\90§\97p
@@ -151,6 +154,9 @@ type
     procedure DrawListViewDragBorder(const Rect: TRect);
     procedure DoSaveLogXML(Log: TBottleLogList);
     procedure DoCloseTab(const Index: integer);
+    function DoSearchLog(Condition: TSearchCond): TBottleLogList;
+    procedure SearchLogIndivisual(Condition: TSearchCond;
+      LogList, Result: TBottleLogList; UntilIndex: integer = -1);
   protected
     procedure CreateParams(var Params: TCreateParams); override;
   public
@@ -321,11 +327,12 @@ begin
   Selected := false;
   IsNormalBottle := false;
   if SelectedBottleLog <> nil then begin
-    StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + '\8c\8f';
     if Change = ctState then begin
       Script := '';
       if lvwLog.Selected <> nil then begin
         Selected := true;
+        StatusBar.Panels[0].Text := Format('%d/%d\8c\8f', [lvwLog.Selected.Index+1,
+          SelectedBottleLog.Count]);
         Log := SelectedBottleLog.Bottles[lvwLog.Selected.Index];
         if (Log.LogType = ltBottle) and not frmSender.Connecting then begin
           IsNormalBottle := true;
@@ -342,6 +349,7 @@ begin
           UpdateScript(''); // \83\8d\83O\83v\83\8c\83r\83\85\81[\95\94\82ð\83N\83\8a\83A
         end;
       end else begin
+        StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + '\8c\8f';
         StatusBar.Panels[1].Text := '';
         UpdateScript(Script); // \83\8d\83O\83v\83\8c\83r\83\85\81[\95\94\83N\83\8a\83A
       end;
@@ -357,6 +365,7 @@ begin
   frmSender.actInsertCue.Enabled := Selected;
   frmSender.actDeleteLogItem.Enabled := Selected;
   mnPopUpCopyScript.Enabled := Selected and IsNormalBottle;
+  mnPopupCopyGhost.Enabled := Selected and IsNormalBottle;
 end;
 
 procedure TfrmLog.lvwLogDblClick(Sender: TObject);
@@ -683,8 +692,11 @@ var i, u, j: integer;
 begin
   Result.Clear;
   SsParser.InputString := Script;
+  SsParser.LeaveEscape := true;
   for i := 0 to SsParser.Count-1 do begin
-    if (SsParser.Match(SsParser[i], '\URL%b') > 0) then begin
+    if (SsParser.Match(SsParser[i], '\URL%b') > 0)
+    and (SsParser.MarkUpType[i] = mtTag) then
+    begin
       for u := 7 downto 1 do begin
         if (SsParser.Match(SsParser[i],
             '\URL%b'+StringReplace(StringOfChar('-', u*2),
@@ -915,39 +927,55 @@ begin
 end;
 
 procedure TfrmLog.tbtnFindBottleClick(Sender: TObject);
-var Query: String;
-    ResultLog: TBottleLogList;
-    Item1, Item2: TLogItem;
-    i, matched: integer;
+var ResultLog: TBottleLogList;
+    Cond: TSearchCond;
+    i: integer;
+    CList, GList: THashedStringList;
 begin
-  if SelectedBottleLog = nil then Exit;
-  if SelectedBottleLog.Count = 0 then begin
-    ShowMessage('\8c\9f\8dõ\91Î\8fÛ\82ª\8bó\82Å\82·\81B');
-    Exit;
-  end;
-  Query := '';
-  matched := 0;
-  if InputQuery('\83X\83N\83\8a\83v\83g\96{\95\82ð\8c\9f\8dõ', '\8c\9f\8dõ\95\8e\9a\97ñ', Query) then begin
-    if Query = '' then Exit;
-    ResultLog := TBottleLogList.Create('\8c\9f\8dõ\8c\8b\89Ê');
-    for i := 0 to SelectedBottleLog.Count-1 do begin
-      Item1 := SelectedBottleLog.Items[i] as TLogItem;
-      if AnsiContainsText(Item1.Script, Query) and (Item1.LogType = ltBottle) then begin
-        matched := matched + 1;
-        Item2 := TLogItem.Create(ltBottle, Item1.MID, Item1.Channel,
-          Item1.Script, Item1.Ghost, Item1.LogTime);
-        Item2.State := lsOpened;
-        Item2.Votes := Item1.Votes;
-        Item2.Agrees := Item1.Agrees;
-        ResultLog.Add(Item2);
+  Application.CreateForm(TfrmSearchLog, frmSearchLog);
+  Cond := TSearchCond.Create(nil);
+  try
+    try
+      with frmSearchLog do
+      begin
+        // \8c»\8dÝ\83\8d\83O\82É\82 \82é\83S\81[\83X\83g\82Æ\83`\83\83\83\93\83l\83\8b\82Ì\83\8a\83X\83g\82ð\8eæ\93¾
+        // \8fd\82½\82¢\82©\82à??
+        CList := THashedStringList.Create;
+        GList := THashedStringList.Create;
+        try
+          for i := 0 to BottleLogList.Count-1 do
+          begin
+            with BottleLogList[i] as TBottleLogList do
+            begin
+              ExtractUniqueChannels(CList);
+              ExtractUniqueGhosts(GList);
+            end;
+          end;
+          CList.Sort;
+          GList.Sort;
+          ChannelList := CList;
+          GhostList   := GList;
+        finally
+          CList.Free;
+          GList.Free;
+        end;
+        if not Execute then
+          Exit
+        else
+          Cond.Assign(Condition);
       end;
+    finally
+      frmSearchLog.Release;
     end;
-    if matched = 0 then
-      ResultLog.AddSystemLog('\8c©\82Â\82©\82è\82Ü\82¹\82ñ\82Å\82µ\82½');
+    // \8c\9f\8dõ\8eÀ\8ds
+    ResultLog := DoSearchLog(Cond);
+    // \90V\83^\83u\82ð\8dì\90¬\82µ\82Ä\89æ\96Ê\8dX\90V
     BottleLogList.Add(ResultLog);
     UpdateTab;
     tabBottleLog.TabIndex := BottleLogList.Count-1;
     UpdateWindow;
+  finally
+    Cond.Free;
   end;
 end;
 
@@ -1584,6 +1612,95 @@ begin
     Canceled := true;
 end;
 
+function TfrmLog.DoSearchLog(Condition: TSearchCond): TBottleLogList;
+var i, UntilIndex: integer;
+begin
+  Result := TBottleLogList.Create('\8c\9f\8dõ\8c\8b\89Ê');
+  if Condition.SearchLogRange in [srSelectedLogList, srAboveSelectedLog] then
+  begin
+    if SelectedBottleLog = nil then
+    begin
+      ShowMessage('\8c\9f\8dõ\91Î\8fÛ\82ª\82 \82è\82Ü\82¹\82ñ');
+      Result.Free;
+      Result := nil;
+      Exit;
+    end else
+    begin
+      if Condition.SearchLogRange = srSelectedLogList then
+        UntilIndex := -1
+      else if lvwLog.Selected = nil then
+        UntilIndex := -1
+      else
+        UntilIndex := lvwLog.Selected.Index;
+      SearchLogIndivisual(Condition, SelectedBottleLog, Result, UntilIndex);
+    end;
+  end else if Condition.SearchLogRange = srAllLogLists then
+  begin
+    for i := 0 to BottleLogList.Count-1 do
+    begin
+      SearchLogIndivisual(Condition, BottleLogList[i] as TBottleLogList,
+        Result);
+    end;
+  end;
+end;
+
+procedure TfrmLog.SearchLogIndivisual(Condition: TSearchCond; LogList,
+  Result: TBottleLogList; UntilIndex: integer = -1);
+var
+  i, Max: integer;
+  Bottle, New: TLogItem;
+  Ok: boolean;
+begin
+  // 1\8cÂ\82Ì\83\8d\83O\83^\83u\82É\91Î\82µ\82Ä\8c\9f\8dõ\82ð\82©\82¯\82é\81BUntilIndex\82Å\94Í\88Í\8ew\92è(\8fÈ\97ª\8e\9e\82»\82Ì\83^\83u\91S\91Ì)
+  if UntilIndex >= 0 then
+    Max := UntilIndex
+  else
+    Max := LogList.Count-1;
+  for i := 0 to Max do
+  begin
+    // \8fð\8c\8f\94»\92è
+    Bottle := LogList.Bottles[i];
+    if Bottle.LogType <> ltBottle then
+      Continue;
+    Ok := true;
+    // \83X\83N\83\8a\83v\83g\83p\83^\81[\83\93\82Å\89ð\90Í
+    if Condition.ScriptPattern <> '' then
+    begin
+      if Condition.ScriptRegExp then
+      begin
+        try
+          if not RegExp.Match(Condition.ScriptPattern, Bottle.Script) then
+            Ok := false;
+        except
+          on EBRegExpError do ; // do nothing
+        end;
+      end else
+      begin
+        if not AnsiContainsText(Bottle.Script, Condition.ScriptPattern) then
+          Ok := false;
+      end;
+    end;
+    // \83`\83\83\83\93\83l\83\8b\96¼\81A\83S\81[\83X\83g\96¼\81A\93\8a\95[\93¯\88Ó
+    if Condition.Channel <> '' then
+      if not AnsiContainsText(Bottle.Channel, Condition.Channel) then
+        Ok := false;
+    if Condition.Ghost <> '' then
+      if not AnsiContainsText(Bottle.Ghost, Condition.Ghost) then
+        Ok := false;
+    if Condition.MinVote > Bottle.Votes then
+      Ok := false;
+    if Condition.MinAgree > Bottle.Agrees then
+      Ok := false;
+    // \8fð\8c\8f\82É\88ê\92v\82µ\82½\82à\82Ì\82ð\8c\8b\89Ê\83\8a\83X\83g\82É\92Ç\89Á
+    if Ok then
+    begin
+      New := TLogItem.Create(Bottle); // \83R\83s\81[\83R\83\93\83X\83g\83\89\83N\83^
+      New.State := lsOpened;
+      Result.Add(New);
+    end;
+  end;
+end;
+
 { TBottleLogDragObject }
 
 function TBottleLogDragObject.GetDragImages: TDragImageList;
@@ -1661,4 +1778,15 @@ begin
     end;
 end;
 
+procedure TfrmLog.mnPopupCopyGhostClick(Sender: TObject);
+var
+  Log: TLogItem;
+  Clip: TClipBoard;
+begin
+  Log := SelectedBottleLog.Bottles[frmLog.lvwLog.Selected.Index];
+  if Log = nil then Exit;
+  Clip := ClipBoard();
+  Clip.SetTextBuf(PChar(Log.Ghost));
+end;
+
 end.