Commit 330d62a4 authored by Harish Fulara's avatar Harish Fulara Committed by Alexandru Băluț

ui: welcome window integration

parent 7c53a243
Pipeline #16282 passed with stage
in 38 minutes and 53 seconds
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkScrolledWindow" id="scrolled_window">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<child>
<object class="GtkViewport" id="view_port">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkBox" id="topvbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkInfoBar" id="infobar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_close_button">True</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="spacing">6</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child internal-child="content_area">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="spacing">16</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="recent_projects_topvbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="margin_top">30</property>
<property name="margin_bottom">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="recent_projects_labelbox">
<property name="name">recent_projects_labelbox</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="recent_projects_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Recent Projects</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">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkListBox" id="recent_projects_listbox">
<property name="name">recent_projects_listbox</property>
<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">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
......@@ -6,36 +6,12 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<child>
<object class="GtkMenuItem" id="menu_new">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="action_name">win.new-project</property>
<property name="label" translatable="yes">New project</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_open">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="action_name">win.open-project</property>
<property name="label" translatable="yes">Open project...</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="menu_sep1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_save_as">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Save the current project under a new name or a different location</property>
<property name="action_name">win.save-as</property>
<property name="action_name">editor.save-as</property>
<property name="label" translatable="yes">Save As...</property>
<property name="use_underline">True</property>
</object>
......@@ -129,9 +105,9 @@
<object class="GtkMenuItem" id="menu_about">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="action_name">win.about</property>
<property name="label" translatable="yes">About</property>
<property name="use_underline">True</property>
<signal name="activate" handler="_aboutCb" swapped="no"/>
</object>
</child>
</object>
......
......@@ -29,7 +29,6 @@ from gi.repository import Gtk
from pitivi.configure import RELEASES_URL
from pitivi.configure import VERSION
from pitivi.dialogs.startupwizard import StartUpWizard
from pitivi.effects import EffectsManager
from pitivi.mainwindow import MainWindow
from pitivi.pluginmanager import PluginManager
......@@ -58,6 +57,7 @@ class Pitivi(Gtk.Application, Loggable):
action_log (UndoableActionLog): The undo/redo log for the current project.
effects (EffectsManager): The effects which can be applied to a clip.
gui (MainWindow): The main window of the app.
recent_manager (Gtk.RecentManager): Manages recently used projects.
project_manager (ProjectManager): The holder of the current project.
settings (GlobalSettings): The application-wide settings.
system (pitivi.utils.system.System): The system running the app.
......@@ -84,7 +84,7 @@ class Pitivi(Gtk.Application, Loggable):
self._last_action_time = Gst.util_get_timestamp()
self.gui = None
self.__welcome_wizard = None
self.recent_manager = Gtk.RecentManager.get_default()
self.__inhibit_cookies = {}
self._version_information = {}
......@@ -152,6 +152,7 @@ class Pitivi(Gtk.Application, Loggable):
self.project_manager.connect(
"new-project-loaded", self._newProjectLoaded)
self.project_manager.connect("project-closed", self._projectClosed)
self.project_manager.connect("project-saved", self.__project_saved_cb)
self._createActions()
self._syncDoUndo()
......@@ -198,27 +199,21 @@ class Pitivi(Gtk.Application, Loggable):
self.gui.present()
# No need to show the welcome wizard.
return
self.createMainWindow()
self.welcome_wizard.show()
@property
def welcome_wizard(self):
if not self.__welcome_wizard:
self.__welcome_wizard = StartUpWizard(self)
return self.__welcome_wizard
self.create_main_window()
self.gui.show_perspective(self.gui.greeter)
self.gui.show()
def createMainWindow(self):
def create_main_window(self):
if self.gui:
return
self.gui = MainWindow(self)
self.gui.setup_ui()
self.add_window(self.gui)
self.gui.checkScreenConstraints()
# We might as well show it.
self.gui.show()
def do_open(self, giofiles, unused_count, unused_hint):
assert giofiles
self.createMainWindow()
self.create_main_window()
self.gui.show()
if len(giofiles) > 1:
self.warning(
"Can open only one project file at a time. Ignoring the rest!")
......@@ -238,8 +233,6 @@ class Pitivi(Gtk.Application, Loggable):
self.warning(
"Not closing since running project doesn't want to close")
return False
if self.welcome_wizard:
self.welcome_wizard.hide()
if self.gui:
self.gui.destroy()
self.threads.stopAllThreads()
......@@ -276,13 +269,23 @@ class Pitivi(Gtk.Application, Loggable):
self._setScenarioFile(project.get_uri())
def _newProjectLoaded(self, unused_project_manager, project):
uri = project.get_uri()
if uri:
# We remove the project from recent projects list
# and then re-add it to this list to make sure it
# gets positioned at the top of the recent projects list.
self.recent_manager.remove_item(uri)
self.recent_manager.add_item(uri)
self.action_log = UndoableActionLog()
self.action_log.connect("pre-push", self._action_log_pre_push_cb)
self.action_log.connect("commit", self._actionLogCommit)
self.action_log.connect("move", self._action_log_move_cb)
self.project_observer = ProjectObserver(project, self.action_log)
def __project_saved_cb(self, unused_project_manager, unused_project, uri):
if uri:
self.recent_manager.add_item(uri)
def _projectClosed(self, unused_project_manager, project):
if project.loaded:
self.action_log = None
......@@ -389,7 +392,7 @@ class Pitivi(Gtk.Application, Loggable):
self.project_manager.current_project.setModificationState(dirty)
# In the tests we do not want to create any gui
if self.gui is not None:
self.gui.showProjectStatus()
self.gui.editor.showProjectStatus()
def simple_inhibit(self, reason, flags):
"""Informs the session manager about actions to be inhibited.
......
......@@ -785,7 +785,7 @@ class TransformationProperties(Gtk.Expander, Loggable):
for prop in ["posx", "posy", "width", "height"]:
self.__update_spin_btn(prop)
# Keep the overlay stack in sync with the spin buttons values
self.app.gui.viewer.overlay_stack.update(self.source)
self.app.gui.editor.viewer.overlay_stack.update(self.source)
def __source_property_changed_cb(self, unused_source, unused_element, param):
self.__update_spin_btn(param.name)
......@@ -862,7 +862,7 @@ class TransformationProperties(Gtk.Expander, Loggable):
if value != cvalue:
self.__set_prop(prop, value)
self.app.gui.viewer.overlay_stack.update(self.source)
self.app.gui.editor.viewer.overlay_stack.update(self.source)
def __set_source(self, source):
if self.source:
......@@ -888,7 +888,7 @@ class TransformationProperties(Gtk.Expander, Loggable):
if source:
self._selected_clip = clip
self.__set_source(source)
self.app.gui.viewer.overlay_stack.select(source)
self.app.gui.editor.viewer.overlay_stack.select(source)
self.show()
return
......
# -*- coding: utf-8 -*-
# Pitivi video editor
# Copyright (c) 2005, Edward Hervey <bilboed@bilboed.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
"""Pitivi's about dialog."""
from gettext import gettext as _
from gi.repository import GES
from gi.repository import Gst
from gi.repository import Gtk
from pitivi.configure import APPNAME
from pitivi.configure import APPURL
from pitivi.configure import GITVERSION
from pitivi.configure import in_devel
from pitivi.configure import VERSION
# pylint: disable=too-few-public-methods
class AboutDialog(Gtk.AboutDialog):
"""Pitivi's about dialog.
Displays info regarding Pitivi's version, license,
maintainers, contributors, etc.
Attributes:
app (Pitivi): The app.
"""
def __init__(self, app):
Gtk.AboutDialog.__init__(self)
self.set_program_name(APPNAME)
self.set_website(APPURL)
if in_devel():
version_str = _("Development version: %s") % GITVERSION
elif not app.isLatest():
version_str = _("Version %(cur_ver)s — %(new_ver)s is available") % \
{"cur_ver": GITVERSION,
"new_ver": app.getLatest()}
elif GITVERSION:
version_str = _("Version %s") % GITVERSION
else:
version_str = _("Version %s") % VERSION
self.set_version(version_str)
comments = ["",
"GES %s" % ".".join(map(str, GES.version())),
"GTK+ %s" % ".".join(map(str, (Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION))),
"GStreamer %s" % ".".join(map(str, Gst.version()))]
self.set_comments("\n".join(comments))
authors = [_("Current maintainers:"),
"Jean-François Fortin Tam <nekohayo@gmail.com>",
"Thibault Saunier <tsaunier@gnome.org>",
"Mathieu Duponchelle <mduponchelle1@gmail.com>",
"Alexandru Băluț <alexandru.balut@gmail.com>",
"",
_("Past maintainers:"),
"Edward Hervey <bilboed@bilboed.com>",
"Alessandro Decina <alessandro.decina@collabora.co.uk>",
"Brandon Lewis <brandon_lewis@berkeley.edu>",
"",
# Translators: this paragraph is to be translated, the list
# of contributors is shown dynamically as a clickable link
# below it
_("Contributors:\n" +
"A handwritten list here would...\n" +
"• be too long,\n" +
"• be frequently outdated,\n" +
"• not show their relative merit.\n\n" +
"Out of respect for our contributors, we point you instead to:\n"),
# Translators: keep the %s at the end of the 1st line
_("The list of contributors on Ohloh %s\n" +
"Or you can run: git shortlog -s -n")
% "http://ohloh.net/p/pitivi/contributors", ]
self.set_authors(authors)
# Translators: See
# https://developer.gnome.org/gtk3/stable/GtkAboutDialog.html#gtk-about-dialog-set-translator-credits
# for details on how this is used.
translators = _("translator-credits")
if translators != "translator-credits":
self.set_translator_credits(translators)
documenters = ["Jean-François Fortin Tam <nekohayo@gmail.com>", ]
self.set_documenters(documenters)
self.set_license_type(Gtk.License.LGPL_2_1)
self.set_icon_name("pitivi")
self.set_logo_icon_name("pitivi")
self.connect("response", self.__about_response_cb)
self.set_transient_for(app.gui)
@staticmethod
def __about_response_cb(dialog, unused_response):
dialog.destroy()
# -*- coding: utf-8 -*-
# Pitivi video editor
# Copyright (c) 2005, Edward Hervey <bilboed@bilboed.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
"""Dialog for browsing through projects to open an existing project."""
from gettext import gettext as _
from gi.repository import GES
from gi.repository import Gtk
# pylint: disable=too-few-public-methods
class BrowseProjectsDialog(Gtk.FileChooserDialog):
"""Displays the Gtk.FileChooserDialog for browsing projects.
Attributes:
app (Pitivi): The app.
"""
def __init__(self, app):
Gtk.FileChooserDialog.__init__(self)
self.set_title(_("Open File..."))
self.set_transient_for(app.gui)
self.set_action(Gtk.FileChooserAction.OPEN)
self.add_buttons(_("Cancel"), Gtk.ResponseType.CANCEL,
_("Open"), Gtk.ResponseType.OK)
self.set_default_response(Gtk.ResponseType.OK)
self.set_select_multiple(False)
# TODO: Remove this set_current_folder call when GTK bug 683999 is
# fixed
self.set_current_folder(app.settings.lastProjectFolder)
formatter_assets = GES.list_assets(GES.Formatter)
formatter_assets.sort(
key=lambda x: - x.get_meta(GES.META_FORMATTER_RANK))
for format_ in formatter_assets:
filt = Gtk.FileFilter()
filt.set_name(format_.get_meta(GES.META_DESCRIPTION))
filt.add_pattern("*%s" %
format_.get_meta(GES.META_FORMATTER_EXTENSION))
self.add_filter(filt)
default = Gtk.FileFilter()
default.set_name(_("All supported formats"))
default.add_custom(Gtk.FileFilterFlags.URI, self.__can_load_uri, None)
self.add_filter(default)
# pylint: disable=bare-except
@staticmethod
def __can_load_uri(filterinfo, unused_uri):
try:
return GES.Formatter.can_load_uri(filterinfo.uri)
except:
return False
# -*- coding: utf-8 -*-
# Pitivi video editor
# Copyright (c) 2010 Mathieu Duponchelle <seeed@laposte.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
import os
from gettext import gettext as _
from gi.repository import Gdk
from gi.repository import GES
from gi.repository import Gtk
from pitivi.check import missing_soft_deps
from pitivi.configure import get_ui_dir
from pitivi.dialogs.depsmanager import DepsManager
from pitivi.shortcuts import show_shortcuts
from pitivi.utils.misc import show_user_manual
from pitivi.utils.ui import fix_infobar
class StartUpWizard(object):
"""A Wizard displaying recent projects.
Allows the user to:
- create a new project and open the settings dialog (Create button),
- create a new project with the default settings (dialog close or ESC),
- load a recently opened project (double click recent chooser),
- load a project (Browse button),
- see the quick start manual (User Manual button).
"""
@staticmethod
def _userManualCb(unused_button):
"""Handles a click on the Help button."""
show_user_manual()
def _cheatsheetCb(self, unused_button):
"""Shows the shortcuts cheatsheet."""
show_shortcuts(self.app)
def __init__(self, app):
self.app = app
self.builder = Gtk.Builder()
self.builder.add_from_file(
os.path.join(get_ui_dir(), "startupwizard.ui"))
self.builder.connect_signals(self)
self.window = self.builder.get_object("window1")
# The line below is supremely important, it will NOT work if set
# only by the GtkBuilder file. The DIALOG TypeHint allows proper
# attachment (visually, behaviorally) to MainWindow, and
# prevents other windows from showing on top too easily.
self.window.set_type_hint(Gdk.WindowTypeHint.DIALOG)
self.recent_chooser = self.builder.get_object("recentchooser2")
# FIXME: gtk creates a combo box with only one item, but there is no
# simple way to hide it.
_filter = Gtk.RecentFilter()
_filter.set_name(_("Projects"))
for asset in GES.list_assets(GES.Formatter):
_filter.add_pattern(
'*.' + asset.get_meta(GES.META_FORMATTER_EXTENSION))
self.recent_chooser.add_filter(_filter)
missing_button = self.builder.get_object("missing_deps_button")
if not missing_soft_deps:
missing_button.hide()
vbox = self.builder.get_object("topvbox")
self.infobar = Gtk.InfoBar()
fix_infobar(self.infobar)
vbox.pack_start(self.infobar, True, True, 0)
if self.app.getLatest():
self._appVersionInfoReceivedCb(self.app, None)
else:
self.app.connect(
"version-info-received", self._appVersionInfoReceivedCb)
def _newProjectCb(self, unused_button):
"""Handles a click on the New (Project) button."""
self.app.project_manager.newBlankProject()
def _loadCb(self, unused_recent_chooser):
"""Handles choosing a project on the recent chooser.
This calls the project manager to load the associated URI.
"""
uri = self.recent_chooser.get_current_uri()
self.app.project_manager.loadProject(uri)
def _keyPressCb(self, unused_widget, event):
"""Handles a key press event on the dialog."""
if event.keyval == Gdk.KEY_Escape:
# The user pressed "Esc".
self.app.project_manager.newBlankProject()
def _onBrowseButtonClickedCb(self, unused_button6):
"""Handles a click on the Browse button."""
self.app.gui.openProject()
def _onMissingDepsButtonClickedCb(self, unused_button):
"""Handles a click on the Missing Deps button."""
DepsManager(self.app, parent_window=self.window)
def _deleteCb(self, unused_widget, unused_event):
"""Handles a click on the X button of the dialog."""
self.app.project_manager.newBlankProject()
return True
def show(self):
if self.window.props.visible:
return
self.window.set_transient_for(self.app.gui)
self.window.show()
project_manager = self.app.project_manager
project_manager.connect("new-project-loading", self._projectLoadingCb)
def hide(self):
if not self.window.props.visible:
return
self.window.hide()
project_manager = self.app.project_manager
project_manager.disconnect_by_func(self._projectLoadingCb)
def _projectLoadingCb(self, unused_project_manager, unused_uri):
"""Handles the start of a project load operation."""
self.hide()
def _appVersionInfoReceivedCb(self, app, unused_version_information):
"""Handles new version info."""
if app.isLatest():
# current version, don't show message
return
latest_version = app.getLatest()
if self.app.settings.lastCurrentVersion != latest_version:
# new latest version, reset counter
self.app.settings.lastCurrentVersion = latest_version
self.app.settings.displayCounter = 0
if self.app.settings.displayCounter >= 5:
# current version info already showed 5 times, don't show again
return
# increment counter, create infobar and show info
self.app.settings.displayCounter = self.app.settings.displayCounter + 1
text = _("Pitivi %s is available.") % latest_version
label = Gtk.Label(label=text)
self.infobar.get_content_area().add(label)
self.infobar.set_message_type(Gtk.MessageType.INFO)
self.infobar.show_all()
# -*- coding: utf-8 -*-
# Pitivi video editor
# Copyright (c) 2005, Edward Hervey <bilboed@bilboed.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
import os
from gettext import gettext as _
from time import time
from urllib.parse import unquote
from gi.repository import Gdk
from gi.repository import GES
from gi.repository import Gio
from gi.repository import GstPbutils
from gi.repository import Gtk
from pitivi.clipproperties import ClipProperties
from pitivi.configure import APPNAME
from pitivi.configure import get_ui_dir
from pitivi.dialogs.prefs import PreferencesDialog
from pitivi.effects import EffectListWidget
from pitivi.mediafilespreviewer import PreviewWidget
from pitivi.medialibrary import AssetThumbnail
from pitivi.medialibrary import MediaLibraryWidget
from pitivi.perspective import Perspective
from pitivi.project import ProjectSettingsDialog
from pitivi.settings import GlobalSettings
from pitivi.tabsmanager import BaseTabs
from pitivi.timeline.timeline import TimelineContainer
from pitivi.titleeditor import TitleEditor
from pitivi.transitions import TransitionsListWidget
from pitivi.utils.loggable import Loggable
from pitivi.utils.misc import path_from_uri
from pitivi.utils.ui import beautify_missing_asset
from pitivi.utils.ui import beautify_time_delta
from pitivi.utils.ui import clear_styles
from pitivi.utils.ui import info_name
from pitivi.utils.ui import PADDING
from pitivi.utils.ui import SPACING
from pitivi.utils.ui import TIMELINE_CSS
from pitivi.viewer.viewer import ViewerContainer
GlobalSettings.addConfigSection("main-window")
GlobalSettings.addConfigOption('mainWindowHPanePosition',