[pitivi] projectsettings: Use ComboBox instead of TreeView for presets
- From: Thibault Saunier <tsaunier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] projectsettings: Use ComboBox instead of TreeView for presets
- Date: Wed, 25 Nov 2015 09:54:57 +0000 (UTC)
commit a04700ee2b23717e93dd42176927fea8131e8dec
Author: Alexandru Băluț <alexandru balut gmail com>
Date: Tue May 12 17:34:08 2015 +0200
projectsettings: Use ComboBox instead of TreeView for presets
This uses a bit more vertical space but saves a lot of horizontal space
and makes the UI less cluttered.
Differential Revision: https://phabricator.freedesktop.org/D356
Reviewed-by: Thibault Saunier <tsaunier gnome org>
data/ui/projectsettings.ui | 505 +++++++++++++++++++-------------------------
pitivi/mainwindow.py | 6 +-
pitivi/preset.py | 34 ++--
pitivi/project.py | 279 ++++++++++++-------------
pitivi/render.py | 8 +-
5 files changed, 370 insertions(+), 462 deletions(-)
---
diff --git a/data/ui/projectsettings.ui b/data/ui/projectsettings.ui
index 1bea536..5d1a2ac 100644
--- a/data/ui/projectsettings.ui
+++ b/data/ui/projectsettings.ui
@@ -45,17 +45,6 @@
</row>
</data>
</object>
- <object class="GtkListStore" id="model3">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">25 FPS</col>
- </row>
- </data>
- </object>
<object class="GtkDialog" id="project-settings-dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
@@ -129,8 +118,126 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
+ <property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
+ <object class="GtkBox" id="video_preset">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Preset:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="video_presets_combo">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="combobox-entry">
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="video_preset_menubutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="video-preset-infobar">
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="message_type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="infobar-action_area2">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="layout_style">center</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox" id="infobar-content_area2">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="video-preset-error-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkBox" id="video_details">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -229,6 +336,7 @@
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
+ <property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="_constrainSarButtonToggledCb"
swapped="no"/>
</object>
@@ -282,6 +390,7 @@
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
+ <property name="xalign">0.5</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="_selectDarRadiobuttonToggledCb"
swapped="no"/>
@@ -332,6 +441,7 @@
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
+ <property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<property name="group">select_dar_radiobutton</property>
</object>
@@ -381,7 +491,6 @@
<object class="GtkComboBox" id="frame_rate_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="model">model3</property>
<child>
<object class="GtkCellRendererText" id="renderer3"/>
<attributes>
@@ -409,20 +518,55 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">0</property>
+ <property name="position">2</property>
</packing>
</child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Video</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkBox" id="audio_tab">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
<child>
- <object class="GtkBox" id="video_preset">
+ <object class="GtkBox" id="audio_preset">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="orientation">vertical</property>
+ <property name="halign">start</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkLabel" id="label11">
+ <object class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="label" translatable="yes">Video Preset</property>
+ <property name="label" translatable="yes">Preset:</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
@@ -434,45 +578,14 @@
</packing>
</child>
<child>
- <object class="GtkInfoBar" id="video-preset-infobar">
- <property name="app_paintable">True</property>
+ <object class="GtkComboBox" id="audio_presets_combo">
+ <property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="message_type">error</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="infobar-action_area2">
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="layout_style">center</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child internal-child="content_area">
- <object class="GtkBox" id="infobar-content_area2">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkLabel" id="video-preset-error-label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="combobox-entry1">
+ <property name="can_focus">True</property>
</object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
</child>
</object>
<packing>
@@ -482,122 +595,81 @@
</packing>
</child>
<child>
- <object class="GtkScrolledWindow" id="scrolledwindow2">
+ <object class="GtkMenuButton" id="audio_preset_menubutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="shadow_type">in</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
<child>
- <object class="GtkTreeView" id="video_preset_treeview">
+ <object class="GtkImage" id="image2">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection1"/>
- </child>
+ <property name="can_focus">False</property>
+ <property name="icon_name">open-menu-symbolic</property>
</object>
</child>
</object>
<packing>
- <property name="expand">True</property>
+ <property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
- <child>
- <object class="GtkToolbar" id="video_presets_toolbar">
- <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="audio-preset-infobar">
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="message_type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="infobar-action_area3">
<property name="can_focus">False</property>
- <property name="show_arrow">False</property>
- <property name="icon_size">1</property>
- <child>
- <object class="GtkToolButton" id="add_video_preset_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip_text" translatable="yes">Create a new
preset</property>
- <property name="icon_name">list-add-symbolic</property>
- <signal name="clicked" handler="_addVideoPresetButtonClickedCb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
+ <property name="orientation">vertical</property>
+ <property name="layout_style">center</property>
<child>
- <object class="GtkToolButton" id="remove_video_preset_button">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Remove the selected
preset</property>
- <property name="icon_name">list-remove-symbolic</property>
- <signal name="clicked" handler="_removeVideoPresetButtonClickedCb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
+ <placeholder/>
</child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox" id="infobar-content_area3">
+ <property name="can_focus">False</property>
<child>
- <object class="GtkToolButton" id="save_video_preset_button">
+ <object class="GtkLabel" id="audio-preset-error-label">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Save changes to the
currently selected preset</property>
- <property name="icon_name">document-save-symbolic</property>
- <signal name="clicked" handler="_saveVideoPresetButtonClickedCb"
swapped="no"/>
+ <property name="can_focus">False</property>
+ <property name="opacity">0.99000000022351742</property>
</object>
<packing>
<property name="expand">False</property>
- <property name="homogeneous">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
</object>
<packing>
- <property name="expand">False</property>
+ <property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">3</property>
+ <property name="position">0</property>
</packing>
</child>
</object>
<packing>
- <property name="expand">True</property>
+ <property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label6">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Video</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="frame2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <child>
- <object class="GtkAlignment" id="alignment2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkBox" id="audio_tab">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="border_width">12</property>
- <property name="spacing">12</property>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
@@ -624,7 +696,7 @@
<object class="GtkComboBox" id="channels_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="model">model3</property>
+ <property name="halign">start</property>
<child>
<object class="GtkCellRendererText" id="renderer4"/>
<attributes>
@@ -658,7 +730,7 @@
<object class="GtkComboBox" id="sample_rate_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="model">model3</property>
+ <property name="halign">start</property>
<child>
<object class="GtkCellRendererText" id="renderer5"/>
<attributes>
@@ -676,160 +748,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="audio_preset">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkLabel" id="label10">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Audio Preset</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkInfoBar" id="audio-preset-infobar">
- <property name="app_paintable">True</property>
- <property name="can_focus">False</property>
- <property name="message_type">error</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="infobar-action_area3">
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="layout_style">center</property>
- <child>
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child internal-child="content_area">
- <object class="GtkBox" id="infobar-content_area3">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkLabel" id="audio-preset-error-label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="audio_preset_treeview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection2"/>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="audio_presets_toolbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_size">1</property>
- <child>
- <object class="GtkToolButton" id="add_audio_preset_button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Create a new
preset</property>
- <property name="icon_name">list-add-symbolic</property>
- <signal name="clicked" handler="_addAudioPresetButtonClickedCb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="remove_audio_preset_button">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Remove the selected
preset</property>
- <property name="icon_name">list-remove-symbolic</property>
- <signal name="clicked" handler="_removeAudioPresetButtonClickedCb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="save_audio_preset_button">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">Save changes to the
currently selected preset</property>
- <property name="icon_name">document-save-symbolic</property>
- <signal name="clicked" handler="_saveAudioPresetButtonClickedCb"
swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
diff --git a/pitivi/mainwindow.py b/pitivi/mainwindow.py
index bbf2aed..fb4b27f 100644
--- a/pitivi/mainwindow.py
+++ b/pitivi/mainwindow.py
@@ -162,11 +162,11 @@ class PitiviMainWindow(Gtk.ApplicationWindow, Loggable):
pm.connect("missing-uri", self._projectManagerMissingUriCb)
def setupCss(self):
- self.css_provider = Gtk.CssProvider()
- self.css_provider.load_from_data(TIMELINE_CSS.encode('UTF-8'))
+ css_provider = Gtk.CssProvider()
+ css_provider.load_from_data(TIMELINE_CSS.encode('UTF-8'))
screen = Gdk.Screen.get_default()
style_context = self.get_style_context()
- style_context.add_provider_for_screen(screen, self.css_provider,
+ style_context.add_provider_for_screen(screen, css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
@staticmethod
diff --git a/pitivi/preset.py b/pitivi/preset.py
index 306bd43..ce5d048 100644
--- a/pitivi/preset.py
+++ b/pitivi/preset.py
@@ -19,21 +19,25 @@
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
+import json
import os.path
from gi.repository import Gst
from gi.repository import Gtk
-import json
from gettext import gettext as _
-from pitivi.render import CachedEncoderList
from pitivi.settings import xdg_data_home
from pitivi.utils.misc import isWritable
from pitivi.configure import get_renderpresets_dir, get_audiopresets_dir, get_videopresets_dir
from pitivi.utils import system
+# Presets created with this name by the app should have "volatile": True
+# so they cannot be saved.
+CUSTOM_PRESET_NAME = _("Custom")
+
+
class DuplicatePresetNameException(Exception):
"""Raised when an operation would result in a duplicated preset name."""
@@ -93,8 +97,7 @@ class PresetManager(object):
self.savePreset(preset_name)
def savePreset(self, preset_name):
- if preset_name == _("No preset"):
- return
+ assert preset_name != CUSTOM_PRESET_NAME
if os.path.isfile(self.user_path):
# We used to save presets as a single file instead of a directory
os.remove(self.user_path)
@@ -206,18 +209,14 @@ class PresetManager(object):
values = self.presets[preset]
self.cur_preset = preset
for field, (setter, getter) in self.widget_map.items():
- if values[field] != 0:
- setter(values[field])
- else:
- setter(self.presets[_("No preset")][field])
+ setter(values[field])
finally:
self.ignore_update_requests = False
def saveCurrentPreset(self):
"""Update the current preset values from the widgets and save it."""
- if self.cur_preset != _("No preset"):
- self._updatePreset()
- self.savePreset(self.cur_preset)
+ self._updatePreset()
+ self.savePreset(self.cur_preset)
def _updatePreset(self):
"""Copy the values from the widgets to the preset."""
@@ -234,7 +233,9 @@ class PresetManager(object):
return any((values[field] != getter()
for field, (setter, getter) in self.widget_map.items()))
- def removePreset(self, name):
+ def removePreset(self, name=None):
+ if name is None:
+ name = self.cur_preset
try:
# Deletes json file if exists
os.remove(self.presets[name]["filepath"])
@@ -258,14 +259,16 @@ class PresetManager(object):
def isSaveButtonSensitive(self):
"""Check if the Save button should be sensitive"""
- if not self.cur_preset or self.cur_preset == _("No preset"):
+ if not self.cur_preset:
+ return False
+ if "volatile" in self.presets[self.cur_preset]:
return False
try:
full_path = self.presets[self.cur_preset]["filepath"]
- (dir, name) = os.path.split(full_path)
except KeyError:
# This is a newly created preset that has not yet been saved
return True
+ (dir, name) = os.path.split(full_path)
if dir == self.default_path or not isWritable(full_path):
# default_path is the system-wide directory where the default
# presets are installed; they are not expected to be editable.
@@ -275,7 +278,7 @@ class PresetManager(object):
def isRemoveButtonSensitive(self):
"""Check if Remove buttons should be sensitive"""
- if not self.cur_preset or self.cur_preset == _("No preset"):
+ if not self.cur_preset:
return False
try:
full_path = self.presets[self.cur_preset]["filepath"]
@@ -387,6 +390,7 @@ class RenderPresetManager(PresetManager):
acodec = parser["acodec"]
vcodec = parser["vcodec"]
+ from pitivi.render import CachedEncoderList
cached_encs = CachedEncoderList()
if (acodec not in [fact.get_name() for fact in cached_encs.aencoders] or
vcodec not in [fact.get_name() for fact in cached_encs.vencoders] or
diff --git a/pitivi/project.py b/pitivi/project.py
index 378a69d..a216d5c 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -27,6 +27,7 @@ Project related classes
import os
from gi.repository import GstPbutils
from gi.repository import GES
+from gi.repository import Gio
from gi.repository import Gst
from gi.repository import Gtk
from gi.repository import GLib
@@ -38,9 +39,8 @@ from datetime import datetime
from gettext import gettext as _
from pwd import getpwuid
-from pitivi.undo.undo import UndoableAction
from pitivi.configure import get_ui_dir
-
+from pitivi.undo.undo import UndoableAction
from pitivi.utils.validate import has_validate, create_monitor
from pitivi.utils.misc import quote_uri, path_from_uri, isWritable, unicode_error_dialog
from pitivi.utils.pipeline import PipelineError, Seeker
@@ -1367,12 +1367,13 @@ class ProjectSettingsDialog():
def __init__(self, parent_window, project):
self.project = project
+ self.audio_presets = AudioPresetManager()
+ self.video_presets = VideoPresetManager()
+ self.preset_actions = {}
self._createUi()
self.window.set_transient_for(parent_window)
self._setupUiConstraints()
self.updateUI()
- self.createAudioNoPreset(self.audio_presets)
- self.createVideoNoPreset(self.video_presets)
def _createUi(self):
"""
@@ -1394,13 +1395,9 @@ class ProjectSettingsDialog():
self.author_entry = getObj("author_entry")
self.width_spinbutton = getObj("width_spinbutton")
self.height_spinbutton = getObj("height_spinbutton")
- self.save_audio_preset_button = getObj("save_audio_preset_button")
- self.save_video_preset_button = getObj("save_video_preset_button")
- self.audio_preset_treeview = getObj("audio_preset_treeview")
- self.video_preset_treeview = getObj("video_preset_treeview")
+ self.audio_presets_combo = getObj("audio_presets_combo")
+ self.video_presets_combo = getObj("video_presets_combo")
self.select_par_radiobutton = getObj("select_par_radiobutton")
- self.remove_audio_preset_button = getObj("remove_audio_preset_button")
- self.remove_video_preset_button = getObj("remove_video_preset_button")
self.constrain_sar_button = getObj("constrain_sar_button")
self.select_dar_radiobutton = getObj("select_dar_radiobutton")
self.video_preset_infobar = getObj("video-preset-infobar")
@@ -1409,13 +1406,16 @@ class ProjectSettingsDialog():
self.author_entry = getObj("author_entry")
self.year_spinbutton = getObj("year_spinbutton")
- # Set the shading style in the contextual toolbars below presets
- video_presets_toolbar = getObj("video_presets_toolbar")
- audio_presets_toolbar = getObj("audio_presets_toolbar")
- video_presets_toolbar.get_style_context().add_class(
- Gtk.STYLE_CLASS_INLINE_TOOLBAR)
- audio_presets_toolbar.get_style_context().add_class(
- Gtk.STYLE_CLASS_INLINE_TOOLBAR)
+ self.video_preset_menubutton = getObj("video_preset_menubutton")
+ self._createPresetMenu(self.video_preset_menubutton,
+ self._addVideoPresetCb,
+ self.video_presets,
+ self.video_presets_combo)
+ self.audio_preset_menubutton = getObj("audio_preset_menubutton")
+ self._createPresetMenu(self.audio_preset_menubutton,
+ self._addAudioPresetCb,
+ self.audio_presets,
+ self.audio_presets_combo)
def _setupUiConstraints(self):
"""
@@ -1461,10 +1461,10 @@ class ProjectSettingsDialog():
self.wg.addVertex(self.par_fraction_widget, signal="value-changed")
self.wg.addVertex(self.width_spinbutton, signal="value-changed")
self.wg.addVertex(self.height_spinbutton, signal="value-changed")
- self.wg.addVertex(self.save_audio_preset_button,
- update_func=self._updateAudioSaveButton)
- self.wg.addVertex(self.save_video_preset_button,
- update_func=self._updateVideoSaveButton)
+ self.wg.addVertex(self.audio_preset_menubutton,
+ update_func=self._updateAudioPresetMenuButton)
+ self.wg.addVertex(self.video_preset_menubutton,
+ update_func=self._updateVideoPresetMenuButton)
self.wg.addVertex(self.channels_combo, signal="changed")
self.wg.addVertex(self.sample_rate_combo, signal="changed")
@@ -1516,16 +1516,12 @@ class ProjectSettingsDialog():
edge_func=self.updateDarFromPar)
# Presets.
- self.audio_presets = AudioPresetManager()
- self.audio_presets.loadAll()
- self._fillPresetsTreeview(self.audio_preset_treeview,
- self.audio_presets,
- self._updateAudioPresetButtons)
- self.video_presets = VideoPresetManager()
- self.video_presets.loadAll()
- self._fillPresetsTreeview(self.video_preset_treeview,
- self.video_presets,
- self._updateVideoPresetButtons)
+ self._loadPresets(self.audio_presets,
+ self.audio_presets_combo,
+ self.audio_preset_menubutton)
+ self._loadPresets(self.video_presets,
+ self.video_presets_combo,
+ self.video_preset_menubutton)
# A map which tells which infobar should be used when displaying
# an error for a preset manager.
@@ -1547,14 +1543,14 @@ class ProjectSettingsDialog():
self.audio_presets, "sample-rate", self.sample_rate_combo)
self.wg.addEdge(
- self.par_fraction_widget, self.save_video_preset_button)
+ self.par_fraction_widget, self.video_preset_menubutton)
self.wg.addEdge(
- self.frame_rate_fraction_widget, self.save_video_preset_button)
- self.wg.addEdge(self.width_spinbutton, self.save_video_preset_button)
- self.wg.addEdge(self.height_spinbutton, self.save_video_preset_button)
+ self.frame_rate_fraction_widget, self.video_preset_menubutton)
+ self.wg.addEdge(self.width_spinbutton, self.video_preset_menubutton)
+ self.wg.addEdge(self.height_spinbutton, self.video_preset_menubutton)
- self.wg.addEdge(self.channels_combo, self.save_audio_preset_button)
- self.wg.addEdge(self.sample_rate_combo, self.save_audio_preset_button)
+ self.wg.addEdge(self.channels_combo, self.audio_preset_menubutton)
+ self.wg.addEdge(self.sample_rate_combo, self.audio_preset_menubutton)
def bindPar(self, mgr):
@@ -1579,76 +1575,80 @@ class ProjectSettingsDialog():
lambda x: widget.set_value(float(x)),
lambda: int(widget.get_value()))
- def _fillPresetsTreeview(self, treeview, mgr, update_buttons_func):
+ def _createPresetMenu(self, button, new_func, mgr, combo):
+ entry = combo.get_child()
+ style_context = entry.get_style_context()
+ style_provider = Gtk.CssProvider()
+ style_provider.load_from_data("GtkEntry.unsaved {font-style:italic;}".encode('UTF-8'))
+ style_context.add_provider(style_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
+
+ action_group = Gio.SimpleActionGroup()
+ menu_model = Gio.Menu()
+ self.preset_actions[button] = {}
+
+ action = Gio.SimpleAction.new("new", None)
+ action.connect("activate", new_func)
+ action_group.insert(action)
+ menu_model.append(_("New"), "preset.%s" % action.get_name())
+ self.preset_actions[button][action.get_name()] = action
+
+ action = Gio.SimpleAction.new("remove", None)
+ action.connect("activate", self._removePresetCb, button, combo, mgr)
+ action_group.insert(action)
+ menu_model.append(_("Remove"), "preset.%s" % action.get_name())
+ self.preset_actions[button][action.get_name()] = action
+
+ action = Gio.SimpleAction.new("save", None)
+ action.connect("activate", self._savePresetCb, mgr, button, combo)
+ action_group.insert(action)
+ menu_model.append(_("Save"), "preset.%s" % action.get_name())
+ self.preset_actions[button][action.get_name()] = action
+
+ menu = Gtk.Menu.new_from_model(menu_model)
+ menu.insert_action_group("preset", action_group)
+ button.set_popup(menu)
+
+ def _updatePresetActions(self, button, combo, mgr):
+ entry = combo.get_child()
+ preset_name = entry.get_text()
+ can_save = mgr.cur_preset != preset_name or mgr.isSaveButtonSensitive()
+ self.preset_actions[button]["save"].set_enabled(can_save)
+ if can_save:
+ entry.get_style_context().add_class("unsaved")
+ else:
+ entry.get_style_context().remove_class("unsaved")
+
+ can_remove = mgr.isRemoveButtonSensitive()
+ self.preset_actions[button]["remove"].set_enabled(can_remove)
+
+ def _loadPresets(self, mgr, combo, button):
"""Set up the specified treeview to display the specified presets.
- @param treeview: The treeview for displaying the presets.
- @type treeview: TreeView
@param mgr: The preset manager.
@type mgr: PresetManager
- @param update_buttons_func: A function which updates the buttons for
- removing and saving a preset, enabling or disabling them accordingly.
- @type update_buttons_func: function
+ @param combo: The combobox displaying the presets.
+ @type combo: Gtk.ComboBox
+ @param button: The menubutton associated with the combobox.
+ @type button: Gtk.MenuButton
"""
- renderer = Gtk.CellRendererText()
- renderer.props.editable = True
- column = Gtk.TreeViewColumn("Preset", renderer, text=0)
- treeview.append_column(column)
- treeview.props.headers_visible = False
+ mgr.loadAll()
model = mgr.getModel()
- treeview.set_model(model)
- model.connect(
- "row-inserted", self._newPresetCb, column, renderer, treeview)
- renderer.connect("edited", self._presetNameEditedCb, mgr)
- renderer.connect(
- "editing-started", self._presetNameEditingStartedCb, mgr)
- treeview.get_selection().connect("changed", self._presetChangedCb, mgr,
- update_buttons_func)
- treeview.connect("focus-out-event", self._treeviewDefocusedCb, mgr)
-
- def createAudioNoPreset(self, mgr):
- mgr.prependPreset(_("No preset"), {
- "channels": self.project.audiochannels,
- "sample-rate": self.project.audiorate})
-
- def createVideoNoPreset(self, mgr):
- mgr.prependPreset(_("No preset"), {
- "par": self.project.videopar,
- "frame-rate": self.project.videorate,
- "height": self.project.videoheight,
- "width": self.project.videowidth})
-
- def _newPresetCb(self, unused_model, path, unused_iter_, column, renderer, treeview):
- """ Handle the addition of a preset to the model of the preset manager. """
- treeview.set_cursor_on_cell(path, column, renderer, start_editing=True)
- treeview.grab_focus()
-
- def _presetNameEditedCb(self, unused_renderer, path, new_text, mgr):
- """Handle the renaming of a preset."""
- try:
- mgr.renamePreset(path, new_text)
- except DuplicatePresetNameException:
- error_markup = _('"%s" already exists.') % new_text
- self._showPresetManagerError(mgr, error_markup)
+ combo.set_model(model)
+ combo.set_entry_text_column(0)
+ combo.connect("changed", self._presetChangedCb, mgr, button)
- def _presetNameEditingStartedCb(self, unused_renderer, unused_editable, unused_path, mgr):
- """Handle the start of a preset renaming."""
- self._hidePresetManagerError(mgr)
-
- def _presetChangedCb(self, selection, mgr, update_preset_buttons_func):
+ def _presetChangedCb(self, combo, mgr, button):
"""Handle the selection of a preset."""
- model, iter_ = selection.get_selected()
- if iter_:
- preset = model[iter_][0]
+ preset_name = combo.get_active_id()
+ if preset_name:
+ # The user selected a preset.
+ mgr.restorePreset(preset_name)
+ self._updateSar()
+ self._updatePresetActions(button, combo, mgr)
+ self._hidePresetManagerError(mgr)
else:
- preset = None
- mgr.restorePreset(preset)
- self._updateSar()
- update_preset_buttons_func()
- self._hidePresetManagerError(mgr)
-
- def _treeviewDefocusedCb(self, unused_widget, unused_event, mgr):
- self._hidePresetManagerError(mgr)
+ # The user is editing the preset name.
+ self._updatePresetActions(button, combo, mgr)
def _showPresetManagerError(self, mgr, error_markup):
"""Show the specified error on the infobar associated with the manager.
@@ -1711,27 +1711,16 @@ class ProjectSettingsDialog():
i += 1
return preset_name
- def _addAudioPresetButtonClickedCb(self, unused_button):
+ def _addAudioPresetCb(self, unused_action, unused_param):
preset_name = self._getUniquePresetName(self.audio_presets)
self.audio_presets.addPreset(preset_name, {
"channels": get_combo_value(self.channels_combo),
"sample-rate": get_combo_value(self.sample_rate_combo),
})
- self.audio_presets.restorePreset(preset_name)
- self._updateAudioPresetButtons()
+ self.audio_presets_combo.set_active_id(preset_name)
+ self._updateAudioPresetMenu()
- def _removeAudioPresetButtonClickedCb(self, unused_button):
- selection = self.audio_preset_treeview.get_selection()
- model, iter_ = selection.get_selected()
- if iter_:
- self.audio_presets.removePreset(model[iter_][0])
-
- def _saveAudioPresetButtonClickedCb(self, unused_button):
- self.audio_presets.saveCurrentPreset()
- self.save_audio_preset_button.set_sensitive(False)
- self.remove_audio_preset_button.set_sensitive(True)
-
- def _addVideoPresetButtonClickedCb(self, unused_button):
+ def _addVideoPresetCb(self, unused_action, unused_param):
preset_name = self._getUniquePresetName(self.video_presets)
self.video_presets.addPreset(preset_name, {
"width": int(self.width_spinbutton.get_value()),
@@ -1739,37 +1728,32 @@ class ProjectSettingsDialog():
"frame-rate": self.frame_rate_fraction_widget.getWidgetValue(),
"par": self.par_fraction_widget.getWidgetValue(),
})
- self.video_presets.restorePreset(preset_name)
- self._updateVideoPresetButtons()
-
- def _removeVideoPresetButtonClickedCb(self, unused_button):
- selection = self.video_preset_treeview.get_selection()
- model, iter_ = selection.get_selected()
- if iter_:
- self.video_presets.removePreset(model[iter_][0])
-
- def _saveVideoPresetButtonClickedCb(self, unused_button):
- self.video_presets.saveCurrentPreset()
- self.save_video_preset_button.set_sensitive(False)
- self.remove_video_preset_button.set_sensitive(True)
-
- def _updateAudioPresetButtons(self):
- can_save = self.audio_presets.isSaveButtonSensitive()
- self.save_audio_preset_button.set_sensitive(can_save)
- can_remove = self.audio_presets.isRemoveButtonSensitive()
- self.remove_audio_preset_button.set_sensitive(can_remove)
-
- def _updateVideoPresetButtons(self):
- self.save_video_preset_button.set_sensitive(
- self.video_presets.isSaveButtonSensitive())
- self.remove_video_preset_button.set_sensitive(
- self.video_presets.isRemoveButtonSensitive())
-
- def _updateAudioSaveButton(self, unused_in, button):
- button.set_sensitive(self.audio_presets.isSaveButtonSensitive())
-
- def _updateVideoSaveButton(self, unused_in, button):
- button.set_sensitive(self.video_presets.isSaveButtonSensitive())
+ self.video_presets_combo.set_active_id(preset_name)
+ self._updateVideoPresetMenu()
+
+ def _removePresetCb(self, unused_action, unused_param, button, combo, mgr):
+ mgr.removePreset()
+ self._updatePresetActions(button, combo, mgr)
+
+ def _savePresetCb(self, unused_action, unused_param, mgr, button, combo):
+ mgr.saveCurrentPreset()
+ self._updatePresetActions(button, combo, mgr)
+
+ def _updateAudioPresetMenuButton(self, unused_source, unused_target):
+ self._updateAudioPresetMenu()
+
+ def _updateAudioPresetMenu(self):
+ button = self.audio_preset_menubutton
+ combo = self.audio_presets_combo
+ self._updatePresetActions(button, combo, self.audio_presets)
+
+ def _updateVideoPresetMenuButton(self, unused_source, unused_target):
+ self._updateVideoPresetMenu()
+
+ def _updateVideoPresetMenu(self):
+ button = self.video_preset_menubutton
+ combo = self.video_presets_combo
+ self._updatePresetActions(button, combo, self.video_presets)
def darSelected(self):
return self.select_dar_radiobutton.props.active
@@ -1838,12 +1822,11 @@ class ProjectSettingsDialog():
year = datetime.now().year
self.year_spinbutton.get_adjustment().set_value(year)
- def updateMetadata(self):
+ def updateProject(self):
self.project.name = self.title_entry.get_text()
self.project.author = self.author_entry.get_text()
self.project.year = str(self.year_spinbutton.get_value_as_int())
- def updateSettings(self):
self.project.videowidth = int(self.width_spinbutton.get_value())
self.project.videoheight = int(self.height_spinbutton.get_value())
self.project.videopar = self.par_fraction_widget.getWidgetValue()
@@ -1854,7 +1837,7 @@ class ProjectSettingsDialog():
self.project.audiorate = get_combo_value(self.sample_rate_combo)
def _responseCb(self, unused_widget, response):
+ """Handle the dialog being closed."""
if response == Gtk.ResponseType.OK:
- self.updateSettings()
- self.updateMetadata()
+ self.updateProject()
self.window.destroy()
diff --git a/pitivi/render.py b/pitivi/render.py
index 7a169d5..ecc808d 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -39,6 +39,7 @@ from gettext import gettext as _
from pitivi import configure
from pitivi.check import missing_soft_deps
+from pitivi.preset import CUSTOM_PRESET_NAME
from pitivi.utils.loggable import Loggable
from pitivi.utils.misc import show_user_manual, path_from_uri
from pitivi.utils.ripple_update_group import RippleUpdateGroup
@@ -421,10 +422,11 @@ class RenderDialog(Loggable):
self.bindHeight(self.render_presets)
self.bindWidth(self.render_presets)
- self.createNoPreset(self.render_presets)
+ self.createVolatileCustomPreset(self.render_presets)
- def createNoPreset(self, mgr):
- mgr.prependPreset(_("No preset"), {
+ def createVolatileCustomPreset(self, mgr):
+ mgr.prependPreset(CUSTOM_PRESET_NAME, {
+ "volatile": True,
"channels": int(get_combo_value(self.channels_combo)),
"sample-rate": int(get_combo_value(self.sample_rate_combo)),
"acodec": get_combo_value(self.audio_encoder_combo).get_name(),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]