OSDN Git Service

仮想リストビューに変更。
[tpi/lychee.git] / src / lychee / dlg_make.cpp
1 /*******************************************************************************\r
2   TPI - flexible but useless plug-in framework.\r
3   Copyright (C) 2002-2009 Silky\r
4 \r
5   This library is free software; you can redistribute it and/or modify it under\r
6   the terms of the GNU Lesser General Public License as published by the Free\r
7   Software Foundation; either version 2.1 of the License, or (at your option)\r
8   any later version.\r
9 \r
10   This library is distributed in the hope that it will be useful, but WITHOUT\r
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or \r
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r
13   for more details.\r
14 \r
15   You should have received a copy of the GNU Lesser General Public License along\r
16   with this library; if not, write to the Free Software Foundation, Inc.,\r
17   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
18 \r
19   $Id$\r
20 *******************************************************************************/\r
21 \r
22 #include "lychee.h"\r
23 \r
24 #include "dlg_make.h"\r
25 #include "frm_main.h"\r
26 #include "functions.h"\r
27 \r
28 #include <wx/dirdlg.h>\r
29 #include <wx/arrimpl.cpp>\r
30 \r
31 WX_DEFINE_OBJARRAY(ArrayTPI_FORMATINFO);\r
32 \r
33 //******************************************************************************\r
34 // MakeDialog\r
35 //******************************************************************************\r
36 \r
37 MakeDialog::MakeDialog(): wxDialog()\r
38 {\r
39         this->uCommand = TPI_COMMAND_CREATE;\r
40 }\r
41 \r
42 //******************************************************************************\r
43 // Event Table.\r
44 //******************************************************************************\r
45 \r
46 BEGIN_EVENT_TABLE(MakeDialog, wxDialog)\r
47         EVT_INIT_DIALOG(                 MakeDialog::OnInit)\r
48         EVT_BUTTON(XRCID("btnDefault"),  MakeDialog::OnBtnDefault)\r
49         EVT_BUTTON(XRCID("btnDesktop"),  MakeDialog::OnBtnDesktop)\r
50         EVT_BUTTON(XRCID("btnCurrent"),  MakeDialog::OnBtnCurrent)\r
51         EVT_BUTTON(XRCID("btnBrowse"),   MakeDialog::OnBtnBrowse)\r
52         EVT_BUTTON(XRCID("btnBrowseKF"), MakeDialog::OnBtnBrowseKF)\r
53         EVT_BUTTON(XRCID("btnOK"),       MakeDialog::OnBtnOK)\r
54         EVT_BUTTON(XRCID("btnCancel"),   MakeDialog::OnBtnCancel)\r
55         EVT_CHOICE(XRCID("chType"),      MakeDialog::OnChoice)\r
56         EVT_CHECKBOX(XRCID("cbUnmask"),  MakeDialog::OnCbUnmask)\r
57         EVT_CHECKBOX(XRCID("cbMakeSFX"), MakeDialog::OnCbMakeSFX)\r
58         EVT_NOTEBOOK_PAGE_CHANGED(XRCID("nbTabs"), MakeDialog::OnTabChanged)\r
59 END_EVENT_TABLE()\r
60 \r
61 //******************************************************************************\r
62 // Event handler.\r
63 //******************************************************************************\r
64 \r
65 void MakeDialog::OnInit(wxInitDialogEvent&)\r
66 {\r
67         // XRCと結びつけ。\r
68         // "General"タブ\r
69         this->cbDir             = XRCCTRL(* this, "cbDir",        wxComboBox);\r
70         this->cbFileName        = XRCCTRL(* this, "cbFileName",   wxComboBox);\r
71         this->cbOpenAfter       = XRCCTRL(* this, "cbOpenAfter",  wxCheckBox);\r
72         this->cbIgnorePath      = XRCCTRL(* this, "cbIgnorePath", wxCheckBox);\r
73         this->cbExitAfter       = XRCCTRL(* this, "cbExitAfter",  wxCheckBox);\r
74         this->chType            = XRCCTRL(* this, "chType",       wxChoice);\r
75         this->chDirMake         = XRCCTRL(* this, "chDirMake",    wxChoice);\r
76         // "Config"タブ\r
77         this->scLevel           = XRCCTRL(* this, "scLevel",      wxSpinCtrl);\r
78         this->scRR              = XRCCTRL(* this, "scRR",         wxSpinCtrl);\r
79         this->tcPassword        = XRCCTRL(* this, "tcPassword",   wxTextCtrl);\r
80         this->tcKeyfile         = XRCCTRL(* this, "tcKeyfile",    wxTextCtrl);\r
81         this->cbSplitSize       = XRCCTRL(* this, "cbSplitSize",  wxComboBox);\r
82         this->cbUnmask          = XRCCTRL(* this, "cbUnmask",     wxCheckBox);\r
83         this->cbEncryptHeader   = XRCCTRL(* this, "cbEncryptHeader", wxCheckBox);\r
84         this->cbSolid           = XRCCTRL(* this, "cbSolid",      wxCheckBox);\r
85         this->cbMMOptimize      = XRCCTRL(* this, "cbMMOptimize", wxCheckBox);\r
86         this->cbMakeSFX         = XRCCTRL(* this, "cbMakeSFX",    wxCheckBox);\r
87         // "Comment"タブ\r
88         this->tcComment         = XRCCTRL(* this, "tcComment",    wxTextCtrl);\r
89         // "Files"タブ\r
90         this->lcFiles           = XRCCTRL(* this, "lcFiles",      myListCtrl2);\r
91 \r
92         // 2回目以降は無視。\r
93         if (! this->cbDir->GetValue().IsEmpty())\r
94         {\r
95                 return;\r
96         }\r
97 \r
98         // ListCtrlに列を追加。\r
99         // wxGTKでは直接wxLC_VIRTUALを指定しないと反映されない。\r
100         this->lcFiles->SetSingleStyle(wxLC_VIRTUAL);\r
101         this->lcFiles->InsertColumn(0, _("Input"),  wxLIST_FORMAT_LEFT,  150);\r
102         this->lcFiles->InsertColumn(1, _("Output"), wxLIST_FORMAT_LEFT,  290);\r
103         this->lcFiles->asInput = this->files;\r
104         this->lcFiles->atDangerItem.SetTextColour(* wxRED);\r
105 \r
106         ::wxXmlResource::Get()->Unload(L_DIR_S_XRC wxT("dlg_make.xrc"));\r
107 \r
108         // 事前準備。\r
109         MainFrame * frm_main = (MainFrame *) this->GetParent();\r
110         wxString szArcPath = frm_main->fnArchive.GetPath(), szArcName = frm_main->fnArchive.GetName();\r
111 \r
112         // パス履歴読み込み。\r
113         for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_PATH); i++)\r
114         {\r
115                 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_PATH, i);\r
116                 if (sz.IsEmpty())\r
117                 {\r
118                         continue;\r
119                 }\r
120 \r
121                 this->cbDir->Append(sz);\r
122         }\r
123         // 書庫名履歴読み込み。\r
124         for (size_t i = 0; i < frm_main->conf.GetHistoryCount(CONF_HISTORY_NAME); i++)\r
125         {\r
126                 wxString sz = frm_main->conf.ReadHistory(CONF_HISTORY_NAME, i);\r
127                 if (sz.IsEmpty())\r
128                 {\r
129                         continue;\r
130                 }\r
131 \r
132                 this->cbFileName->Append(sz);\r
133         }\r
134 \r
135         // パスを設定。\r
136         this->cbDir->SetValue(szArcPath);\r
137 \r
138         // コマンド別の処理。\r
139         switch (this->uCommand)\r
140         {\r
141         case TPI_COMMAND_EXTRACT:\r
142                 // 初期値を設定。\r
143                 this->SetTitle(_("Extract"));\r
144                 this->tcComment->SetValue(frm_main->aiArchive.szComment);\r
145 \r
146                 // 展開先を予測。ただしDTVスキャンに時間がかかる場合はスキップ可能。\r
147                 if (this->lcFiles->asInput.GetCount() < 3000 || ::AskDlg(_("This archive contains so many files that it takes long to check Directory Traversal Vulnerability(DTV) problem. If you are sure this archive is safe, you can skip this scanning process. Do you want to scan for DTV problem?"), this) == wxYES)\r
148                 {\r
149                         wxNotebookEvent e;\r
150                         e.SetSelection(3);\r
151                         this->OnTabChanged(e);\r
152                 }\r
153 \r
154                 // コントロールを無効化。\r
155                 this->scLevel->Disable();\r
156                 this->scRR->Disable();\r
157                 this->cbEncryptHeader->Disable();\r
158                 this->cbSolid->Disable();\r
159                 this->cbMMOptimize->Disable();\r
160                 this->tcComment->SetEditable(false);\r
161         case TPI_COMMAND_ADD:\r
162                 // コントロールを無効化(展開時も)。\r
163                 this->cbFileName->Disable();\r
164                 this->chType->Disable();\r
165                 this->chDirMake->Enable();\r
166                 this->cbSplitSize->Disable();\r
167                 this->cbMakeSFX->Disable();\r
168 \r
169                 // 書庫名を設定。\r
170                 this->cbFileName->SetValue(szArcName);\r
171 \r
172                 // 書庫形式欄を設定。\r
173                 this->afInfo.Add(frm_main->aiArchive.fiInfo);\r
174                 this->chType->Append(frm_main->aiArchive.fiInfo.szTypeName);\r
175 \r
176                 // とりあえず最初の形式にしておく。\r
177                 this->chType->SetSelection(0);\r
178                 {\r
179                         wxCommandEvent e;\r
180                         e.SetInt(0);\r
181                         this->OnChoice(e);\r
182                 }\r
183 \r
184                 if (this->uCommand != TPI_COMMAND_ADD)\r
185                 {\r
186                         break;\r
187                 }\r
188                 this->SetTitle(_("Add"));\r
189 \r
190                 // コントロールを無効化(追加時のみ)。\r
191                 this->cbDir->Disable();\r
192                 this->chDirMake->Disable();\r
193                 break;\r
194         case TPI_COMMAND_CREATE:\r
195                 this->SetTitle(_("Create"));\r
196 \r
197                 // 書庫名を設定。初期化の都合上.を付加しておく。\r
198                 this->cbFileName->SetValue(szArcName + wxT('.'));\r
199 \r
200                 // ライブラリを検索。\r
201                 TPIHandle tpi;\r
202                 wxDir fs(L_DIR_B_LIB);\r
203                 wxString szTPIName;\r
204                 if (fs.GetFirst(& szTPIName,wxT("*" TPI_EXT)))\r
205                 {\r
206                         do\r
207                         {\r
208                                 // ロード。\r
209                                 wxString szLibName = L_DIR_B_LIB + szTPIName;\r
210                                 if (tpi.InitLibrary(szLibName, wxEmptyString, 0))\r
211                                 {\r
212                                         // 対応する形式名を取得。\r
213                                         TPI_FORMATINFO fiInfo;\r
214                                         if (tpi.GetFormatInformation(& fiInfo, true))\r
215                                         {\r
216                                                 do\r
217                                                 {\r
218                                                         if (fiInfo.eSupportedCommand & TPI_COMMAND_CREATE && (this->lcFiles->asInput.GetCount() == 1 || fiInfo.fArchive))\r
219                                                         {\r
220                                                                 fiInfo.szTPIName = szLibName;\r
221                                                                 this->afInfo.Add(fiInfo);\r
222                                                                 this->chType->Append(fiInfo.szTypeName);\r
223                                                         }\r
224                                                 }\r
225                                                 while (tpi.GetFormatInformation(& fiInfo, false));\r
226                                         }\r
227                                         tpi.FreeLibrary();\r
228                                 }\r
229                         }\r
230                         while (fs.GetNext(& szTPIName));\r
231                 }\r
232 \r
233                 if (this->chType->GetCount() == 0)\r
234                 {\r
235                         // 形式の候補が一つもない場合。\r
236                         XRCCTRL(* this, "btnOK", wxButton)->Disable();\r
237                         break;\r
238                 }\r
239 \r
240                 // とりあえず最初の形式にしておく。\r
241                 this->chType->SetSelection(0);\r
242                 wxCommandEvent e;\r
243                 e.SetInt(0);\r
244                 this->OnChoice(e);\r
245                 break;\r
246         }\r
247 }\r
248 \r
249 void MakeDialog::OnBtnDefault(wxCommandEvent&)\r
250 {\r
251         this->cbDir->SetValue(((MainFrame *) this->GetParent())->conf.ReadId(CONF_DEFAULT_PATH, (wxString) wxEmptyString));\r
252 }\r
253 \r
254 void MakeDialog::OnBtnDesktop(wxCommandEvent&)\r
255 {\r
256         wxFileName fn(wxFileName::GetHomeDir(), wxT("Desktop"));\r
257         this->cbDir->SetValue(fn.GetFullPath());\r
258 }\r
259 \r
260 void MakeDialog::OnBtnCurrent(wxCommandEvent&)\r
261 {\r
262         this->cbDir->SetValue(((MainFrame *) this->GetParent())->fnArchive.GetPath());\r
263 }\r
264 \r
265 void MakeDialog::OnBtnBrowse(wxCommandEvent&)\r
266 {\r
267         wxDirDialog dd(this);\r
268         dd.SetPath(this->cbDir->GetValue());\r
269         if (dd.ShowModal() == wxID_OK)\r
270         {\r
271                 this->cbDir->SetValue(dd.GetPath());\r
272         }\r
273 }\r
274 \r
275 void MakeDialog::OnBtnBrowseKF(wxCommandEvent&)\r
276 {\r
277         wxFileDialog fd(this);\r
278         fd.SetWindowStyleFlag(wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
279         if (fd.ShowModal() == wxID_OK)\r
280         {\r
281                 this->tcKeyfile->SetValue(fd.GetPath());\r
282         }\r
283 }\r
284 \r
285 void MakeDialog::OnBtnOK(wxCommandEvent&)\r
286 {\r
287         // 履歴書き込み。\r
288         if (this->uCommand != TPI_COMMAND_ADD)\r
289         {\r
290                 MainFrame * frm_main = (MainFrame *) this->GetParent();\r
291                 wxFileName fnCurrent(this->cbDir->GetValue(), this->uCommand == TPI_COMMAND_CREATE ? this->cbFileName->GetValue() : (wxString) wxEmptyString);\r
292                 frm_main->conf.WriteHistory(CONF_HISTORY_FULL, fnCurrent.GetFullPath());\r
293                 frm_main->conf.WriteHistory(CONF_HISTORY_PATH, fnCurrent.GetPath());\r
294                 frm_main->conf.WriteHistory(CONF_HISTORY_NAME, fnCurrent.GetFullName());\r
295         }\r
296         this->EndModal(wxID_OK);\r
297 }\r
298 \r
299 void MakeDialog::OnBtnCancel(wxCommandEvent&)\r
300 {\r
301         this->EndModal(wxID_CANCEL);\r
302 }\r
303 \r
304 void MakeDialog::OnChoice(wxCommandEvent& e)\r
305 {\r
306         TPI_FORMATINFO * fiInfo = & this->afInfo[e.GetInt()];\r
307         // 形式が各種設定に対応しているか。\r
308         // 作成時/追加時/展開時設定。\r
309         this->tcPassword->Enable(fiInfo->fEncryptPassword);\r
310         this->cbUnmask->Enable(fiInfo->fEncryptPassword);\r
311         this->tcKeyfile->Enable(fiInfo->fEncryptKeyFile);\r
312         if (this->uCommand == TPI_COMMAND_EXTRACT)\r
313         {\r
314                 return;\r
315         }\r
316 \r
317         // 作成時/追加時設定。\r
318         this->scLevel->SetRange(fiInfo->nCompressLevelMin, fiInfo->nCompressLevelMax);\r
319         this->scLevel->SetValue(fiInfo->nCompressLevelMax);\r
320         this->scLevel->Enable(fiInfo->nCompressLevelMin != fiInfo->nCompressLevelMax);\r
321         this->scRR->SetRange(fiInfo->nRecoveryRecordMin, fiInfo->nRecoveryRecordMax);\r
322         this->scRR->SetValue(fiInfo->nRecoveryRecordMin);\r
323         this->scRR->Enable(fiInfo->nRecoveryRecordMin != fiInfo->nRecoveryRecordMax);\r
324         this->cbEncryptHeader->Enable(fiInfo->fEncryptHeader);\r
325         this->cbSolid->Enable(fiInfo->fSolid);\r
326         this->cbMMOptimize->Enable(fiInfo->fMMOptimize);\r
327         this->tcComment->Enable(fiInfo->fComment);\r
328         if (this->uCommand == TPI_COMMAND_ADD)\r
329         {\r
330                 return;\r
331         }\r
332 \r
333         // 作成時設定。\r
334         this->cbSplitSize->Enable(fiInfo->fMultiVolume);\r
335         this->cbMakeSFX->Enable(fiInfo->fSFX);\r
336 \r
337         wxFileName fn(this->cbFileName->GetValue());\r
338         fn.SetExt(this->cbMakeSFX->IsEnabled() && this->cbMakeSFX->IsChecked() ? EXE_EXT : fiInfo->szSuffix.BeforeFirst(wxT(';')));\r
339         this->cbFileName->SetValue(fn.GetFullName());\r
340 }\r
341 \r
342 void MakeDialog::OnCbUnmask(wxCommandEvent&)\r
343 {\r
344         this->tcPassword->SetWindowStyle(this->tcPassword->GetWindowStyle() & (this->cbUnmask->IsChecked() ? ~ wxTE_PASSWORD : wxTE_PASSWORD));\r
345         this->tcPassword->Refresh();\r
346 }\r
347 \r
348 void MakeDialog::OnCbMakeSFX(wxCommandEvent&)\r
349 {\r
350         wxFileName fn(this->cbFileName->GetValue());\r
351         fn.SetExt(this->cbMakeSFX->IsChecked() ? EXE_EXT : this->afInfo[this->chType->GetSelection()].szSuffix.BeforeFirst(wxT(';')));\r
352         this->cbFileName->SetValue(fn.GetFullName());\r
353 }\r
354 \r
355 void MakeDialog::OnTabChanged(wxNotebookEvent& e)\r
356 {\r
357         // "Files"タブのときは処理。\r
358         if (e.GetSelection() != 3)\r
359         {\r
360                 return;\r
361         }\r
362         this->lcFiles->DeleteAllItems();\r
363         this->lcFiles->asOutput.Clear();\r
364         this->lcFiles->apItem.Clear();\r
365 \r
366         switch (this->uCommand)\r
367         {\r
368         case TPI_COMMAND_EXTRACT:\r
369         {\r
370                 // ファイルの出力先を推測。\r
371                 wxString szOutputRootDir = WillMakeDirByArcName((MainFrame *) this->GetParent(), this) ? MakeDirPath(wxFileName::DirName(this->cbDir->GetValue()), wxFileName(this->cbFileName->GetValue()).GetName(), false).GetPath() : this->cbDir->GetValue();\r
372 \r
373                 // 各ファイルにパスを付加。\r
374                 bool fDTVWarning = false;\r
375                 for (size_t i = 0; i < this->lcFiles->asInput.GetCount(); i++)\r
376                 {\r
377                         wxString szOutputFile = szOutputRootDir + wxFileName::GetPathSeparator();\r
378                         wxFileName fnStored(this->lcFiles->asInput[i]);\r
379                         if (! this->cbIgnorePath->IsChecked())\r
380                         {\r
381                                 szOutputFile += fnStored.GetPathWithSep();\r
382                         }\r
383                         wxFileName fnOutput(szOutputFile + fnStored.GetFullName());\r
384                         if (! fnOutput.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG) || ! fnOutput.GetFullPath().StartsWith(szOutputRootDir))\r
385                         {\r
386                                 fDTVWarning = true;\r
387                                 this->lcFiles->apItem.Add(& this->lcFiles->atDangerItem);\r
388                         }\r
389                         else\r
390                         {\r
391                                 this->lcFiles->apItem.Add(NULL);\r
392                         }\r
393                         this->lcFiles->asOutput.Add(fnOutput.GetFullPath());\r
394                 }\r
395 \r
396                 if (fDTVWarning && ::AskDlg(_("This archive may have Directory Traversal Vulnerability(DTV) problem, and some danger files may be extracted to the unexpected system directory! It is strongly recommended to ignore file path. Would you like to do so?"), this) == wxYES)\r
397                 {\r
398                         this->cbIgnorePath->SetValue(true);\r
399                         this->OnTabChanged(e);\r
400                 }\r
401                 break;\r
402         }\r
403         case TPI_COMMAND_ADD:\r
404         case TPI_COMMAND_CREATE:\r
405                 // TODO : 格納パスを推測。\r
406                 this->lcFiles->asOutput = this->lcFiles->asInput;\r
407                 this->lcFiles->apItem.SetCount(this->lcFiles->asInput.GetCount(), NULL);\r
408                 break;\r
409         }\r
410 \r
411         // リストビューに表示。\r
412         this->lcFiles->SetItemCount(this->lcFiles->asInput.GetCount());\r
413 }\r
414 \r
415 //******************************************************************************\r
416 // myListCtrl2\r
417 //******************************************************************************\r
418 \r
419 IMPLEMENT_DYNAMIC_CLASS(myListCtrl2, wxListView)\r
420 \r
421 //******************************************************************************\r
422 // Event handler.\r
423 //******************************************************************************\r
424 wxString myListCtrl2::OnGetItemText(long i, long column) const\r
425 {\r
426         // リストビューに項目を追加。\r
427         switch (column)\r
428         {\r
429         case 0:\r
430                 return this->asInput[i];\r
431         case 1:\r
432                 return this->asOutput[i];\r
433         default:\r
434                 return wxEmptyString;\r
435         }\r
436 }\r
437 \r
438 wxListItemAttr * myListCtrl2::OnGetItemAttr(long i) const\r
439 {\r
440         return (wxListItemAttr *) this->apItem[i];\r
441 }\r