NCBI C++ ToolKit
project_task.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: project_task.cpp 47464 2023-04-20 00:19:10Z evgeniev $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Andrey Yazhuk
27  *
28  */
29 
30 #include <ncbi_pch.hpp>
31 
33 
35 
37 #include <gui/core/document.hpp>
39 #include <gui/core/save_dlg.hpp>
41 
45 
49 
52 
53 #include <serial/iterator.hpp>
54 
55 #include <wx/filedlg.h>
56 #include <wx/msgdlg.h>
57 #include <wx/filename.h>
58 
60 
62 
63 
66 
67 CProjectTask::CProjectTask(IServiceLocator* srv_locator, vector<wxString>& filenames)
69  m_SrvLocator(srv_locator)
70 {
71  _ASSERT(!filenames.empty());
73 }
74 
76 {
79  CGBDocument* doc = dynamic_cast<CGBDocument*>(ws.GetProjectFromId(*it));
80  if (!doc) continue;
81 
82  if (doc->IsDirty()) {
83  unsaved.push_back(*it);
84  continue;
85  }
86 
87  wxString path = doc->GetFileName();
88  if (!path.empty() && !wxFileName::FileExists(path))
89  unsaved.push_back(*it);
90  }
91  return unsaved;
92 }
93 
94 void CProjectTask::UnLoadProjects(IServiceLocator* serviceLocator, const TProjectIdVector& project_ids)
95 {
96  CProjectService* service = serviceLocator->GetServiceByType<CProjectService>().GetPointer();
97 
98  CRef<CGBWorkspace> ws = service->GetGBWorkspace();
99  if (!ws) return;
100 
101  TProjectIdVector toUnload(project_ids.begin(), project_ids.end());
102 
103  // collect selected projects that need to be saved
104  TProjectIdVector unsaved = s_GetUnsavedProjects(*ws, toUnload);
105 
106  bool ok = true;
107  if (!unsaved.empty()) {
108  // select all
109  TProjectIdVector selected;
110  for (size_t i = 0; i < unsaved.size(); i++)
111  selected.push_back(i);
112 
113  // ask user about unsaved projects and saved selected
114  ok = x_DoSaveUserSelected(service, *ws, "Unload Project",
115  "There are new or modified projects. "
116  "If not saved the new projects will be lost and the modified "
117  "projects will loose all changes. Would you like to save the selected projects?",
118  false, true, unsaved, selected);
119  }
120  // now unload (remove) the projects
121  if (ok) {
122  ITERATE(TProjectIdVector, it, toUnload) {
123  CRef<CGBDocument> doc(dynamic_cast<CGBDocument*>(ws->GetProjectFromId(*it)));
124  if (!doc) continue;
125 
126  if (doc->IsLoading()) {
127  doc->CancelLoading();
128  }
129  else if (doc->IsLoaded()) {
130  doc->UnloadProject(true);
131  if (doc->GetFilename().empty()) { // the user refused to save - remove it completely
132  service->RemoveProject(*doc);
133  }
134  }
135  }
136  }
137 }
138 
139 void CProjectTask::LoadProjects(IServiceLocator* serviceLocator, const TProjectIdVector& project_ids)
140 {
141  CProjectService* service = serviceLocator->GetServiceByType<CProjectService>().GetPointer();
142  CRef<CGBWorkspace> ws = service->GetGBWorkspace();
143  if (!ws) return;
144 
145  CIRef<CAppTaskService> task_srv = serviceLocator->GetServiceByType<CAppTaskService>();
146  _ASSERT(task_srv);
147 
148  ITERATE(TProjectIdVector, it, project_ids) {
150  task(new CProjectLoadingTask(*it, service, false));
151  task_srv->AddTask(*task);
152  }
153 }
154 
155 bool CProjectTask::RemoveProjects(IServiceLocator* serviceLocator, const TProjectIdVector& project_ids, bool confirm)
156 {
157  CProjectService* service = serviceLocator->GetServiceByType<CProjectService>().GetPointer();
158 
159  CRef<CGBWorkspace> ws = service->GetGBWorkspace();
160  if (!ws) return true;
161 
162  TProjectIdVector toRemove;
163  copy(project_ids.begin(), project_ids.end(), back_inserter(toRemove));
164 
165  // collect selected projects that need to be saved
166  TProjectIdVector unsaved = s_GetUnsavedProjects(*ws, toRemove);
167 
168  bool ok = true;
169  if (!unsaved.empty()) {
170  // select all
171  TProjectIdVector selected;
172  for (size_t i = 0; i < unsaved.size(); i++)
173  selected.push_back(i);
174 
175  // ask user about unsaved projects and saved selected
176  ok = x_DoSaveUserSelected(service, *ws, "Remove - Save changed projects",
177  "These projects are new or modified, "
178  "all changes will be lost if these projects are not saved. Would you "
179  "like to save the selected projects?",
180  false, true, unsaved, selected);
181  }
182  else if (confirm) {
183  // simply warn that projects will be removed
184  int res = wxMessageBox(wxT("Remove selected projects?"), wxT("Remove Project"),
185  wxYES_NO | wxICON_QUESTION);
186  ok = (res == wxYES);
187  }
188 
189  // now remove all projects
190  if (ok && !toRemove.empty()) {
191  ITERATE(TProjectIdVector, it, toRemove) {
192  CRef<CGBDocument> doc(dynamic_cast<CGBDocument*>(ws->GetProjectFromId(*it)));
193  if (!doc) continue;
194  if (doc->IsLoading())
195  doc->CancelLoading();
196  service->RemoveProject(*doc);
197  }
198 
199  for (CTypeIterator<CGBProjectHandle> it(ws->SetWorkspace()); it; ++it) {
200  CGBDocument* doc = dynamic_cast<CGBDocument*>(&*it);
201  if (!doc) continue;
202  return ok;
203  }
204 
206  }
207  return ok;
208 }
209 
211 {
212  CProjectService* service = serviceLocator->GetServiceByType<CProjectService>().GetPointer();
213  CRef<CGBWorkspace> ws = service->GetGBWorkspace();
214  if (!ws) return true;
215 
216  TProjectIdVector projects;
217  for (CTypeIterator<CGBProjectHandle> it(ws->SetWorkspace()); it; ++it) {
218  CGBDocument* doc = dynamic_cast<CGBDocument*>(&*it);
219  if (!doc) continue;
220  projects.push_back(doc->GetId());
221  }
222 
223  if (RemoveProjects(serviceLocator, projects, false)) {
225  return true;
226  }
227 
228  return false;
229 }
230 
231 
232 void CProjectTask::Save(IServiceLocator* serviceLocator, const TProjectIdVector& project_ids, bool save_as)
233 {
234  CProjectService* service = serviceLocator->GetServiceByType<CProjectService>().GetPointer();
235 
236  CRef<CGBWorkspace> ws = service->GetGBWorkspace();
237  if (!ws) return;
238 
239  TProjectIdVector loaded, selected;
240 
241  for (CTypeConstIterator<CGBProjectHandle> it(ws->GetWorkspace()); it; ++it) {
242  const CGBDocument* doc = dynamic_cast<const CGBDocument*>(&*it);
243  if (!doc) continue;
244  else if (doc->IsLoaded()) {
245  auto id = doc->GetId();
246  loaded.push_back(id);
247 
248  for (size_t j = 0; j < project_ids.size(); j++) {
249  if (project_ids[j] == id)
250  selected.push_back(loaded.size() - 1);
251  }
252  }
253  }
254 
255  string title = save_as ? "Save As" : "Save";
256 
257  // ask user about unsaved projects and save them
258  x_DoSaveUserSelected(service, *ws, title, "", save_as, false,
259  loaded, selected);
260 
261 }
262 
264 {
265 }
266 
268 {
269  x_OpenProjects();
270  return eCompleted;
271 }
272 
274 {
275  CProjectService* service = m_SrvLocator->GetServiceByType<CProjectService>().GetPointer();
276 
277  if (!service->HasWorkspace())
278  service->CreateNewWorkspace();
279 
280  CRef<CGBWorkspace> ws = service->GetGBWorkspace();
281  if (!ws) return;
282 
283  CWorkspaceFolder& root_folder = ws->SetWorkspace();
284 
285  TProjectIdVector ids;
286  for( size_t i = 0; i < m_ProjectFilenames.size(); i++ ) {
287  wxString filename = m_ProjectFilenames[i];
288  if (root_folder.FindProjectByFilename(FnToStdString(filename))) {
289  wxString msg = wxString::Format(
290  wxT("Project \"%s\" is already opened."), filename.c_str());
291  wxMessageBox(msg, wxT("Open Project"), wxOK | wxICON_EXCLAMATION);
292  } else {
293  CRef<CGBDocument> doc(new CGBDocument(service));
294  doc->SetFileName(filename);
295  service->AddProject(*doc);
296  ids.push_back(doc->GetId());
297  }
298  }
299 
300  if (!ids.empty()) {
302 
303  _ASSERT(task_srv);
304 
305  ITERATE(TProjectIdVector, it, ids) {
307  task(new CProjectLoadingTask(*it, service, true));
308  task_srv->AddTask(*task);
309  }
310  }
311 }
312 
313 static wxString AskProjectSaveFilename(const wxString& docTitle, bool as = false)
314 {
315  // generate the default filename
316  wxString title = docTitle;
317  if (title.length() > 512) {
318  title.erase(509);
319  title += wxT("...");
320  }
321  wxString fname = title + wxT(".gbp");
322 
324  file_data.m_Style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT;
325  file_data.SetFilename(fname);
326  file_data.m_Title = wxT("Save Project \"") + title + (as ? wxT("\" As") : wxT("\""));
327 
330  }
331  return wxEmptyString;
332 }
333 
334 // shows "Save" dialog and save workspace and projects selected by the user
336  CGBWorkspace& ws,
337  const string& title,
338  const string& description,
339  bool save_as,
340  bool no_btn,
341  const TProjectIdVector& project_ids,
342  const TProjectIdVector& selected)
343 {
344  // prepare parameters for the dialog
345  SSaveProjectsDlgParams params;
346  params.m_Description = description;
347  params.m_ShowNoButton = no_btn;
348 
349  // prepare projects data
350  params.m_ProjectIds = project_ids;
351  for( size_t i = 0; i < selected.size(); i++ ) {
352  params.m_ProjectsToSave.Add(static_cast<int>(selected[i]));
353  }
354 
355  // create and initialize the dialog
356  CSaveDlg dlg(ws, NULL);
357  dlg.SetRegistryPath("ApplicationGUI.SaveDlg"); //TODO
358  dlg.SetParams(params);
359  dlg.SetTitle(ToWxString(title));
360 
361  int res = dlg.ShowModal();
362 
363  switch(res) {
364  case wxID_SAVE: {
365  // save selected
366  params = dlg.GetParams();
367  bool ok = true;
368  for( size_t i = 0; ok && i < params.m_ProjectsToSave.size(); i++) {
369  int index = params.m_ProjectsToSave[i];
370 
371  CGBDocument* doc = dynamic_cast<CGBDocument*>(ws.GetProjectFromId(params.m_ProjectIds[index]));
372  if (!doc) {
373  ok = false;
374  continue;
375  }
376  _ASSERT(doc->IsLoaded());
377 
378  wxString filename;
379  if (!save_as) {
380  filename = doc->GetFileName();
381  if (filename.find(wxT("http://")) == 0 || filename.find(wxT("https://")) == 0 || filename.find(wxT("ftp://")) == 0) {
382  wxString msg = wxT("The project\n") + filename;
383  msg += wxT("\nmust have a local file name in order to save it.");
385  filename.clear();
386  }
387  }
388 
389  if (filename.empty())
390  filename = AskProjectSaveFilename(ToWxString(doc->GetDescr().GetTitle()), true);
391 
392  if (filename.empty()) {
393  ok = false;
394  continue;
395  }
396 
397  try {
398  doc->SetFileName(filename);
399  doc->Save(filename);
400  service->AddToProjectWorkspaceMRUList(filename);
401  ERR_POST(Info << "Project saved:" << filename);
402  }
403  catch (const CException& e) {
404  NcbiErrorBox(e.GetMsg(), "Save Project - Error");
405  ok = false;
406  }
407  catch (const exception& e) {
408  NcbiErrorBox(e.what(), "Save Project - Error");
409  ok = false;
410  }
411  }
412  return ok;
413  }
414  case wxID_NO:
415  return true;
416  case wxID_CANCEL:
417  default:
418  return false;
419  }
420  return false;
421 }
422 
423 
User-defined methods of the data storage class.
User-defined methods of the data storage class.
CAppTaskService - Application Task Service.
CAppTask - default implementation of IAppTask, use it as a base class for custom tasks.
virtual void SetRegistryPath(const string &path)
Definition: dialog.cpp:59
CGBDocument.
Definition: document.hpp:113
void SetFileName(const wxString &filename)
Definition: document.cpp:137
void Save(const wxString &abs_path)
Definition: document.cpp:503
void UnloadProject(bool reset_hist_async=true)
Definition: document.cpp:1316
void CancelLoading()
Definition: document.cpp:269
wxString GetFileName() const
Definition: document.cpp:132
bool IsLoading() const
Definition: document.cpp:264
CGBWorkspace.
Definition: GBWorkspace.hpp:63
CGBProjectHandle * GetProjectFromId(CGBProjectHandle::TId id)
static SWFileDlgData sm_ProjectDlgData
static data structures for File dialogs
CProjectService - a service providing API for operations with Workspaces and Projects.
void RemoveProject(CGBDocument &doc)
CRef< objects::CGBWorkspace > GetGBWorkspace()
void AddProject(CGBDocument &doc)
void AddToProjectWorkspaceMRUList(const wxString &path)
CProjectTask(IServiceLocator *srv_locator, vector< wxString > &filenames)
static bool RemoveAllProjects(IServiceLocator *serviceLocator)
static void LoadProjects(IServiceLocator *serviceLocator, const TProjectIdVector &project_ids)
virtual ~CProjectTask()
IServiceLocator * m_SrvLocator
void x_OpenProjects()
overriding CAppTask::x_Run()
vector< TProjectId > TProjectIdVector
static void Save(IServiceLocator *serviceLocator, const TProjectIdVector &project_ids, bool save_as)
static bool RemoveProjects(IServiceLocator *serviceLocator, const TProjectIdVector &project_ids, bool confirm=true)
static bool x_DoSaveUserSelected(CProjectService *service, objects::CGBWorkspace &ws, const string &title, const string &description, bool save_as, bool no_btn, const TProjectIdVector &project_ids, const TProjectIdVector &selected)
virtual ETaskState x_Run()
override this function in derived classes
static void UnLoadProjects(IServiceLocator *serviceLocator, const TProjectIdVector &project_ids)
vector< wxString > m_ProjectFilenames
CRef –.
Definition: ncbiobj.hpp:618
CSaveDlg - a dialog for saving workspace and projects.
Definition: save_dlg.hpp:86
void SetParams(const SSaveProjectsDlgParams &value)
Definition: save_dlg.cpp:148
const SSaveProjectsDlgParams & GetParams() const
Definition: save_dlg.cpp:142
Template class for iteration on objects of class C (non-medifiable version)
Definition: iterator.hpp:767
Template class for iteration on objects of class C.
Definition: iterator.hpp:673
static bool CleanUp()
CGBProjectHandle * FindProjectByFilename(const string &filename)
finds a project in the folder and its sub folders
IServiceLocator - an abstract mechanism for locating services.
Definition: service.hpp:71
wxArrayInt m_ProjectsToSave
indices of the projects to save (checked items)
Definition: save_dlg.hpp:68
vector< objects::CGBProjectHandle::TId > m_ProjectIds
Definition: save_dlg.hpp:65
#define false
Definition: bool.h:36
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NULL
Definition: ncbistd.hpp:225
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:461
virtual const char * what(void) const noexcept
Standard report (includes full backlog).
Definition: ncbiexpt.cpp:342
void Info(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1185
CIRef< T > GetServiceByType()
retrieves a typed reference to a service, the name of C++ type is used as the name of the service.
Definition: service.hpp:91
ETaskState
List of task states defining the task management FSM.
Definition: app_task.hpp:87
@ eCompleted
successfully finished
Definition: app_task.hpp:92
void SetFilename(const wxString &filename)
void NcbiErrorBox(const string &message, const string &title="Error")
specialized Message Box function for reporting critical errors
EDialogReturnValue NcbiMessageBoxW(const wxString &message, TDialogType type=eDialog_Ok, EDialogIcon icon=eIcon_Exclamation, const wxString &title=wxT("Error"), EDialogTextMode text_mode=eRaw)
wxString m_Title
int NcbiFileBrowser(SFileDlgData &data, wxWindow *parent=NULL)
show wxFileDialog and returns
wxString GetFilename() const
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define kEmptyStr
Definition: ncbistr.hpp:123
int i
#define wxT(x)
Definition: muParser.cpp:41
Format
Definition: njn_ioutil.hpp:52
void copy(Njn::Matrix< S > *matrix_, const Njn::Matrix< T > &matrix0_)
Definition: njn_matrix.hpp:613
static int filenames
Definition: pcre2grep.c:247
USING_SCOPE(objects)
static wxString AskProjectSaveFilename(const wxString &docTitle, bool as=false)
static CProjectTask::TProjectIdVector s_GetUnsavedProjects(CGBWorkspace &ws, const CProjectTask::TProjectIdVector &projects)
static SLJIT_INLINE sljit_ins msg(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
#define _ASSERT
wxString ToWxString(const string &s)
Definition: wx_utils.hpp:173
string FnToStdString(const wxString &s)
Definition: wx_utils.cpp:268
Modified on Fri Sep 20 14:58:25 2024 by modify_doxy.py rev. 669887