BOOST_FOREACH.
[dcpomatic.git] / src / wx / wx_util.cc
index 4fde32674c2129721c3b8c87839c2f14227238e7..3386b2700c522c7047c4bb0e0c738473cf1b6303 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
 #include "wx_util.h"
 #include "file_picker_ctrl.h"
+#include "static_text.h"
+#include "password_entry.h"
 #include "lib/config.h"
+#include "lib/job_manager.h"
 #include "lib/util.h"
 #include "lib/cross.h"
+#include "lib/job.h"
+#include "lib/warnings.h"
 #include <dcp/locale_convert.h>
+DCPOMATIC_DISABLE_WARNINGS
 #include <wx/spinctrl.h>
 #include <wx/splash.h>
+#include <wx/progdlg.h>
+#include <wx/filepicker.h>
+DCPOMATIC_ENABLE_WARNINGS
 #include <boost/thread.hpp>
 
-using namespace std;
-using namespace boost;
+using std::string;
+using std::vector;
+using std::pair;
+using std::shared_ptr;
+using boost::optional;
 using dcp::locale_convert;
+using namespace dcpomatic;
+
+wxStaticText *
+#ifdef __WXOSX__
+create_label (wxWindow* p, wxString t, bool left)
+#else
+create_label (wxWindow* p, wxString t, bool)
+#endif
+{
+#ifdef __WXOSX__
+       if (left) {
+               t += wxT (":");
+       }
+#endif
+       return new StaticText (p, t);
+}
 
 /** Add a wxStaticText to a wxSizer, aligning it at vertical centre.
  *  @param s Sizer to add to.
@@ -45,42 +73,65 @@ using dcp::locale_convert;
  *  @param prop Proportion to pass when calling Add() on the wxSizer.
  */
 wxStaticText *
-#ifdef __WXOSX__
 add_label_to_sizer (wxSizer* s, wxWindow* p, wxString t, bool left, int prop, int flags)
-#else
-add_label_to_sizer (wxSizer* s, wxWindow* p, wxString t, bool, int prop, int flags)
-#endif
 {
 #ifdef __WXOSX__
        if (left) {
                flags |= wxALIGN_RIGHT;
-               t += wxT (":");
        }
 #endif
-       wxStaticText* m = new wxStaticText (p, wxID_ANY, t);
+       wxStaticText* m = create_label (p, t, left);
        s->Add (m, prop, flags, 6);
        return m;
 }
 
 wxStaticText *
 #ifdef __WXOSX__
-add_label_to_sizer (wxGridBagSizer* s, wxWindow* p, wxString t, bool left, wxGBPosition pos, wxGBSpan span)
+add_label_to_sizer (wxSizer* s, wxStaticText* t, bool left, int prop, int flags)
 #else
-add_label_to_sizer (wxGridBagSizer* s, wxWindow* p, wxString t, bool, wxGBPosition pos, wxGBSpan span)
+add_label_to_sizer (wxSizer* s, wxStaticText* t, bool, int prop, int flags)
 #endif
+{
+#ifdef __WXOSX__
+       if (left) {
+               flags |= wxALIGN_RIGHT;
+       }
+#endif
+       s->Add (t, prop, flags, 6);
+       return t;
+}
+
+wxStaticText *
+add_label_to_sizer (wxGridBagSizer* s, wxWindow* p, wxString t, bool left, wxGBPosition pos, wxGBSpan span)
 {
        int flags = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT;
 #ifdef __WXOSX__
        if (left) {
                flags |= wxALIGN_RIGHT;
-               t += wxT (":");
        }
 #endif
-       wxStaticText* m = new wxStaticText (p, wxID_ANY, t);
+       wxStaticText* m = create_label (p, t, left);
        s->Add (m, pos, span, flags);
        return m;
 }
 
