Index: src/ch/ClipboardMonitor.cpp =================================================================== diff -u -rb684bec49aaaea4b89ab2e599497f4085d8698a3 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/ClipboardMonitor.cpp (.../ClipboardMonitor.cpp) (revision b684bec49aaaea4b89ab2e599497f4085d8698a3) +++ src/ch/ClipboardMonitor.cpp (.../ClipboardMonitor.cpp) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -181,12 +181,8 @@ SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_FIRSTCOPY_STRING)); SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING)); - CTaskPtr spTask = pData->m_pTasks->CreateTask(); - spTask->SetTaskDefinition(tTaskDefinition); + CTaskPtr spTask = pData->m_pTasks->CreateTask(tTaskDefinition); - // add task to a list of tasks and start - pData->m_pTasks->Add(spTask); - // write spTask to a file spTask->Store(); Index: src/ch/MainWnd.cpp =================================================================== diff -u -ra0a0c78670588f86c6be24afb076e6b304441563 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision a0a0c78670588f86c6be24afb076e6b304441563) +++ src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -1,5 +1,5 @@ /*************************************************************************** -* Copyright (C) 2001-2008 by Jozef Starosczyk * +* Copyright (C) 2001-2011 by Jozef Starosczyk * * ixen@copyhandler.com * * * * This program is free software; you can redistribute it and/or modify * @@ -32,8 +32,8 @@ #include "MiniviewDlg.h" #include "StatusDlg.h" #include "ClipboardMonitor.h" - #include +#include #ifdef _DEBUG #define new DEBUG_NEW @@ -166,7 +166,7 @@ return -1; // get msg id of taskbar created message - m_uiTaskbarRestart=RegisterWindowMessage(_T("TaskbarCreated")); + m_uiTaskbarRestart = RegisterWindowMessage(_T("TaskbarCreated")); // Create the tray icon ShowTrayIcon(); @@ -180,13 +180,65 @@ GetApp().GetProgramDataPath(strPath); strPath += _T("\\Tasks\\"); m_tasks.SetTasksDir(strPath); + + // load tasks m_tasks.LoadDataProgress(); + + // import tasks specified at command line (before loading current tasks) + const TCommandLineParser& cmdLine = GetApp().GetCommandLine(); + if(cmdLine.HasTaskDefinitionPath()) + { + std::vector vTaskPaths; + cmdLine.GetTaskDefinitionPaths(vTaskPaths); + + const size_t stBufferSize = 4096; + boost::shared_array szBuffer(new wchar_t[stBufferSize]); + + BOOST_FOREACH(const CString& strPath, vTaskPaths) + { + bool bImported = false; + + try + { + CTaskPtr spTask = m_tasks.ImportTask(strPath); + if(spTask) + spTask->Store(); + bImported = true; + } + catch(icpf::exception& e) + { + bImported = false; + e.get_info(szBuffer.get(), stBufferSize); + } + catch(...) + { + bImported = false; + szBuffer.get()[0] = _T('\0'); + } + + if(!bImported) + { + ictranslate::CFormat fmt; + fmt.SetFormat(_T("Error encountered while importing task from path '%path'. Error: %err.")); + fmt.SetParam(_T("%path"), strPath); + fmt.SetParam(_T("%error"), szBuffer.get()); + + LOG_ERROR(fmt); + + fmt.SetFormat(GetResManager().LoadString(IDS_TASK_IMPORT_FAILED)); + fmt.SetParam(_T("%path"), strPath); + AfxMessageBox(fmt, MB_OK | MB_ICONERROR); + } + } + } + + // resume tasks m_tasks.TasksRetryProcessing(); // start clipboard monitoring LOG_INFO(_T("Starting clipboard monitor...")); CClipboardMonitor::StartMonitor(&m_tasks); - + EUpdatesFrequency eFrequency = (EUpdatesFrequency)GetPropValue(GetConfig()); if(eFrequency != eFreq_Never) { @@ -323,7 +375,11 @@ m_ctlTray.SetTooltipText(text); } else - m_ctlTray.SetTooltipText(GetApp().GetAppNameVer()); + { + CString strText = GetApp().GetAppNameVer(); + strText += GetResManager().LoadString(IDS_CH_PORTABLE_STRING); + m_ctlTray.SetTooltipText(strText); + } break; } } @@ -532,15 +588,8 @@ SetTaskPropValue(tTaskDefinition.GetConfiguration(), ffFilters); // create task with the above definition - CTaskPtr spTask = m_tasks.CreateTask(); + CTaskPtr spTask = m_tasks.CreateTask(tTaskDefinition); - spTask->SetTaskDefinition(tTaskDefinition); - - m_tasks.Add(spTask); - - // save state of a task - spTask->Store(); - // add to task list and start processing spTask->BeginProcessing(); @@ -621,15 +670,9 @@ SetTaskPropValue(tTaskDefinition.GetConfiguration(), dlg.m_ccData.m_afFilters); // new task - CTaskPtr spTask = m_tasks.CreateTask(); - spTask->SetTaskDefinition(tTaskDefinition); - - m_tasks.Add(spTask); + CTaskPtr spTask = m_tasks.CreateTask(tTaskDefinition); - // save - spTask->Store(); - - // store and start + // start spTask->BeginProcessing(); } } Index: src/ch/TCommandLineParser.cpp =================================================================== diff -u --- src/ch/TCommandLineParser.cpp (revision 0) +++ src/ch/TCommandLineParser.cpp (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -0,0 +1,72 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TCommandLineParser.cpp +/// @date 2011/04/08 +/// @brief Contains an implementation of command line parser class. +// ============================================================================ +#include "stdafx.h" +#include "TCommandLineParser.h" +#include + +TCommandLineParser::TCommandLineParser() +{ +} + +TCommandLineParser::~TCommandLineParser() +{ +} + +void TCommandLineParser::ParseCommandLine(const wchar_t* pszCommandLine) +{ + m_mapVariables.clear(); + + namespace po = boost::program_options; + + std::vector args = po::split_winmain(pszCommandLine); + + po::options_description desc(""); + desc.add_options() + ("ImportTaskDefinition", po::wvalue< std::vector >(), ""); + + po::variables_map vm; + po::store(po::wcommand_line_parser(args).options(desc).run(), m_mapVariables); + po::notify(vm); +} + +bool TCommandLineParser::HasCommandLineParams() const +{ + return !m_mapVariables.empty(); +} + +bool TCommandLineParser::HasTaskDefinitionPath() const +{ + return m_mapVariables.count("ImportTaskDefinition") > 0; +} + +void TCommandLineParser::GetTaskDefinitionPaths(std::vector& vPaths) const +{ + vPaths.clear(); + + std::vector vValues; + if(HasTaskDefinitionPath()) + { + vValues = m_mapVariables["ImportTaskDefinition"].as >(); + std::transform(vValues.begin(), vValues.end(), std::back_inserter(vPaths), boost::bind(&std::wstring::c_str, _1)); + } +} Index: src/ch/TCommandLineParser.h =================================================================== diff -u --- src/ch/TCommandLineParser.h (revision 0) +++ src/ch/TCommandLineParser.h (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -0,0 +1,44 @@ +// ============================================================================ +// Copyright (C) 2001-2011 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file TCommandLineParser.h +/// @date 2011/04/08 +/// @brief Contains class for handling command line options. +// ============================================================================ +#ifndef __TCOMMANDLINEPARSER_H__ +#define __TCOMMANDLINEPARSER_H__ + +#include + +class TCommandLineParser +{ +public: + TCommandLineParser(); + ~TCommandLineParser(); + + void ParseCommandLine(const wchar_t* pszCommandLine); + + bool HasCommandLineParams() const; + + bool HasTaskDefinitionPath() const; + void GetTaskDefinitionPaths(std::vector& vPaths) const; + +private: + boost::program_options::variables_map m_mapVariables; +}; +#endif Index: src/ch/TTaskDefinition.cpp =================================================================== diff -u -rb684bec49aaaea4b89ab2e599497f4085d8698a3 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/TTaskDefinition.cpp (.../TTaskDefinition.cpp) (revision b684bec49aaaea4b89ab2e599497f4085d8698a3) +++ src/ch/TTaskDefinition.cpp (.../TTaskDefinition.cpp) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -21,15 +21,19 @@ /// @brief Contains implementation of class representing task input data. // ============================================================================ #include "stdafx.h" +#include "..\common\version.h" #include #include #include #include #include "TTaskDefinition.h" +#define CURRENT_TASK_VERSION (((unsigned long long)PRODUCT_VERSION1) << 48 | ((unsigned long long)PRODUCT_VERSION2) << 32 | ((unsigned long long)PRODUCT_VERSION3) << 16 | ((unsigned long long)PRODUCT_VERSION4)) + TTaskDefinition::TTaskDefinition() : m_bModified(false), - m_strTaskUniqueID() + m_strTaskUniqueID(), + m_ullTaskVersion(CURRENT_TASK_VERSION) { boost::uuids::random_generator gen; boost::uuids::uuid u = gen(); @@ -41,6 +45,7 @@ m_vSourcePaths(rSrc.m_vSourcePaths), m_pathDestinationPath(rSrc.m_pathDestinationPath), m_tOperationPlan(rSrc.m_tOperationPlan), + m_ullTaskVersion(rSrc.m_ullTaskVersion), m_tConfiguration(rSrc.m_tConfiguration), m_bModified(rSrc.m_bModified) { @@ -58,6 +63,7 @@ m_vSourcePaths = rSrc.m_vSourcePaths; m_pathDestinationPath = rSrc.m_pathDestinationPath; m_tOperationPlan = rSrc.m_tOperationPlan; + m_ullTaskVersion = rSrc.m_ullTaskVersion; m_tConfiguration = rSrc.m_tConfiguration; m_bModified = rSrc.m_bModified; } @@ -175,20 +181,39 @@ } // basic information + // source paths to be processed if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.SourcePaths"), m_vSourcePaths) || m_vSourcePaths.IsEmpty()) THROW(_T("Missing source paths"), 0, 0, 0); + // destination path if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.DestinationPath"), m_pathDestinationPath) || m_pathDestinationPath.IsEmpty()) THROW(_T("Missing destination path"), 0, 0, 0); m_pathDestinationPath.AppendSeparatorIfDoesNotExist(); + // type of the operation int iOperation = eOperation_None; if(!tTaskInfo.GetValue(_T("TaskDefinition.OperationType"), iOperation)) THROW(_T("Missing operation type"), 0, 0, 0); m_tOperationPlan.SetOperationType((EOperationType)iOperation); + // and version of the task + if(!GetConfigValue(tTaskInfo, _T("TaskDefinition.Version"), m_ullTaskVersion)) + THROW(_T("Missing task definition version"), 0, 0, 0); + + if(m_ullTaskVersion < CURRENT_TASK_VERSION) + { + // migrate the task to the newer version + // (nothing to migrate at this point, since 1.40 is the first release with xml-based tasks). + + // then mark it as a newest version task + m_ullTaskVersion = CURRENT_TASK_VERSION; + m_bModified = true; + } + else if(m_ullTaskVersion > CURRENT_TASK_VERSION) + THROW(_T("Unsupported task version"), 0, 0, 0); + tTaskInfo.ExtractSubConfig(_T("TaskDefinition.TaskSettings"), m_tConfiguration); } Index: src/ch/TTaskDefinition.h =================================================================== diff -u -rb684bec49aaaea4b89ab2e599497f4085d8698a3 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/TTaskDefinition.h (.../TTaskDefinition.h) (revision b684bec49aaaea4b89ab2e599497f4085d8698a3) +++ src/ch/TTaskDefinition.h (.../TTaskDefinition.h) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -77,6 +77,9 @@ TOperationPlan m_tOperationPlan; ///< Describes the operation along with sub-operations to be performed on the task input data + // Task version + unsigned long long m_ullTaskVersion; + // Global task settings chcore::TConfig m_tConfiguration; Index: src/ch/ch.cpp =================================================================== diff -u -ra0a0c78670588f86c6be24afb076e6b304441563 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/ch.cpp (.../ch.cpp) (revision a0a0c78670588f86c6be24afb076e6b304441563) +++ src/ch/ch.cpp (.../ch.cpp) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -25,6 +25,7 @@ #include #include "CrashDlg.h" #include "../common/version.h" +#include "TCommandLineParser.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -205,6 +206,11 @@ // ================================= Crash handling ======================================= SetUnhandledExceptionFilter(&MyUnhandledExceptionFilter); + // ================================= Handle command line ================================== + // parse the command line this early, so we can support as much options as possible in the future + // (i.e. override the defaults used below) + m_cmdLineParser.ParseCommandLine(::GetCommandLine()); + // ================================= Configuration ======================================== CString strPath; CString strCfgPath; Index: src/ch/ch.h =================================================================== diff -u -r3cd8d4a64a63e4fb32d7dc96e46789c713698435 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/ch.h (.../ch.h) (revision 3cd8d4a64a63e4fb32d7dc96e46789c713698435) +++ src/ch/ch.h (.../ch.h) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -30,6 +30,7 @@ #include "../libictranslate/ResourceManager.h" #include "../libchcore/TConfig.h" #include "TShellExtensionClient.h" +#include "TCommandLineParser.h" ///////////////////////////////////////////////////////////////////////////// // CCopyHandlerApp: @@ -62,6 +63,8 @@ void OnConfigNotify(const std::set& setPropNames); void OnResManNotify(UINT uiType); + const TCommandLineParser& GetCommandLine() const { return m_cmdLineParser; } + protected: bool UpdateHelpPaths(); HWND HHelp(HWND hwndCaller, LPCTSTR pszFile, UINT uCommand, DWORD_PTR dwData); @@ -71,6 +74,7 @@ protected: HANDLE m_hMapObject; TShellExtensionClient m_tShellExtClient; + TCommandLineParser m_cmdLineParser; CWnd *m_pMainWindow; Index: src/ch/ch.rc =================================================================== diff -u -ra0a0c78670588f86c6be24afb076e6b304441563 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/ch.rc (.../ch.rc) (revision a0a0c78670588f86c6be24afb076e6b304441563) +++ src/ch/ch.rc (.../ch.rc) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -1055,9 +1055,10 @@ IDS_UPDATER_WAITING_STRING "Please wait for the connection with %site to be established..." IDS_SHELL_EXTENSION_MISMATCH_STRING "Copy Handler encountered incompatible version of component enabling integration with system installed on your system.\nWould you like to update it now (requires administrative rights)?" - IDS_SHELL_EXTENSION_UNREGISTERED_STRING "Copy Handler's component enabling integration with system is disabled.\nDo you want to enable it now (requires administrative rights)?" - IDS_SHELL_EXTENSION_REGISTERED_MISMATCH_STRING "Copy Handler's component enabling integration with system was updated.\nPlease reboot your system for changes to take effect." + IDS_SHELL_EXTENSION_UNREGISTERED_STRING "Copy Handler's component enabling integration with system is disabled.\nDo you want to enable it now (requires administrative rights)?" + IDS_SHELL_EXTENSION_REGISTERED_MISMATCH_STRING "Copy Handler's component enabling integration with system was updated.\nPlease reboot your system for changes to take effect." IDS_CH_PORTABLE_STRING " (portable mode)" + IDS_TASK_IMPORT_FAILED "Failed to import task '%path'." END STRINGTABLE Index: src/ch/ch.vc90.vcproj =================================================================== diff -u -r8c87d4185fbe5b952c49f72afcfd5f9fca338fb4 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 8c87d4185fbe5b952c49f72afcfd5f9fca338fb4) +++ src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -750,6 +750,14 @@ RelativePath="stdafx.h" > + + + + SetTaskDefinition(tTaskDefinition); + Add(spTask); + spTask->Store(); + } + + return spTask; +} + +CTaskPtr CTaskArray::ImportTask(const CString& strTaskPath) +{ + // load task definition from the new location + TTaskDefinition tTaskDefinition; + tTaskDefinition.Load(strTaskPath); + + return CreateTask(tTaskDefinition); +} + +CTaskPtr CTaskArray::CreateEmptyTask() +{ BOOST_ASSERT(m_piFeedbackFactory); if(!m_piFeedbackFactory) return CTaskPtr(); @@ -954,7 +976,7 @@ return CTaskPtr(); BOOST_ASSERT(m_stNextSessionUniqueID != NO_TASK_SESSION_UNIQUE_ID); - CTaskPtr spTask(boost::make_shared(piHandler, m_stNextSessionUniqueID++)); + CTaskPtr spTask(new CTask(piHandler, m_stNextSessionUniqueID++)); // NO_TASK_SESSION_UNIQUE_ID is a special value so it should not be used to identify tasks if(m_stNextSessionUniqueID == NO_TASK_SESSION_UNIQUE_ID) @@ -1151,7 +1173,7 @@ bWorking = finder.FindNextFile(); // load data - spTask = CreateTask(); + spTask = CreateEmptyTask(); try { spTask->Load(finder.GetFilePath()); Index: src/ch/task.h =================================================================== diff -u -rc866a5e96f5eaf160278a8c128bf86e342cc2409 -r8dd3566d66a35a662872eaaa45eef5049e71c3dc --- src/ch/task.h (.../task.h) (revision c866a5e96f5eaf160278a8c128bf86e342cc2409) +++ src/ch/task.h (.../task.h) (revision 8dd3566d66a35a662872eaaa45eef5049e71c3dc) @@ -107,10 +107,8 @@ }; public: - CTask(chcore::IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID); ~CTask(); - void SetTaskDefinition(const TTaskDefinition& rTaskDefinition); const TTaskDefinition& GetTaskDefinition() const { return m_tTaskDefinition; } void SetTaskState(ETaskCurrentState eTaskState); @@ -152,6 +150,10 @@ CString GetRelatedPath(EPathType ePathType); protected: + CTask(chcore::IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID); + + void SetTaskDefinition(const TTaskDefinition& rTaskDefinition); + // methods are called when task is being added or removed from the global task array /// Method is called when this task is being added to a CTaskArray object void OnRegisterTask(TTasksGlobalStats& rtGlobalStats); @@ -268,7 +270,8 @@ void Create(chcore::IFeedbackHandlerFactory* piFeedbackHandlerFactory); - CTaskPtr CreateTask(); + CTaskPtr CreateTask(const TTaskDefinition& tTaskDefinition); + CTaskPtr ImportTask(const CString& strTaskPath); size_t GetSize() const; @@ -305,7 +308,9 @@ protected: void StopAllTasksNL(); - + + CTaskPtr CreateEmptyTask(); + public: tstring_t m_strTasksDir;