OSDN Git Service

C++11のrange-based forを用いて書き直し。
[tpi/lychee.git] / src / lychee / dlg_process.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 #include "dlg_process.h"\r
24 #include "dlg_make.h"\r
25 #include "frm_main.h"\r
26 #include "functions.h"\r
27 \r
28 ProcessDialog * g_procDlg = NULL;\r
29 \r
30 //******************************************************************************\r
31 // ProcessDialog\r
32 //******************************************************************************\r
33 \r
34 ProcessDialog::ProcessDialog(wxWindow * parent, wxULongLong_t n, wxString szPassword): wxDialog(), nFileCount(n), szPassword(szPassword), fOpen(false)\r
35 {\r
36         ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_process.xrc"));\r
37         ::wxXmlResource::Get()->LoadDialog(this, this->GetParent(), wxT("dlg_process"));\r
38         g_procDlg = this;\r
39         this->hParent = parent;\r
40         this->InitDialog();\r
41 }\r
42 \r
43 ProcessDialog::~ProcessDialog()\r
44 {\r
45         // ウインドウの機能を有効化。\r
46         MainFrame * frm_main = (MainFrame *) this->hParent;\r
47         frm_main->tree_ctrl->Thaw();\r
48         frm_main->list_ctrl->Thaw();\r
49         frm_main->menubar->EnableTop(0, true);\r
50         frm_main->menubar->EnableTop(1, true);\r
51         frm_main->menubar->EnableTop(2, true);\r
52         frm_main->toolbar->Enable();\r
53 \r
54         // 書庫を開く途中に中断した場合、書庫を閉じる処理を行う。\r
55         if (this->fOpen && this->fCancel)\r
56         {\r
57                 wxCommandEvent e;\r
58                 frm_main->OnArcClose(e);\r
59         }\r
60 \r
61 #ifdef __WINDOWS__\r
62         if (this->tlTaskbar != NULL)\r
63         {\r
64                 this->tlTaskbar->SetProgressState(this->hTBWnd, TBPF_NOPROGRESS);\r
65                 this->tlTaskbar->Release();\r
66         }\r
67 #endif\r
68         ((MainFrame *) this->hParent)->gFrame->Show(false);\r
69         g_procDlg = NULL;\r
70 }\r
71 \r
72 //******************************************************************************\r
73 // Event table.\r
74 //******************************************************************************\r
75 \r
76 BEGIN_EVENT_TABLE(ProcessDialog, wxDialog)\r
77         EVT_INIT_DIALOG(ProcessDialog::OnInit)\r
78         EVT_CLOSE(ProcessDialog::OnClose)\r
79 END_EVENT_TABLE()\r
80 \r
81 //******************************************************************************\r
82 // Event handler.\r
83 //******************************************************************************\r
84 \r
85 void ProcessDialog::OnInit(wxInitDialogEvent &)\r
86 {\r
87         if (this->nOverwriteMode == wxID_OK)\r
88         {\r
89                 // 2回目以降は何もせず終了。\r
90                 return;\r
91         }\r
92 \r
93         // XRCと結びつけ。\r
94         this->ebTarget          = XRCCTRL(* this, "ebTarget",     wxTextCtrl);\r
95         this->ebSource          = XRCCTRL(* this, "ebSource",     wxTextCtrl);\r
96         this->gFile             = XRCCTRL(* this, "gFile",        wxGauge);\r
97         this->gArchive          = XRCCTRL(* this, "gArchive",     wxGauge);\r
98         this->fCancel           = false;\r
99         this->nOverwriteMode    = wxID_OK;\r
100         ::wxXmlResource::Get()->Unload(L_DIR_S_XRC wxT("dlg_process.xrc"));\r
101 \r
102         // コールバックを送信。\r
103         TPI_PROCESSINFO piInfo;\r
104         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
105         piInfo.eStatus = 0x1000;\r
106         piInfo.fiInfo.fnFileName = ((MainFrame *) this->hParent)->fnArchive;\r
107         piInfo.fiInfo.nUnpackedSize = this->nFileCount;\r
108         this->CallbackProc(TPI_NOTIFY_COMMON, & piInfo);\r
109 \r
110         if (((MainFrame *) this->hParent)->conf.ReadId(CONF_PROCESS_DLG, false))\r
111         {\r
112                 // 旧来の進捗ダイアログを表示。\r
113                 // ここでOnInitが呼ばれるので、OnInitの最初で無効化している。\r
114                 this->Show();\r
115         }\r
116 \r
117         // ウインドウの機能を無効化。\r
118         MainFrame * frm_main = (MainFrame *) this->hParent;\r
119         frm_main->tree_ctrl->Freeze();\r
120         frm_main->list_ctrl->Freeze();\r
121         frm_main->menubar->EnableTop(0, false);\r
122         frm_main->menubar->EnableTop(1, false);\r
123         frm_main->menubar->EnableTop(2, false);\r
124         frm_main->toolbar->Enable(false);\r
125 #ifdef __WINDOWS__\r
126         // タスクバー。\r
127         this->hTBWnd = this->hParent->GetHandle();\r
128 \r
129         ::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **) & this->tlTaskbar);\r
130         if (this->tlTaskbar != NULL)\r
131         {\r
132                 this->tlTaskbar->HrInit();\r
133         }\r
134 #endif\r
135 }\r
136 \r
137 void ProcessDialog::OnClose(wxCloseEvent & e)\r
138 {\r
139         if (e.CanVeto() && AskDlg(_("Really do you want to cancel this operation?"), this) == wxYES)\r
140         {\r
141                 this->fCancel = true;\r
142         }\r
143         e.Veto();\r
144 }\r
145 \r
146 int ProcessDialog::CallbackProc(unsigned int _uMsg, void * _pStructure)\r
147 {\r
148         if (_uMsg != TPI_NOTIFY_COMMON)\r
149         {\r
150                 return TPI_CALLBACK_UNSUPPORTED;\r
151         }\r
152 \r
153         TPI_PROCESSINFO * piInfo = (TPI_PROCESSINFO *) _pStructure;\r
154         if (piInfo == NULL)\r
155         {\r
156                 return TPI_CALLBACK_CONTINUE;\r
157         }\r
158 \r
159         switch (piInfo->eMessage)\r
160         {\r
161         case TPI_MESSAGE_STATUS:\r
162         {\r
163                 static int s_nProcess;\r
164 #ifdef __WINDOWS__\r
165                 static int s_nFileCount;\r
166 #endif\r
167                 static wxStopWatch sw;\r
168                 switch (piInfo->eStatus)\r
169                 {\r
170                 case TPI_STATUS_OPENARCHIVE:\r
171                         this->ebSource->ChangeValue(piInfo->fiInfo.fnFileName.GetFullPath());\r
172                         sw.Start();\r
173                         break;\r
174                 case TPI_STATUS_BEGINPROCESS:\r
175                         if (piInfo->fiInfo.nUnpackedSize > 10000)\r
176                         {\r
177                                 this->gFile->SetRange(piInfo->fiInfo.nUnpackedSize);\r
178                         }\r
179                 case TPI_STATUS_INPROCESS:\r
180                         if (sw.Time() > 500)\r
181                         {\r
182                                 if (this->IsShownOnScreen())\r
183                                 {\r
184                                         sw.Start();\r
185                                         this->ebSource->ChangeValue(piInfo->fiInfo.fnFileName.GetFullPath());\r
186                                         this->ebTarget->ChangeValue(piInfo->fnDestination.GetFullPath());\r
187                                         if (piInfo->fiInfo.nUnpackedSize > 10000)\r
188                                         {\r
189                                                 this->gFile->SetValue(piInfo->nProcessedSize);\r
190                                         }\r
191                                         this->gArchive->SetValue(s_nProcess);\r
192                                         this->Update();\r
193                                         ::wxSafeYield(this, true);\r
194                                 }\r
195                                 else\r
196                                 {\r
197                                         ::wxSafeYield(this->hParent, true);\r
198                                 }\r
199                                 ((MainFrame *) this->hParent)->gFrame->SetValue(s_nProcess);\r
200                         }\r
201 #ifdef __WINDOWS__\r
202                         if (this->tlTaskbar != NULL)\r
203                         {\r
204                                 this->tlTaskbar->SetProgressValue(this->hTBWnd, s_nProcess, s_nFileCount);\r
205                         }\r
206 #endif\r
207                         break;\r
208                 case TPI_STATUS_ENDPROCESS:\r
209                         s_nProcess++;\r
210                         break;\r
211                 // Lycheeの独自仕様。\r
212                 case 0x1000: // 初期設定。\r
213                         this->ebSource->ChangeValue(piInfo->fiInfo.fnFileName.GetFullPath());\r
214                         this->Update();\r
215                         ((MainFrame *) this->hParent)->gFrame->Show();\r
216                         ::wxSafeYield(this->hParent, true);\r
217                 case 0x1001: // 閲覧時は最初にファイル数が分からないので、ここで設定。\r
218                         this->gArchive->SetRange(piInfo->fiInfo.nUnpackedSize);\r
219                         ((MainFrame *) this->hParent)->gFrame->SetRange(piInfo->fiInfo.nUnpackedSize);\r
220                         s_nProcess = 0;\r
221 #ifdef __WINDOWS__\r
222                         s_nFileCount = piInfo->fiInfo.nUnpackedSize;\r
223 #endif\r
224 //                      sw.Start();\r
225                         if (piInfo->eStatus == 0x1001)\r
226                         {\r
227                                 this->fOpen = true;\r
228                         }\r
229                         break;\r
230                 case 0x1002: // 各ファイルの処理を開始。\r
231 //                      if (sw.Time() > 500)\r
232                         {\r
233                                 if (this->IsShownOnScreen())\r
234                                 {\r
235 //                                      sw.Start();\r
236                                         this->ebTarget->ChangeValue(piInfo->fiInfo.fnFileName.GetFullPath());\r
237                                         this->gArchive->SetValue(piInfo->nProcessedSize);\r
238                                         this->Update();\r
239 //                                      ::wxSafeYield(this, true);\r
240                                 }\r
241 //                              ::wxSafeYield(this->hParent, true);\r
242                         }\r
243                         ((MainFrame *) this->hParent)->gFrame->SetValue(piInfo->nProcessedSize);\r
244 #ifdef __WINDOWS__\r
245                         if (this->tlTaskbar != NULL)\r
246                         {\r
247                                 this->tlTaskbar->SetProgressValue(this->hTBWnd, piInfo->nProcessedSize, s_nFileCount);\r
248                         }\r
249 #endif\r
250                         break;\r
251                 }\r
252                 break;\r
253         }\r
254         case TPI_MESSAGE_ASK:\r
255         {\r
256 #ifdef __WINDOWS__\r
257                 if (this->tlTaskbar != NULL)\r
258                 {\r
259                         this->tlTaskbar->SetProgressState(this->hTBWnd, TBPF_PAUSED);\r
260                 }\r
261 #endif\r
262                 switch (piInfo->eStatus)\r
263                 {\r
264                 case TPI_PARAM_PASSWORD:\r
265                 {\r
266                         if (piInfo->fiInfo.fnFileName == fnFormer || this->szPassword.IsEmpty())\r
267                         {\r
268                                 piInfo->szParam = ::wxGetPasswordFromUser(_("Password for:\n") + piInfo->fiInfo.fnFileName.GetFullPath(), wxT("Lychee"), wxEmptyString, this);\r
269                                 if (piInfo->szParam.IsEmpty())\r
270                                 {\r
271                                         this->fCancel = true;\r
272                                 }\r
273                                 this->szPassword = piInfo->szParam;\r
274                         }\r
275                         else\r
276                         {\r
277                                 piInfo->szParam = this->szPassword;\r
278                                 fnFormer = piInfo->fiInfo.fnFileName;\r
279                         }\r
280                         break;\r
281                 }\r
282                 case TPI_PARAM_NEXTVOLUME:\r
283                 {\r
284                         wxFileDialog fd(this, _("Choose next volume of: ") + piInfo->fiInfo.fnFileName.GetFullName(), piInfo->fiInfo.fnFileName.GetPath(), wxEmptyString, wxFileSelectorDefaultWildcardStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST);\r
285                         if (fd.ShowModal() == wxID_CANCEL)\r
286                         {\r
287                                 this->fCancel = true;\r
288                         }\r
289                         piInfo->szParam = fd.GetPath();\r
290                         break;\r
291                 }\r
292                 case TPI_PARAM_DEST:\r
293                         if (piInfo->fnDestination.FileExists() || ::wxDirExists(piInfo->fnDestination.GetFullPath()))\r
294                         {\r
295                                 // 上書き確認を行う。\r
296                                 bool bPerm = false;\r
297                                 if (this->nOverwriteMode == wxID_OK)\r
298                                 {\r
299                                         OverwriteDialog odDlg;\r
300                                         odDlg.fnExist = & piInfo->fnDestination;\r
301                                         odDlg.tmWrite = & piInfo->fiInfo.tmModify;\r
302                                         odDlg.nWriteSize = piInfo->fiInfo.nUnpackedSize;\r
303 \r
304                                         this->nOverwriteMode = odDlg.ShowModal();\r
305                                         bPerm = odDlg.cbApplyAll->IsChecked();\r
306                                 }\r
307                                 else\r
308                                 {\r
309                                         bPerm = true;\r
310                                 }\r
311                                 switch (this->nOverwriteMode)\r
312                                 {\r
313                                 case wxID_CANCEL:\r
314                                         this->fCancel = true;\r
315                                         break;\r
316                                 case 0:\r
317                                         // 自動上書き。既存のファイルを削除しておく。\r
318                                         if (piInfo->fnDestination.FileExists())\r
319                                         {\r
320                                                 ::wxRemoveFile(piInfo->fnDestination.GetFullPath());\r
321                                         }\r
322                                         else if (::wxDirExists(piInfo->fnDestination.GetFullPath()))\r
323                                         {\r
324                                                 // TODO: 再帰削除。\r
325                                                 ::wxRmdir(piInfo->fnDestination.GetFullPath());\r
326                                         }\r
327                                         break;\r
328                                 case 1:\r
329                                         // 自動スキップ。\r
330                                         piInfo->fnDestination.Clear();\r
331                                         break;\r
332                                 case 2:\r
333                                         // 自動リネーム。\r
334                                         break;\r
335                                 }\r
336                                 if (! bPerm)\r
337                                 {\r
338                                         this->nOverwriteMode = wxID_OK;\r
339                                 }\r
340                         }\r
341                         break;\r
342                 default:\r
343                         return TPI_CALLBACK_UNSUPPORTED;\r
344                 }\r
345 #ifdef __WINDOWS__\r
346                 if (this->tlTaskbar != NULL)\r
347                 {\r
348                         this->tlTaskbar->SetProgressState(this->hTBWnd, TBPF_NORMAL);\r
349                 }\r
350 #endif\r
351                 break;\r
352         }\r
353         default:\r
354                 return TPI_CALLBACK_UNSUPPORTED;\r
355         }\r
356 \r
357         return this->fCancel ? TPI_CALLBACK_CANCEL : TPI_CALLBACK_CONTINUE;\r
358 }\r
359 //******************************************************************************\r
360 // OverwriteDialog\r
361 //******************************************************************************\r
362 \r
363 OverwriteDialog::OverwriteDialog(): wxDialog()\r
364 {\r
365         ::wxXmlResource::Get()->Load(L_DIR_S_XRC wxT("dlg_overwrite.xrc"));\r
366         ::wxXmlResource::Get()->LoadDialog(this, this->GetParent(), wxT("dlg_overwrite"));      \r
367 }\r
368 \r
369 //******************************************************************************\r
370 // Event table.\r
371 //******************************************************************************\r
372 \r
373 BEGIN_EVENT_TABLE(OverwriteDialog, wxDialog)\r
374         EVT_INIT_DIALOG(OverwriteDialog::OnInit)\r
375         EVT_BUTTON(XRCID("btnOverwrite"), OverwriteDialog::OnBtnOverwrite)\r
376         EVT_BUTTON(XRCID("btnSkip"), OverwriteDialog::OnBtnSkip)\r
377         EVT_BUTTON(XRCID("btnAuto"), OverwriteDialog::OnBtnAuto)\r
378         EVT_BUTTON(XRCID("btnBrowse"), OverwriteDialog::OnBtnBrowse)\r
379         EVT_CLOSE(OverwriteDialog::OnClose)\r
380 END_EVENT_TABLE()\r
381 \r
382 //******************************************************************************\r
383 // Event handler.\r
384 //******************************************************************************\r
385 \r
386 void OverwriteDialog::OnInit(wxInitDialogEvent &)\r
387 {\r
388         // XRCと結びつけ。\r
389         this->ebTarget          = XRCCTRL(* this, "ebTarget",     wxTextCtrl);\r
390         this->cbApplyAll        = XRCCTRL(* this, "cbApplyAll",   wxCheckBox);\r
391         ::wxXmlResource::Get()->Unload(L_DIR_S_XRC wxT("dlg_overwrite.xrc"));\r
392 \r
393         // ファイル情報を設定。\r
394         this->ebTarget->SetValue(this->fnExist->GetFullPath());\r
395         XRCCTRL(* this, "stExistTime", wxStaticText)->SetLabel(this->fnExist->GetModificationTime().Format(_("%Y/%m/%d %H:%M:%S modified, ")));\r
396         XRCCTRL(* this, "stExistSize", wxStaticText)->SetLabel(this->fnExist->GetHumanReadableSize());\r
397         XRCCTRL(* this, "stWriteTime", wxStaticText)->SetLabel(this->tmWrite->Format(_("%Y/%m/%d %H:%M:%S modified, ")));\r
398         XRCCTRL(* this, "stWriteSize", wxStaticText)->SetLabel(wxFileName::GetHumanReadableSize((wxULongLong) this->nWriteSize));\r
399         XRCCTRL(* this, "sbIcon", wxStaticBitmap)->SetIcon(GetFileTypeIcon(* this->fnExist));\r
400 }\r
401 \r
402 void OverwriteDialog::OnClose(wxCloseEvent & e)\r
403 {\r
404         if (e.CanVeto() && AskDlg(_("Really do you want to cancel this operation?"), this) == wxYES)\r
405         {\r
406                 this->EndModal(wxID_CANCEL);\r
407         }\r
408         e.Veto();\r
409 }\r
410 \r
411 void OverwriteDialog::OnBtnOverwrite(wxCommandEvent&)\r
412 {\r
413         if (this->fnExist->GetFullPath() != this->ebTarget->GetValue())\r
414         {\r
415                 // 保存先を変えているので、次回もダイアログを表示。\r
416                 this->cbApplyAll->SetValue(false);\r
417                 * this->fnExist = wxFileName(this->ebTarget->GetValue());\r
418         }\r
419         this->EndModal(0);\r
420 }\r
421 \r
422 void OverwriteDialog::OnBtnSkip(wxCommandEvent&)\r
423 {\r
424         this->EndModal(1);\r
425 }\r
426 \r
427 void OverwriteDialog::OnBtnAuto(wxCommandEvent&)\r
428 {\r
429         this->EndModal(2);\r
430 }\r
431 \r
432 void OverwriteDialog::OnBtnBrowse(wxCommandEvent&)\r
433 {\r
434         wxFileName fn(this->ebTarget->GetValue());\r
435         wxFileDialog fd(this, _("Choose a file"), fn.GetPath(), fn.GetFullName(), wxFileSelectorDefaultWildcardStr, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);\r
436         if (fd.ShowModal() == wxID_OK)\r
437         {\r
438                 this->ebTarget->SetValue(fd.GetPath());\r
439         }\r
440 }\r
441 \r
442 //******************************************************************************\r
443 //    ダイアログプロシージャ\r
444 //******************************************************************************\r
445 \r
446 int __stdcall TPICallbackProc(unsigned int _uMsg, void * _pStructure)\r
447 {\r
448         return g_procDlg == NULL ? TPI_CALLBACK_CONTINUE : g_procDlg->CallbackProc(_uMsg, _pStructure);\r
449 }\r