+wxStaticText *
+#ifdef __WXOSX__
+add_label_to_sizer (wxGridBagSizer* s, wxStaticText* t, bool left, wxGBPosition pos, wxGBSpan span)
+#else
+add_label_to_sizer (wxGridBagSizer* s, wxStaticText* t, bool, wxGBPosition pos, wxGBSpan span)
+#endif
+{
+       int flags = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT;
+#ifdef __WXOSX__
+       if (left) {
+               flags |= wxALIGN_RIGHT;
+       }
+#endif
+       s->Add (t, pos, span, flags);
+       return t;
+}
+
 /** Pop up an error dialogue box.
  *  @param parent Parent.
  *  @param m Message.
@@ -91,7 +142,9 @@ error_dialog (wxWindow* parent, wxString m, optional<wxString> e)
 {
        wxMessageDialog* d = new wxMessageDialog (parent, m, _("DCP-o-matic"), wxOK | wxICON_ERROR);
        if (e) {
-               d->SetExtendedMessage (*e);
+               wxString em = *e;
+               em[0] = wxToupper (em[0]);
+               d->SetExtendedMessage (em);
        }
        d->ShowModal ();
        d->Destroy ();
@@ -109,6 +162,7 @@ message_dialog (wxWindow* parent, wxString m)
        d->Destroy ();
 }
 
+/** @return true if the user answered "yes" */
 bool
 confirm_dialog (wxWindow* parent, wxString m)
 {
@@ -157,6 +211,20 @@ checked_set (FilePickerCtrl* widget, boost::filesystem::path value)
        }
 }
 
+void
+checked_set (wxDirPickerCtrl* widget, boost::filesystem::path value)
+{
+       if (widget->GetPath() != std_to_wx (value.string())) {
+               if (value.empty()) {
+                       /* Hack to make wxWidgets clear the control when we are passed
+                          an empty value.
+                       */
+                       value = " ";
+               }
+               widget->SetPath (std_to_wx (value.string()));
+       }
+}
+
 void
 checked_set (wxSpinCtrl* widget, int value)
 {
@@ -230,6 +298,14 @@ checked_set (wxTextCtrl* widget, string value)
        }
 }
 
