summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/job.cc30
-rw-r--r--src/lib/job.h14
-rw-r--r--src/wx/job_manager_view.cc29
-rw-r--r--src/wx/job_manager_view.h2
4 files changed, 64 insertions, 11 deletions
diff --git a/src/lib/job.cc b/src/lib/job.cc
index 8c1612a55..ace02b8b3 100644
--- a/src/lib/job.cc
+++ b/src/lib/job.cc
@@ -38,6 +38,7 @@ using boost::shared_ptr;
*/
Job::Job (shared_ptr<Film> f)
: _film (f)
+ , _thread (0)
, _state (NEW)
, _start_time (0)
, _progress_unknown (false)
@@ -52,7 +53,7 @@ Job::start ()
{
set_state (RUNNING);
_start_time = time (0);
- boost::thread (boost::bind (&Job::run_wrapper, this));
+ _thread = new boost::thread (boost::bind (&Job::run_wrapper, this));
}
/** A wrapper for the ::run() method to catch exceptions */
@@ -77,6 +78,10 @@ Job::run_wrapper ()
}
set_error (e.what(), m);
+
+ } catch (boost::thread_interrupted &) {
+
+ set_state (FINISHED_CANCELLED);
} catch (std::exception& e) {
@@ -120,7 +125,7 @@ bool
Job::finished () const
{
boost::mutex::scoped_lock lm (_state_mutex);
- return _state == FINISHED_OK || _state == FINISHED_ERROR;
+ return _state == FINISHED_OK || _state == FINISHED_ERROR || _state == FINISHED_CANCELLED;
}
/** @return true if the job has finished successfully */
@@ -139,6 +144,13 @@ Job::finished_in_error () const
return _state == FINISHED_ERROR;
}
+bool
+Job::finished_cancelled () const
+{
+ boost::mutex::scoped_lock lm (_state_mutex);
+ return _state == FINISHED_CANCELLED;
+}
+
/** Set the state of this job.
* @param s New state.
*/
@@ -173,6 +185,7 @@ Job::set_progress (float p)
boost::mutex::scoped_lock lm (_progress_mutex);
_progress_unknown = false;
_stack.back().normalised = p;
+ boost::this_thread::interruption_point ();
}
/** @return fractional overall progress, or -1 if not known */
@@ -285,6 +298,8 @@ Job::status () const
s << String::compose (_("OK (ran for %1)"), seconds_to_hms (_ran_for));
} else if (finished_in_error ()) {
s << String::compose (_("Error (%1)"), error_summary());
+ } else if (finished_cancelled ()) {
+ s << _("Cancelled");
}
return s.str ();
@@ -296,3 +311,14 @@ Job::remaining_time () const
{
return elapsed_time() / overall_progress() - elapsed_time();
}
+
+void
+Job::cancel ()
+{
+ if (!_thread) {
+ return;
+ }
+
+ _thread->interrupt ();
+ _thread->join ();
+}
diff --git a/src/lib/job.h b/src/lib/job.h
index c98dbaea1..fd036bce2 100644
--- a/src/lib/job.h
+++ b/src/lib/job.h
@@ -28,6 +28,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/signals2.hpp>
+#include <boost/thread.hpp>
class Film;
@@ -46,12 +47,14 @@ public:
virtual void run () = 0;
void start ();
+ void cancel ();
bool is_new () const;
bool running () const;
bool finished () const;
bool finished_ok () const;
bool finished_in_error () const;
+ bool finished_cancelled () const;
std::string error_summary () const;
std::string error_details () const;
@@ -74,10 +77,11 @@ protected:
/** Description of a job's state */
enum State {
- NEW, ///< the job hasn't been started yet
- RUNNING, ///< the job is running
- FINISHED_OK, ///< the job has finished successfully
- FINISHED_ERROR ///< the job has finished in error
+ NEW, ///< the job hasn't been started yet
+ RUNNING, ///< the job is running
+ FINISHED_OK, ///< the job has finished successfully
+ FINISHED_ERROR, ///< the job has finished in error
+ FINISHED_CANCELLED ///< the job was cancelled
};
void set_state (State);
@@ -90,6 +94,8 @@ private:
void run_wrapper ();
+ boost::thread* _thread;
+
/** mutex for _state and _error */
mutable boost::mutex _state_mutex;
/** current state of the job */
diff --git a/src/wx/job_manager_view.cc b/src/wx/job_manager_view.cc
index 7361f29a8..f7d2315cc 100644
--- a/src/wx/job_manager_view.cc
+++ b/src/wx/job_manager_view.cc
@@ -42,7 +42,7 @@ JobManagerView::JobManagerView (wxWindow* parent)
sizer->Add (_panel, 1, wxEXPAND);
SetSizer (sizer);
- _table = new wxFlexGridSizer (4, 6, 6);
+ _table = new wxFlexGridSizer (5, 6, 6);
_table->AddGrowableCol (1, 1);
_panel->SetSizer (_table);
@@ -85,10 +85,14 @@ JobManagerView::update ()
r.message = new wxStaticText (_panel, wxID_ANY, std_to_wx (""));
_table->Insert (index + 2, r.message, 1, wxALIGN_CENTER_VERTICAL | wxALL, 6);
+ r.cancel = new wxButton (_panel, wxID_ANY, _("Cancel"));
+ r.cancel->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (JobManagerView::cancel_clicked), 0, this);
+ _table->Insert (index + 3, r.cancel, 1, wxALIGN_CENTER_VERTICAL | wxALL, 6);
+
r.details = new wxButton (_panel, wxID_ANY, _("Details..."));
r.details->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (JobManagerView::details_clicked), 0, this);
r.details->Enable (false);
- _table->Insert (index + 3, r.details, 1, wxALIGN_CENTER_VERTICAL | wxALL, 6);
+ _table->Insert (index + 4, r.details, 1, wxALIGN_CENTER_VERTICAL | wxALL, 6);
_job_records[*i] = r;
}
@@ -105,18 +109,21 @@ JobManagerView::update ()
_job_records[*i].gauge->Pulse ();
}
}
-
+
if ((*i)->finished() && !_job_records[*i].finalised) {
- _job_records[*i].gauge->SetValue (100);
checked_set (_job_records[*i].message, st);
+ if (!(*i)->finished_cancelled()) {
+ _job_records[*i].gauge->SetValue (100);
+ }
(*i)->Finished ();
_job_records[*i].finalised = true;
+ _job_records[*i].cancel->Enable (false);
if (!(*i)->error_details().empty ()) {
_job_records[*i].details->Enable (true);
}
}
- index += 4;
+ index += 5;
}
_table->Layout ();
@@ -136,3 +143,15 @@ JobManagerView::details_clicked (wxCommandEvent& ev)
}
}
}
+
+void
+JobManagerView::cancel_clicked (wxCommandEvent& ev)
+{
+ wxObject* o = ev.GetEventObject ();
+
+ for (map<boost::shared_ptr<Job>, JobRecord>::iterator i = _job_records.begin(); i != _job_records.end(); ++i) {
+ if (i->second.cancel == o) {
+ i->first->cancel ();
+ }
+ }
+}
diff --git a/src/wx/job_manager_view.h b/src/wx/job_manager_view.h
index d43e795ea..72ac85c02 100644
--- a/src/wx/job_manager_view.h
+++ b/src/wx/job_manager_view.h
@@ -39,6 +39,7 @@ public:
private:
void periodic (wxTimerEvent &);
+ void cancel_clicked (wxCommandEvent &);
void details_clicked (wxCommandEvent &);
boost::shared_ptr<wxTimer> _timer;
@@ -47,6 +48,7 @@ private:
struct JobRecord {
wxGauge* gauge;
wxStaticText* message;
+ wxButton* cancel;
wxButton* details;
bool finalised;
};