# (c) Copyright 2009-2015. CodeWeavers, Inc.
import os
import gobject
gobject.threads_init()
import gtk
import cxutils
import distversion
import bottlequery
import bottlecollection
import bottlemanagement
import cxguitools
import pyop
# for localization
from cxutils import cxgettext as _
class NoBottlesController(object):
def __init__(self, inCommand):
#----------------------------------------------------------------------
# Setup the GUI
#----------------------------------------------------------------------
self.xml = gtk.Builder()
self.xml.set_translation_domain("crossover")
self.xml.add_from_file(cxguitools.get_ui_path("nobottlesdlg"))
self.xml.connect_signals(self)
dlgWidget = self.xml.get_object("NoBottlesDialog")
icons = cxguitools.get_std_icon_list('cxrun')
dlgWidget.set_icon_list(*icons)
#----------------------------------------------------------------------------
# Set up progress bar
#----------------------------------------------------------------------------
progbar = self.xml.get_object("ProgBar")
progbar.set_pulse_step(.05)
progbar.hide()
#----------------------------------------------------------------------------
# Set up bottle type combo
#----------------------------------------------------------------------------
templatewidget = self.xml.get_object("bottletype")
liststore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
templatewidget.set_model(liststore)
index = 0
for template in sorted(bottlemanagement.template_list(), None, bottlemanagement.get_template_key):
new_row = liststore.append()
liststore.set_value(new_row, 0, bottlemanagement.get_template_name(template))
liststore.set_value(new_row, 1, template)
if template == "win7":
templatewidget.set_active(index)
index += 1
#----------------------------------------------------------------------------
# ...and bottle name. This part should be pretty safe since we know
# that there are no existing bottles.
#----------------------------------------------------------------------------
bottle_name_hint = _("New Bottle")
if not distversion.IS_MACOSX:
# Spaces cause trouble in Nautilus (GNOME bug 700320).
# So allow them but avoid them by default
bottle_name_hint = bottle_name_hint.replace(' ', '_')
bottleNameWidget = self.xml.get_object("newbottlename")
bottleNameWidget.set_text(bottlequery.unique_bottle_name(bottle_name_hint))
self.command = inCommand
commandWidget = self.xml.get_object("commandlabel")
commandWidget.set_text(self.command)
self.commandOp = None
self.set_widget_sensitivities(self)
dlgWidget.show()
def new_bottle_delete_text(self, caller, start, stop):
# pylint: disable=R0201
name = caller.get_text()
name = name[:start] + name[stop:]
if not cxutils.is_valid_bottlename(name):
caller.emit_stop_by_name("delete-text")
def new_bottle_insert_text(self, caller, new_text, _length, _user_data):
# pylint: disable=R0201
name = caller.get_text()
position = caller.get_position()
name = name[:position] + new_text + name[position:]
if not cxutils.is_valid_bottlename(name):
caller.emit_stop_by_name("insert-text")
def set_command(self, command):
commandEntry = self.xml.get_object("command")
commandEntry.set_text(command)
def cancel_clicked(self, caller):
self.xml.get_object("NoBottlesDialog").destroy()
self.quit_requested(caller)
def quit_requested(self, _caller):
# pylint: disable=R0201
cxguitools.toplevel_quit()
def progbar_pulse(self):
progBar = self.xml.get_object("ProgBar")
progBar.pulse()
return True
def set_widget_sensitivities(self, _caller):
if self.xml.get_object("newbottlename").get_text():
self.xml.get_object("createandrun").set_sensitive(True)
else:
self.xml.get_object("createandrun").set_sensitive(False)
def create_bottle_and_run(self, _caller):
dlgWidget = self.xml.get_object("NoBottlesDialog")
bottleNameWidget = self.xml.get_object("newbottlename")
self.bottlename = cxutils.string_to_unicode(bottleNameWidget.get_text())
templatewidget = self.xml.get_object("bottletype")
templatemodel = templatewidget.get_model()
template = templatemodel.get_value(templatewidget.get_active_iter(), 1)
progbar = self.xml.get_object("ProgBar")
newBottleOp = NewBottleOperation(self.bottlename, template, self)
progbar.show()
dlgWidget.set_sensitive(False)
self.animateEvent = gobject.timeout_add(100, self.progbar_pulse)
pyop.sharedOperationQueue.enqueue(newBottleOp)
def AddBottleFinished(self, op):
# This is a delegate method for the NewBottleOperation.
if not op.exitStatus[0]:
cxguitools.CXMessageDlg(primary=_("Could not create bottle"), secondary=op.exitStatus[1], message_type=gtk.MESSAGE_ERROR)
gobject.source_remove(self.animateEvent)
self.xml.get_object("ProgBar").hide()
dlgWidget = self.xml.get_object("NoBottlesDialog")
dlgWidget.set_sensitive(True)
else:
bottlecollection.sharedCollection().refresh()
setDefaultBottleOp = SetDefaultBottleOperation(self.bottlename, self, True)
pyop.sharedOperationQueue.enqueue(setDefaultBottleOp)
def MakeDefaultFinished(self):
# This is a delegate method for the SetDefaultBottleOperation. Once the bottle
# is created, we want to launch the requested command and exit.
gobject.source_remove(self.animateEvent)
args = [os.path.join(cxutils.CX_ROOT, "bin", "cxstart"),
"--bottle", self.bottlename, "--"]
args.extend(cxutils.cmdlinetoargv(self.command))
os.execv(args[0], args)
self.quit_requested(self)
class NewBottleOperation(pyop.PythonOperation):
def __init__(self, bottle_name, template, new_bottle_controller):
pyop.PythonOperation.__init__(self)
self.exitStatus = None
self.new_bottle_name = bottle_name
self.template = template
self.new_bottle_controller = new_bottle_controller
def __unicode__(self):
return "NewBottleOperation for " + self.new_bottle_name
def enqueued(self):
bottlecollection.sharedCollection().add_ignored_bottle(self.new_bottle_name)
pyop.PythonOperation.enqueued(self)
def main(self):
self.exitStatus = bottlemanagement.create_bottle(self.new_bottle_name, self.template)
def finish(self):
bottlecollection.sharedCollection().remove_ignored_bottle(self.new_bottle_name)
self.new_bottle_controller.AddBottleFinished(self)
pyop.PythonOperation.finish(self)
class SetDefaultBottleOperation(pyop.PythonOperation):
def __init__(self, bottle_name, main_window, state):
pyop.PythonOperation.__init__(self)
self.state = state
self.main_window = main_window
self.bottle_name = bottle_name
def __unicode__(self):
return "SetDefaultBottleOperation for " + self.bottle_name
def enqueued(self):
pyop.PythonOperation.enqueued(self)
def main(self):
bottlemanagement.set_default_bottle(self.bottle_name, self.state)
def finish(self):
bottlecollection.sharedCollection().refreshDefaultBottle()
self.main_window.MakeDefaultFinished()
pyop.PythonOperation.finish(self)