+void
+checked_set (PasswordEntry* entry, string value)
+{
+       if (entry->get() != value) {
+               entry->set(value);
+       }
+}
+
 void
 checked_set (wxTextCtrl* widget, wxString value)
 {
@@ -299,6 +375,9 @@ dcpomatic_setup_i18n ()
                   of wxWidgets.
                */
                locale->AddCatalog (wxT ("dcpomatic2-wxstd"));
+
+               /* Fedora 29 (at least) installs wxstd3.mo instead of wxstd.mo */
+               locale->AddCatalog (wxT ("wxstd3"));
 #endif
 
                locale->AddCatalog (wxT ("libdcpomatic2-wx"));
@@ -393,13 +472,10 @@ maybe_show_splash ()
 {
        wxSplashScreen* splash = 0;
        try {
-               if (!Config::have_existing ("config.xml")) {
-                       wxBitmap bitmap;
-                       boost::filesystem::path p = shared_path () / "splash.png";
-                       if (bitmap.LoadFile (std_to_wx (p.string ()), wxBITMAP_TYPE_PNG)) {
-                               splash = new wxSplashScreen (bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, 0, 0, -1);
-                               wxYield ();
-                       }
+               wxBitmap bitmap;
+               if (bitmap.LoadFile(bitmap_path("splash"), wxBITMAP_TYPE_PNG)) {
+                       splash = new wxSplashScreen (bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, 0, 0, -1);
+                       wxYield ();
                }
        } catch (boost::filesystem::filesystem_error& e) {
                /* Maybe we couldn't find the splash image; never mind */
@@ -408,12 +484,6 @@ maybe_show_splash ()
        return splash;
 }
 
-boost::filesystem::path
-path_from_file_dialog (wxFileDialog* dialog, string extension)
-{
-       return boost::filesystem::path(wx_to_std(dialog->GetPath())).replace_extension(extension);
-}
-
 double
 calculate_mark_interval (double mark_interval)
 {
@@ -436,3 +506,100 @@ calculate_mark_interval (double mark_interval)
 
        return mark_interval;
 }
+
+
+/** @return false if the task was cancelled */
+bool
+display_progress (wxString title, wxString task)
+{
+       JobManager* jm = JobManager::instance ();
+
+       wxProgressDialog progress (title, task, 100, 0, wxPD_CAN_ABORT);
+
+       bool ok = true;
+
+       while (jm->work_to_do()) {
+               dcpomatic_sleep_seconds (1);
+               if (!progress.Pulse()) {
+                       /* user pressed cancel */
+                       for (auto i: jm->get()) {
+                               i->cancel();
+                       }
+                       ok = false;
+                       break;
+               }
+       }
+
+       return ok;
+}
+
+
+int
+get_offsets (vector<Offset>& offsets)
+{
+       offsets.push_back (Offset(_("UTC-11"),  -11,  0));
+       offsets.push_back (Offset(_("UTC-10"),  -10,  0));
+       offsets.push_back (Offset(_("UTC-9"),    -9,  0));
+       offsets.push_back (Offset(_("UTC-8"),    -8,  0));
+       offsets.push_back (Offset(_("UTC-7"),    -7,  0));
+       offsets.push_back (Offset(_("UTC-6"),    -6,  0));
+       offsets.push_back (Offset(_("UTC-5"),    -5,  0));
+       offsets.push_back (Offset(_("UTC-4:30"), -4, 30));
+       offsets.push_back (Offset(_("UTC-4"),    -4,  0));
+       offsets.push_back (Offset(_("UTC-3:30"), -3, 30));
+       offsets.push_back (Offset(_("UTC-3"),    -3,  0));
+       offsets.push_back (Offset(_("UTC-2"),    -2,  0));
+       offsets.push_back (Offset(_("UTC-1"),    -1,  0));
+       int utc = offsets.size();
+       offsets.push_back (Offset(_("UTC")  ,     0,  0));
+       offsets.push_back (Offset(_("UTC+1"),     1,  0));
+       offsets.push_back (Offset(_("UTC+2"),     2,  0));
+       offsets.push_back (Offset(_("UTC+3"),     3,  0));
+       offsets.push_back (Offset(_("UTC+4"),     4,  0));
+       offsets.push_back (Offset(_("UTC+5"),     5,  0));
+       offsets.push_back (Offset(_("UTC+5:30"),  5, 30));
+       offsets.push_back (Offset(_("UTC+6"),     6,  0));
+       offsets.push_back (Offset(_("UTC+7"),     7,  0));
+       offsets.push_back (Offset(_("UTC+8"),     8,  0));
+       offsets.push_back (Offset(_("UTC+9"),     9,  0));
+       offsets.push_back (Offset(_("UTC+9:30"),  9, 30));
+       offsets.push_back (Offset(_("UTC+10"),   10,  0));
+       offsets.push_back (Offset(_("UTC+11"),   11,  0));
+       offsets.push_back (Offset(_("UTC+12"),   12,  0));
+
+       return utc;
+}
+
+
+wxString
+bitmap_path (string name)
+{
+       boost::filesystem::path base;
+
+#ifdef DCPOMATIC_DEBUG
+       /* Hack to allow Linux and OS X to find icons when running from the source tree */
+       char* path = getenv ("DCPOMATIC_GRAPHICS");
+       if (path) {
+               base = path;
+       } else {
+               base = resources_path();
+       }
+#else
+       base = resources_path();
+#endif
+
+       boost::filesystem::path p = base / String::compose("%1.png", name);
+       return std_to_wx (p.string());
+}
+
+
+wxSize
+small_button_size (wxWindow* parent, wxString text)
+{
+       wxClientDC dc (parent);
+       wxSize size = dc.GetTextExtent (text);
+       size.SetHeight (-1);
+       size.IncBy (24, 0);
+       return size;
+}
+