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 39891 2017-11-20 18:17:24Z katargir $
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 
75 static vector<int> s_GetUnsavedProjects(CGBWorkspace& ws, const vector<int>& projects)
76 {
77  vector<int> unsaved;
78  ITERATE(vector<int>, it, projects) {
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  vector<int> toUnload(project_ids.begin(), project_ids.end());
102 
103  // collect selected projects that need to be saved
104  vector<int> unsaved = s_GetUnsavedProjects(*ws, toUnload);
105 
106  bool ok = true;
107  if (!unsaved.empty()) {
108  // select all
109  vector<int> 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(vector<int>, 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  vector<int> toRemove;
163  copy(project_ids.begin(), project_ids.end(), back_inserter(toRemove));
164 
165  // collect selected projects that need to be saved
166  vector<int> unsaved = s_GetUnsavedProjects(*ws, toRemove);
167 
168  bool ok = true;
169  if (!unsaved.empty()) {
170  // select all
171  vector<int> 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(vector<int>, 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  vector<int> 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  vector<int> 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  int 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 vector<int>& project_ids,
342  const vector<int>& selected)
343 {
344  // prepare parameters for the dialog
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(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.");
384  NcbiMessageBoxW(msg);
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 
CGBWorkspace.
Definition: GBWorkspace.hpp:62
const SSaveProjectsDlgParams & GetParams() const
Definition: save_dlg.cpp:142
virtual ETaskState x_Run()
override this function in derived classes
static const unsigned char msg[]
Definition: ccm.c:378
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
CGBDocument.
Definition: document.hpp:109
static vector< int > s_GetUnsavedProjects(CGBWorkspace &ws, const vector< int > &projects)
void Save(const wxString &abs_path)
Definition: document.cpp:501
Template class for iteration on objects of class C.
Definition: iterator.hpp:672
IServiceLocator * m_SrvLocator
void RemoveProject(CGBDocument &doc)
CSaveDlg - a dialog for saving workspace and projects.
Definition: save_dlg.hpp:85
Template class for iteration on objects of class C (non-medifiable version)
Definition: iterator.hpp:762
wxString ToWxString(const char *s)
Definition: wx_utils.hpp:159
USING_SCOPE(objects)
wxString m_Title
wxString GetFileName() const
Definition: document.cpp:130
User-defined methods of the data storage class.
vector< int > m_ProjectIds
Definition: save_dlg.hpp:65
CProjectService - a service providing API for operations with Workspaces and Projects.
User-defined methods of the data storage class.
void SetFilename(const wxString &filename)
wxArrayInt m_ProjectsToSave
indices of the projects to save (checked items)
Definition: save_dlg.hpp:68
wxString GetFilename() const
#define NULL
Definition: ncbistd.hpp:225
static const unsigned char res[3][32]
Definition: ccm.c:389
static bool x_DoSaveUserSelected(CProjectService *service, objects::CGBWorkspace &ws, const string &title, const string &description, bool save_as, bool no_btn, const vector< int > &project_ids, const vector< int > &selected)
#define kEmptyStr
Definition: ncbistr.hpp:121
CGBProjectHandle * FindProjectByFilename(const string &filename)
finds a project in the folder and its sub folders
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:795
int i
void SetFileName(const wxString &filename)
Definition: document.cpp:135
void copy(Njn::Matrix< S > *matrix_, const Njn::Matrix< T > &matrix0_)
Definition: njn_matrix.hpp:612
static SWFileDlgData sm_ProjectDlgData
static data structures for File dialogs
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:101
virtual void SetRegistryPath(const string &path)
Definition: dialog.cpp:56
static void LoadProjects(IServiceLocator *serviceLocator, const TProjectIdVector &project_ids)
EDialogReturnValue NcbiMessageBoxW(const wxString &message, TDialogType type=eDialog_Ok, EDialogIcon icon=eIcon_Exclamation, const wxString &title=wxT("Error"), EDialogTextMode text_mode=eRaw)
void UnloadProject(bool reset_hist_async=true)
Definition: document.cpp:1332
CAppTask - default implementation of IAppTask, use it as a base class for custom tasks.
CRef< objects::CGBWorkspace > GetGBWorkspace()
static wxString AskProjectSaveFilename(const wxString &docTitle, bool as=false)
CAppTaskService - Application Task Service.
void x_OpenProjects()
overriding CAppTask::x_Run()
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:185
const TWorkspace & GetWorkspace(void) const
Get the Workspace member data.
static bool RemoveAllProjects(IServiceLocator *serviceLocator)
virtual ~CProjectTask()
string FnToStdString(const wxString &s)
Definition: wx_utils.cpp:189
CProjectTask(IServiceLocator *srv_locator, vector< wxString > &filenames)
bool IsLoading() const
Definition: document.cpp:262
static int filenames
Definition: pcregrep.c:157
IServiceLocator - an abstract mechanism for locating services.
Definition: service.hpp:70
CGBProjectHandle * GetProjectFromId(CGBProjectHandle::TId id)
vector< wxString > m_ProjectFilenames
void SetWorkspace(TWorkspace &value)
Assign a value to Workspace data member.
static bool RemoveProjects(IServiceLocator *serviceLocator, const TProjectIdVector &project_ids, bool confirm=true)
static bool CleanUp()
CRef –.
Definition: ncbiobj.hpp:616
Format
Definition: njn_ioutil.hpp:52
successfully finished
Definition: app_task.hpp:92
vector< int > TProjectIdVector
void Info(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1029
#define wxT(x)
Definition: muParser.cpp:41
static void UnLoadProjects(IServiceLocator *serviceLocator, const TProjectIdVector &project_ids)
#define _ASSERT
int NcbiFileBrowser(SFileDlgData &data, wxWindow *parent=NULL)
show wxFileDialog and returns
Definition: dbpivot.c:60
void AddToProjectWorkspaceMRUList(const wxString &path)
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:459
static std::unique_ptr< CParams > params
Definition: wgs_params.cpp:491
void NcbiErrorBox(const string &message, const string &title="Error")
specialized Message Box function for reporting critical errors
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:98
void AddProject(CGBDocument &doc)
void SetParams(const SSaveProjectsDlgParams &value)
Definition: save_dlg.cpp:148
void CancelLoading()
Definition: document.cpp:267
static void Save(IServiceLocator *serviceLocator, const TProjectIdVector &project_ids, bool save_as)
ETaskState
List of task states defining the task management FSM.
Definition: app_task.hpp:87
Modified on Fri Apr 20 12:42:28 2018 by modify_doxy.py rev. 546573