5ec9677460
So we have several nasty issues when using ignore-spm-downgrades here. First of all, calculate_world_updates should get the setting directly from SystemSettings instead of bugging developer asking for it. Secondly, calculate_world_updates should return a 4D tuple, also containing the matches ignored when ignore-spm-downgrades is enabled. Moreover, Spritz packages.py getPackageItem featured an unused argument, which has been dropped. I know this commit is a bitch because we are talking about changing API and affecting several files at once.
6120 lines
231 KiB
Python
6120 lines
231 KiB
Python
#!/usr/bin/python -tt
|
|
# -*- coding: iso-8859-1 -*-
|
|
# Yum Exteder (yumex) - A GUI for yum
|
|
# Copyright (C) 2006 Tim Lauridsen < tim<AT>yum-extender<DOT>org >
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
from __future__ import with_statement
|
|
import time, gtk, gobject, pango, thread, pty, sys
|
|
from etpgui.widgets import UI
|
|
from etpgui import CURRENT_CURSOR, busyCursor, normalCursor
|
|
from spritz_setup import const, cleanMarkupString, SpritzConf, unicode2htmlentities, fakeoutfile, fakeinfile
|
|
from entropy.i18n import _,_LOCALE
|
|
import packages
|
|
from entropy.exceptions import *
|
|
from entropy.const import *
|
|
from entropy.misc import TimeScheduled, ParallelTask
|
|
|
|
class MenuSkel:
|
|
|
|
def _getAllMethods(self):
|
|
result = {}
|
|
allAttrNames = self.__dict__.keys() + self._getAllClassAttributes()
|
|
for name in allAttrNames:
|
|
value = getattr(self, name)
|
|
if callable(value):
|
|
result[name] = value
|
|
return result
|
|
|
|
def _getAllClassAttributes(self):
|
|
nameSet = {}
|
|
for currClass in self._getAllClasses():
|
|
nameSet.update(currClass.__dict__)
|
|
result = nameSet.keys()
|
|
return result
|
|
|
|
def _getAllClasses(self):
|
|
result = [self.__class__]
|
|
i = 0
|
|
while i < len(result):
|
|
currClass = result[i]
|
|
result.extend(list(currClass.__bases__))
|
|
i = i + 1
|
|
return result
|
|
|
|
class NoticeBoardWindow(MenuSkel):
|
|
|
|
def __init__( self, window, entropy ):
|
|
|
|
from entropy.misc import rssFeed
|
|
self.rssFeed = rssFeed
|
|
self.Entropy = entropy
|
|
self.window = window
|
|
|
|
self.nb_ui = UI( const.GLADE_FILE, 'noticeBoardWindow', 'entropy' )
|
|
self.nb_ui.signal_autoconnect(self._getAllMethods())
|
|
self.nb_ui.noticeBoardWindow.set_transient_for(self.window)
|
|
|
|
mytxt = "<big><b>%s</b></big>\n<small>%s</small>" % (
|
|
_("Repositories Notice Board"),
|
|
_("Here below you will find a list of important news directly issued by your applications maintainers. Double click on each item to retrieve detailed info."),
|
|
)
|
|
self.nb_ui.noticeBoardLabel.set_markup(mytxt)
|
|
self.view = self.nb_ui.noticeView
|
|
self.model = self.setup_view()
|
|
|
|
|
|
def load(self, repoids):
|
|
self.repoids = repoids
|
|
self.show_data()
|
|
self.view.expand_all()
|
|
self.nb_ui.noticeBoardWindow.show_all()
|
|
|
|
def setup_view(self):
|
|
model = gtk.TreeStore( gobject.TYPE_PYOBJECT )
|
|
self.view.set_model( model )
|
|
self.create_text_column( _( "Notice" ), size = 200, expand = True, set_height = 40 )
|
|
return model
|
|
|
|
def text_data_func( self, column, cell, model, iterator ):
|
|
obj = model.get_value(iterator, 0)
|
|
if obj:
|
|
if obj.has_key('is_repo'):
|
|
cell.set_property('markup',"<big><b>%s</b></big>\n<small>%s</small>" % (cleanMarkupString(obj['name']),cleanMarkupString(obj['desc']),))
|
|
else:
|
|
mytxt = '<b><u>%s</u></b>\n<small><b>%s</b>: %s</small>' % (
|
|
cleanMarkupString(obj['pubDate']),
|
|
_("Title"),
|
|
cleanMarkupString(obj['title']),
|
|
)
|
|
cell.set_property('markup',mytxt)
|
|
cell.set_property('cell-background',obj['color'])
|
|
|
|
def create_text_column( self, hdr, size = None, expand = False, set_height = 0 ):
|
|
cell = gtk.CellRendererText()
|
|
if set_height: cell.set_property('height', set_height)
|
|
column = gtk.TreeViewColumn( hdr, cell )
|
|
column.set_cell_data_func( cell, self.text_data_func )
|
|
if size != None:
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( size )
|
|
column.set_resizable( False )
|
|
column.set_expand( expand )
|
|
self.view.append_column( column )
|
|
|
|
def on_noticeBoardWindow_delete_event(self, *myargs):
|
|
self.model.clear()
|
|
self.nb_ui.noticeBoardWindow.destroy()
|
|
del self.nb_ui
|
|
|
|
def on_closeNoticeBoardButton_clicked(self, widget):
|
|
self.on_noticeBoardWindow_delete_event(widget)
|
|
|
|
def on_noticeView_row_activated(self, widget, iterator, path):
|
|
( model, iterator ) = widget.get_selection().get_selected()
|
|
if model != None and iterator != None:
|
|
obj = model.get_value(iterator, 0)
|
|
if not obj.has_key('is_repo'):
|
|
my = RmNoticeBoardMenu(self.nb_ui.noticeBoardWindow)
|
|
my.load(obj)
|
|
|
|
def show_data(self):
|
|
self.model.clear()
|
|
colors = ["#CDEEFF","#AFCBDA"]
|
|
avail_repos = self.Entropy.SystemSettings['repositories']['available']
|
|
for repoid in self.repoids:
|
|
counter = 0
|
|
master_dict = {
|
|
'is_repo': True,
|
|
'name': repoid,
|
|
'desc': avail_repos[repoid].get('description'),
|
|
'path': self.repoids[repoid],
|
|
'color': colors[0]
|
|
}
|
|
parent = self.model.append( None, (master_dict,) )
|
|
try:
|
|
myrss = self.rssFeed(self.repoids[repoid],'','')
|
|
except:
|
|
continue
|
|
items, entries_len = myrss.getEntries()
|
|
items = items.copy()
|
|
items_keys = sorted(items.keys())
|
|
for key in items_keys:
|
|
counter += 1
|
|
mydict = items[key].copy()
|
|
mydict['color'] = colors[counter%len(colors)]
|
|
mydict['id'] = key
|
|
self.model.append( parent, (mydict,) )
|
|
|
|
class RemoteConnectionMenu(MenuSkel):
|
|
|
|
import entropy.dump as dumpTools
|
|
store_path = 'connection_manager'
|
|
def __init__( self, Entropy, verification_callback, window ):
|
|
|
|
self.Entropy = Entropy
|
|
# hostname, port, username, password, ssl will be passed as parameters
|
|
self.verification_callback = verification_callback
|
|
self.window = window
|
|
self.cm_ui = UI( const.GLADE_FILE, 'remoteConnManager', 'entropy' )
|
|
self.cm_ui.signal_autoconnect(self._getAllMethods())
|
|
self.cm_ui.remoteConnManager.set_transient_for(self.window)
|
|
self.cm_ui.remoteConnManager.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
self.connStore = gtk.ListStore( gobject.TYPE_PYOBJECT )
|
|
self.connView = self.cm_ui.connManagerConnView
|
|
self.connView.set_model(self.connStore)
|
|
self.button_pressed = False
|
|
self.loaded = False
|
|
self.parameters = None
|
|
self.connection_data = self.get_stored_connection_data()
|
|
self.setup_view()
|
|
if self.connection_data: self.set_connection_object(self.connection_data[0])
|
|
|
|
def on_connManagerAddConnButton_clicked(self, widget):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
def fake_callback_cb(s):
|
|
return True
|
|
|
|
input_params = [
|
|
('name',_("Connection name"),fake_callback,False),
|
|
('hostname',_("Hostname"),fake_callback,False),
|
|
('port',_("Port"),fake_callback,False),
|
|
('user',_("Username"),fake_callback,False),
|
|
('ssl',('checkbox',_('SSL Connection'),),fake_callback_cb,False),
|
|
]
|
|
data = self.Entropy.inputBox(
|
|
_('Choose what kind of test you would like to run'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
self.store_connection_data_item(data)
|
|
self.fill_connection_view()
|
|
self.store_connection_data()
|
|
|
|
def on_connManagerConnView_row_activated(self, treeview, path, column):
|
|
self.on_connManagerSetConnButton_clicked(treeview)
|
|
|
|
def set_connection_object(self, obj):
|
|
self.cm_ui.connManagerHostnameEntry.set_text(obj['hostname'])
|
|
self.cm_ui.connManagerPortSpinButton.set_value(float(obj['port']))
|
|
self.cm_ui.connManagerUsernameEntry.set_text(obj['user'])
|
|
self.cm_ui.connManagerPasswordEntry.set_text('')
|
|
self.cm_ui.connManagerSSLCheckButton.set_active(obj['ssl'])
|
|
|
|
def on_connManagerSetConnButton_clicked(self, widget):
|
|
model, myiter = self.connView.get_selection().get_selected()
|
|
if not myiter: return
|
|
obj = model.get_value(myiter, 0)
|
|
self.set_connection_object(obj)
|
|
|
|
def on_connManagerRemoveConnButton_clicked(self, widget):
|
|
model, myiter = self.connView.get_selection().get_selected()
|
|
if not myiter: return
|
|
obj = model.get_value(myiter, 0)
|
|
self.remove_connection_data_item(obj)
|
|
self.fill_connection_view()
|
|
self.store_connection_data()
|
|
|
|
def get_stored_connection_data(self):
|
|
obj = self.dumpTools.loadobj(self.store_path)
|
|
if not obj: return []
|
|
return obj
|
|
|
|
def remove_connection_data_item(self, item):
|
|
if item in self.connection_data:
|
|
self.connection_data.remove(item)
|
|
|
|
def store_connection_data_item(self, item):
|
|
self.connection_data.append(item)
|
|
|
|
def store_connection_data(self):
|
|
self.dumpTools.dumpobj(self.store_path, self.connection_data)
|
|
|
|
def fill_connection_view(self):
|
|
self.connStore.clear()
|
|
for item in self.connection_data:
|
|
self.connStore.append( (item,) )
|
|
self.connView.queue_draw()
|
|
|
|
def setup_view(self):
|
|
|
|
self.create_text_column( self.connView, _( "Connection" ), 'name', size = 200, expand = True)
|
|
self.create_text_column( self.connView, _( "Hostname" ), 'hostname', size = 100)
|
|
self.create_text_column( self.connView, _( "Port" ), 'port', size = 50)
|
|
|
|
# SSL
|
|
cell = gtk.CellRendererPixbuf()
|
|
column = gtk.TreeViewColumn( _("SSL"), cell ) # Document Type
|
|
column.set_cell_data_func( cell, self.ssl_pixbuf )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( 50 )
|
|
column.set_sort_column_id( -1 )
|
|
self.connView.append_column( column )
|
|
|
|
self.fill_connection_view()
|
|
|
|
|
|
def ssl_pixbuf( self, column, cell, model, myiter ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
if obj['ssl']:
|
|
cell.set_property( 'stock-id', 'gtk-apply' )
|
|
return
|
|
cell.set_property( 'stock-id', 'gtk-cancel' )
|
|
|
|
def get_data_text( self, column, cell, model, myiter, property ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj: cell.set_property('markup',obj[property])
|
|
|
|
def create_text_column( self, view, hdr, property, size, sortcol = None, expand = False, set_height = 0, cell_data_func = None, sort_col_id = -1):
|
|
if cell_data_func == None: cell_data_func = self.get_data_text
|
|
cell = gtk.CellRendererText()
|
|
if set_height: cell.set_property('height', set_height)
|
|
column = gtk.TreeViewColumn( hdr, cell )
|
|
column.set_resizable( True )
|
|
column.set_cell_data_func( cell, cell_data_func, property )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( size )
|
|
column.set_expand(expand)
|
|
column.set_sort_column_id( sort_col_id )
|
|
view.append_column( column )
|
|
return column
|
|
|
|
def load( self ):
|
|
bold_items = [
|
|
self.cm_ui.connManagerTitleLabel,
|
|
]
|
|
for item in bold_items:
|
|
item.set_markup("<b>%s</b>" % ( item.get_text(),))
|
|
|
|
self.loaded = True
|
|
self.cm_ui.remoteConnManager.show_all()
|
|
|
|
def run(self):
|
|
|
|
if not self.loaded:
|
|
return None
|
|
|
|
tries = 3
|
|
while tries:
|
|
|
|
while not self.button_pressed:
|
|
time.sleep(0.05)
|
|
while gtk.events_pending():
|
|
gtk.main_iteration()
|
|
continue
|
|
|
|
if self.parameters:
|
|
valid, error_msg = self.verification_callback(
|
|
self.parameters['hostname'],
|
|
self.parameters['port'],
|
|
self.parameters['username'],
|
|
self.parameters['password'],
|
|
self.parameters['ssl']
|
|
)
|
|
if not valid:
|
|
okDialog(self.window, error_msg, title = _("Connection Error"))
|
|
self.button_pressed = False
|
|
tries -= 1
|
|
continue
|
|
break
|
|
|
|
self.destroy()
|
|
if not tries:
|
|
return None
|
|
return self.parameters
|
|
|
|
def on_remoteConnEventBox_key_release_event(self, widget, event):
|
|
if event.string == "\r":
|
|
self.cm_ui.connManagerConnectButton.clicked()
|
|
return True
|
|
return False # propagate
|
|
|
|
def on_connManagerConnectButton_clicked(self, widget):
|
|
self.parameters = {
|
|
'hostname': self.cm_ui.connManagerHostnameEntry.get_text(),
|
|
'port': self.cm_ui.connManagerPortSpinButton.get_value(),
|
|
'username': self.cm_ui.connManagerUsernameEntry.get_text(),
|
|
'password': self.cm_ui.connManagerPasswordEntry.get_text(),
|
|
'ssl': self.cm_ui.connManagerSSLCheckButton.get_active()
|
|
}
|
|
self.button_pressed = True
|
|
|
|
def on_remoteConnCloseButton_clicked(self, widget):
|
|
self.parameters = None
|
|
self.button_pressed = True
|
|
|
|
def destroy( self ):
|
|
self.cm_ui.remoteConnManager.hide()
|
|
self.cm_ui.remoteConnManager.destroy()
|
|
|
|
class RepositoryManagerMenu(MenuSkel):
|
|
|
|
import threading
|
|
def __init__(self, Entropy, window):
|
|
self.do_debug = False
|
|
if etpUi['debug']: self.do_debug = True
|
|
self.BufferLock = self.threading.Lock()
|
|
import entropy.tools as entropyTools
|
|
self.entropyTools = entropyTools
|
|
self.Entropy = Entropy
|
|
self.window = window
|
|
self.sm_ui = UI( const.GLADE_FILE, 'repositoryManager', 'entropy' )
|
|
self.sm_ui.signal_autoconnect(self._getAllMethods())
|
|
self.sm_ui.repositoryManager.set_transient_for(self.window)
|
|
|
|
self.DataStore = None
|
|
self.DataView = None
|
|
self.QueueLock = self.threading.Lock()
|
|
self.OutputLock = self.threading.Lock()
|
|
self.paused_queue_id = None
|
|
self.is_processing = None
|
|
self.is_writing_output = False
|
|
self.Output = None
|
|
self.output_pause = False
|
|
self.queue_pause = False
|
|
self.ssl_mode = True
|
|
self.repos_loaded = False
|
|
self.PinboardData = {}
|
|
self.Queue = {}
|
|
|
|
self.setup_queue_view()
|
|
self.setup_pinboard_view()
|
|
self.setup_console()
|
|
|
|
self.QueueUpdater = TimeScheduled(5, self.update_queue_view)
|
|
self.OutputUpdater = TimeScheduled(0.5, self.update_output_view)
|
|
self.PinboardUpdater = TimeScheduled(60, self.update_pinboard_view)
|
|
self.notebook_pages = {
|
|
'queue': 0,
|
|
'commands': 1,
|
|
'data': 2,
|
|
'output': 3
|
|
}
|
|
self.dict_queue_keys = ['queue','processing','processed','errored']
|
|
self.DataScroll = self.sm_ui.dataViewScrollWin
|
|
self.DataViewBox = self.sm_ui.repoManagerDataViewBox
|
|
self.DataViewButtons = {}
|
|
self.setup_data_view_buttons()
|
|
self.data_tree_selection_mode = None
|
|
self.DataViewVbox = self.sm_ui.dataViewVbox
|
|
|
|
from entropy.client.services.system.interfaces import Client as SystemManagerClientInterface
|
|
from entropy.client.services.system.commands import Repository as SystemManagerRepositoryClientCommands
|
|
from entropy.client.services.system.methods import Repository as SystemManagerRepositoryMethodsInterface
|
|
self.Service = SystemManagerClientInterface(
|
|
self.Entropy,
|
|
MethodsInterface = SystemManagerRepositoryMethodsInterface,
|
|
ClientCommandsInterface = SystemManagerRepositoryClientCommands
|
|
)
|
|
self.CommandsStore = None
|
|
self.setup_commands_view()
|
|
self.fill_commands_view(self.Service.get_available_client_commands())
|
|
self.ServiceStatus = True
|
|
self.connection_done = False
|
|
self.setup_available_repositories()
|
|
|
|
def __del__(self):
|
|
if hasattr(self,'connection_done'):
|
|
if self.connection_done:
|
|
self.Service.kill_all_connections()
|
|
|
|
def uiLock(self, action):
|
|
self.sm_ui.repositoryManager.set_sensitive(not action)
|
|
|
|
def set_notebook_page(self, page):
|
|
self.sm_ui.repoManagerNotebook.set_current_page(page)
|
|
|
|
def setup_console(self):
|
|
|
|
self.clipboard = gtk.Clipboard()
|
|
self.pty = pty.openpty()
|
|
self.std_output = fakeoutfile(self.pty[1])
|
|
self.std_input = fakeinfile(self.pty[1])
|
|
|
|
# setup add repository window
|
|
self.console_menu_xml = gtk.glade.XML( const.GLADE_FILE, "terminalMenu",domain="entropy" )
|
|
self.console_menu = self.console_menu_xml.get_widget( "terminalMenu" )
|
|
self.console_menu_xml.signal_autoconnect(self)
|
|
|
|
from etpgui.widgets import SpritzConsole
|
|
self.SpritzConsole = SpritzConsole
|
|
self.console = self.SpritzConsole()
|
|
self.console.set_scrollback_lines(1024)
|
|
self.console.set_scroll_on_output(True)
|
|
self.console.set_pty(self.pty[0])
|
|
self.console.connect("button-press-event", self.on_console_click)
|
|
self.console.connect("commit",self.on_console_commit)
|
|
termScroll = gtk.VScrollbar(self.console.get_adjustment())
|
|
self.sm_ui.repoManagerVteBox.pack_start(self.console, True, True)
|
|
self.sm_ui.repoManagerTermScrollBox.pack_start(termScroll, False)
|
|
self.sm_ui.repoManagerTermHBox.show_all()
|
|
|
|
def debug_print(self, f, msg):
|
|
if self.do_debug: print "repoman debug:",f,msg
|
|
|
|
def clear_console(self):
|
|
self.std_output.text_written = []
|
|
self.std_input.text_read = ''
|
|
self.console.reset()
|
|
|
|
def clear_data_store_and_view(self):
|
|
self.debug_print("clear_data_store_and_view","enter")
|
|
self.reset_data_view()
|
|
self.hide_all_data_view_buttons()
|
|
self.DataViewVbox.queue_draw()
|
|
while gtk.events_pending():
|
|
gtk.main_iteration()
|
|
|
|
def reset_data_view(self):
|
|
if self.DataView != None:
|
|
self.debug_print("reset_data_view","removing old DataView")
|
|
self.DataScroll.remove(self.DataView)
|
|
self.DataScroll.queue_draw()
|
|
self.DataView.destroy()
|
|
self.DataView = None
|
|
self.debug_print("reset_data_view","removal of old DataView done")
|
|
|
|
def on_repoManagerConsoleEvent_enter_notify_event(self, widget, event):
|
|
self.console.grab_focus()
|
|
|
|
def on_console_click(self, widget, event):
|
|
if event.button == 3:
|
|
self.console_menu.popup( None, None, None, event.button, event.time )
|
|
return True
|
|
|
|
def on_console_commit(self, widget, txt, txtlen):
|
|
if txt == "\r":
|
|
self.on_repoManagerStdinEntry_activate(None, False, self.std_input.text_read)
|
|
self.std_input.text_read = ''
|
|
elif txt == '\x7f':
|
|
self.std_input.text_read = self.std_input.text_read[:-1]
|
|
else:
|
|
self.std_input.text_read += txt
|
|
|
|
def on_terminal_clear_activate(self, widget):
|
|
self.clear_console()
|
|
|
|
def on_terminal_copy_activate(self, widget):
|
|
self.clipboard.clear()
|
|
self.clipboard.set_text(''.join(self.std_output.text_written))
|
|
|
|
def setup_data_view_buttons(self):
|
|
|
|
glsa_package_info_button = gtk.Button(label = _("Packages information"))
|
|
glsa_package_info_image = gtk.Image()
|
|
glsa_package_info_image.set_from_stock(gtk.STOCK_INFO, 4)
|
|
glsa_package_info_button.set_image(glsa_package_info_image)
|
|
|
|
glsa_adv_info_button = gtk.Button(label = _("Advisory information"))
|
|
glsa_adv_info_image = gtk.Image()
|
|
glsa_adv_info_image.set_from_stock(gtk.STOCK_EDIT, 4)
|
|
glsa_adv_info_button.set_image(glsa_adv_info_image)
|
|
|
|
#
|
|
|
|
mirror_updates_execute_button = gtk.Button(label = _("Execute"))
|
|
mirror_updates_execute_button_image = gtk.Image()
|
|
mirror_updates_execute_button_image.set_from_stock(gtk.STOCK_EXECUTE, 4)
|
|
mirror_updates_execute_button.set_image(mirror_updates_execute_button_image)
|
|
|
|
#
|
|
|
|
database_updates_package_info_button = gtk.Button(label = _("Packages information"))
|
|
database_updates_package_info_image = gtk.Image()
|
|
database_updates_package_info_image.set_from_stock(gtk.STOCK_INFO, 4)
|
|
database_updates_package_info_button.set_image(database_updates_package_info_image)
|
|
|
|
database_updates_change_repo_button = gtk.Button(label = _("Destination repository"))
|
|
database_updates_change_repo_image = gtk.Image()
|
|
database_updates_change_repo_image.set_from_stock(gtk.STOCK_CONVERT, 4)
|
|
database_updates_change_repo_button.set_image(database_updates_change_repo_image)
|
|
|
|
database_updates_execute_button = gtk.Button(label = _("Execute"))
|
|
database_updates_execute_button_image = gtk.Image()
|
|
database_updates_execute_button_image.set_from_stock(gtk.STOCK_EXECUTE, 4)
|
|
database_updates_execute_button.set_image(database_updates_execute_button_image)
|
|
|
|
#
|
|
|
|
available_packages_package_info_button = gtk.Button(label = _("Packages information"))
|
|
available_packages_package_info_image = gtk.Image()
|
|
available_packages_package_info_image.set_from_stock(gtk.STOCK_INFO, 4)
|
|
available_packages_package_info_button.set_image(available_packages_package_info_image)
|
|
|
|
available_packages_remove_package_button = gtk.Button(label = _("Remove packages"))
|
|
available_packages_remove_package_image = gtk.Image()
|
|
available_packages_remove_package_image.set_from_stock(gtk.STOCK_REMOVE, 4)
|
|
available_packages_remove_package_button.set_image(available_packages_remove_package_image)
|
|
|
|
available_packages_move_package_button = gtk.Button(label = _("Copy/move packages"))
|
|
available_packages_move_package_image = gtk.Image()
|
|
available_packages_move_package_image.set_from_stock(gtk.STOCK_COPY, 4)
|
|
available_packages_move_package_button.set_image(available_packages_move_package_image)
|
|
|
|
categories_updates_compile_button = gtk.Button(label = _("Compile selected"))
|
|
categories_updates_compile_image = gtk.Image()
|
|
categories_updates_compile_image.set_from_stock(gtk.STOCK_GOTO_BOTTOM, 4)
|
|
categories_updates_compile_button.set_image(categories_updates_compile_image)
|
|
|
|
categories_updates_add_use_button = gtk.Button(label = _("Add USE"))
|
|
categories_updates_add_use_image = gtk.Image()
|
|
categories_updates_add_use_image.set_from_stock(gtk.STOCK_ADD, 4)
|
|
categories_updates_add_use_button.set_image(categories_updates_add_use_image)
|
|
|
|
categories_updates_remove_use_button = gtk.Button(label = _("Remove USE"))
|
|
categories_updates_remove_use_image = gtk.Image()
|
|
categories_updates_remove_use_image.set_from_stock(gtk.STOCK_REMOVE, 4)
|
|
categories_updates_remove_use_button.set_image(categories_updates_remove_use_image)
|
|
|
|
#
|
|
|
|
notice_board_view_button = gtk.Button(label = _("View"))
|
|
notice_board_view_image = gtk.Image()
|
|
notice_board_view_image.set_from_stock(gtk.STOCK_ZOOM_IN, 4)
|
|
notice_board_view_button.set_image(notice_board_view_image)
|
|
|
|
notice_board_add_button = gtk.Button(label = _("Add"))
|
|
notice_board_add_image = gtk.Image()
|
|
notice_board_add_image.set_from_stock(gtk.STOCK_ADD, 4)
|
|
notice_board_add_button.set_image(notice_board_add_image)
|
|
|
|
notice_board_remove_button = gtk.Button(label = _("Remove"))
|
|
notice_board_remove_image = gtk.Image()
|
|
notice_board_remove_image.set_from_stock(gtk.STOCK_REMOVE, 4)
|
|
notice_board_remove_button.set_image(notice_board_remove_image)
|
|
|
|
notice_board_refresh_button = gtk.Button(label = _("Refresh"))
|
|
notice_board_refresh_image = gtk.Image()
|
|
notice_board_refresh_image.set_from_stock(gtk.STOCK_REFRESH, 4)
|
|
notice_board_refresh_button.set_image(notice_board_refresh_image)
|
|
|
|
self.DataViewButtons = {
|
|
'glsa': {
|
|
'package_info_button': glsa_package_info_button,
|
|
'adv_info_button': glsa_adv_info_button,
|
|
'order': ['package_info_button','adv_info_button'],
|
|
'handler_ids': [],
|
|
},
|
|
'mirror_updates': {
|
|
'execute_button': mirror_updates_execute_button,
|
|
'order': ['execute_button'],
|
|
'handler_ids': [],
|
|
},
|
|
'database_updates': {
|
|
'package_info_button': database_updates_package_info_button,
|
|
'change_repo_button': database_updates_change_repo_button,
|
|
'execute_button': database_updates_execute_button,
|
|
'order': ['package_info_button','change_repo_button','execute_button'],
|
|
'handler_ids': [],
|
|
},
|
|
'available_packages': {
|
|
'package_info_button': available_packages_package_info_button,
|
|
'remove_package_button': available_packages_remove_package_button,
|
|
'move_package_button': available_packages_move_package_button,
|
|
'order': ['package_info_button','remove_package_button','move_package_button'],
|
|
'handler_ids': [],
|
|
},
|
|
'categories_updates': {
|
|
'compile_button': categories_updates_compile_button,
|
|
'add_use_button': categories_updates_add_use_button,
|
|
'remove_use_button': categories_updates_remove_use_button,
|
|
'order': ['compile_button','add_use_button','remove_use_button'],
|
|
'handler_ids': [],
|
|
},
|
|
'notice_board': {
|
|
'add_button': notice_board_add_button,
|
|
'remove_button': notice_board_remove_button,
|
|
'refresh_button': notice_board_refresh_button,
|
|
'view_button': notice_board_view_button,
|
|
'order': ['view_button','add_button','remove_button','refresh_button'],
|
|
'handler_ids': [],
|
|
}
|
|
}
|
|
|
|
for cat in self.DataViewButtons:
|
|
for w_id in self.DataViewButtons[cat]['order']:
|
|
self.DataViewBox.pack_start(self.DataViewButtons[cat][w_id], False, False, 1)
|
|
|
|
def show_data_view_buttons_cat(self, cat):
|
|
if cat in self.DataViewButtons:
|
|
for w_id in self.DataViewButtons[cat]['order']:
|
|
self.DataViewButtons[cat][w_id].show()
|
|
# disconnect all signal handlers
|
|
for h_id in self.DataViewButtons[cat]['handler_ids']:
|
|
w = self.DataViewButtons[cat][w_id]
|
|
if w.handler_is_connected(h_id): w.disconnect(h_id)
|
|
del self.DataViewButtons[cat]['handler_ids'][:]
|
|
|
|
def hide_all_data_view_buttons(self):
|
|
self.debug_print("hide_all_data_view_buttons","enter")
|
|
for cat in self.DataViewButtons:
|
|
for w_id in self.DataViewButtons[cat]['order']:
|
|
self.debug_print("hide_all_data_view_buttons","hiding button %s,%s" % (cat,w_id,))
|
|
self.DataViewButtons[cat][w_id].hide()
|
|
self.debug_print("hide_all_data_view_buttons","quit")
|
|
|
|
def setup_available_repositories(self):
|
|
self.EntropyRepositories = {
|
|
'available': [],
|
|
'current': ''
|
|
}
|
|
self.EntropyRepositoryCombo = self.sm_ui.repoManagerRepositoryCombo
|
|
self.EntropyRepositoryStore = gtk.ListStore( gobject.TYPE_STRING )
|
|
self.EntropyRepositoryCombo.set_model(self.EntropyRepositoryStore)
|
|
cell = gtk.CellRendererText()
|
|
self.EntropyRepositoryCombo.pack_start(cell, True)
|
|
self.EntropyRepositoryCombo.add_attribute(cell, 'text', 0)
|
|
self.EntropyRepositoryComboLoader = ParallelTask(self.load_available_repositories)
|
|
|
|
def setup_commands_view(self):
|
|
|
|
# setup commands view
|
|
self.CommandsView = self.sm_ui.repoManagerCommandsView
|
|
self.CommandsStore = gtk.ListStore( gobject.TYPE_PYOBJECT )
|
|
self.CommandsView.set_model( self.CommandsStore )
|
|
|
|
# command col
|
|
self.create_text_column( self.CommandsView, _( "Command" ), 'commands:command', size = 270, set_height = 40)
|
|
# desc col
|
|
self.create_text_column( self.CommandsView, _( "Description" ), 'commands:desc', size = 200, expand = True, set_height = 40)
|
|
|
|
def fill_commands_view(self, data):
|
|
self.CommandsStore.clear()
|
|
keys = sorted(data.keys())
|
|
for key in keys:
|
|
if data[key]['private']: continue
|
|
item = data[key].copy()
|
|
item['key'] = key
|
|
params = ' | '.join([cleanMarkupString(unicode(x)) for x in item['params']])
|
|
if not params:
|
|
params = _("None")
|
|
txt = "<small><b>%s</b>: %s\n<b>%s</b>: %s</small>" % (
|
|
_("Description"),
|
|
cleanMarkupString(item['desc']),
|
|
_("Parameters"),
|
|
params,
|
|
)
|
|
item['myinfo'] = txt
|
|
self.CommandsStore.append((item,))
|
|
self.CommandsView.queue_draw()
|
|
|
|
def setup_queue_view(self):
|
|
|
|
# setup queue view
|
|
self.QueueView = self.sm_ui.repoManagerQueueView
|
|
self.QueueStore = gtk.ListStore( gobject.TYPE_PYOBJECT, gobject.TYPE_STRING )
|
|
self.QueueView.set_model( self.QueueStore )
|
|
|
|
# selection pixmap
|
|
cell = gtk.CellRendererPixbuf()
|
|
column = gtk.TreeViewColumn( _("Status"), cell )
|
|
column.set_cell_data_func( cell, self.queue_pixbuf )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( 80 )
|
|
column.set_sort_column_id( 0 )
|
|
self.QueueView.append_column( column )
|
|
|
|
# command col
|
|
self.create_text_column( self.QueueView, _( "Command" ), 'queue:command_name', size = 180)
|
|
# description col
|
|
self.create_text_column( self.QueueView, _( "Parameters" ), 'queue:command_text', size = 200, expand = True)
|
|
# date col
|
|
self.create_text_column( self.QueueView, _( "Date" ), 'queue:ts', size = 120, sort_col_id = 1)
|
|
|
|
def setup_data_view(self):
|
|
|
|
store = gtk.TreeStore( gobject.TYPE_PYOBJECT )
|
|
self.debug_print("setup_data_view","enter")
|
|
self.reset_data_view()
|
|
self.debug_print("setup_data_view","creating new DataView")
|
|
dv = gtk.TreeView()
|
|
dv.set_model(store)
|
|
self.data_tree_selection_mode = dv.get_selection().get_mode()
|
|
self.DataStore = store
|
|
self.DataView = dv
|
|
self.debug_print("setup_data_view","quit")
|
|
|
|
def show_data_view(self):
|
|
self.DataScroll.add(self.DataView)
|
|
self.debug_print("show_data_view","adding to DataScroll")
|
|
self.DataView.show()
|
|
self.debug_print("show_data_view","showing DataView")
|
|
|
|
def setup_pinboard_view(self):
|
|
|
|
# setup pinboard view
|
|
self.PinboardView = self.sm_ui.repoManagerPinboardView
|
|
self.PinboardStore = gtk.ListStore( gobject.TYPE_PYOBJECT, gobject.TYPE_STRING )
|
|
self.PinboardView.set_model( self.PinboardStore )
|
|
self.PinboardView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
|
self.PinboardView.set_rubber_banding(True)
|
|
|
|
# selection pixmap
|
|
cell = gtk.CellRendererPixbuf()
|
|
column = gtk.TreeViewColumn( _("Status"), cell )
|
|
column.set_cell_data_func( cell, self.pinboard_pixbuf )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( 80 )
|
|
column.set_sort_column_id( 0 )
|
|
self.PinboardView.append_column( column )
|
|
|
|
# date
|
|
self.create_text_column( self.PinboardView, _( "Date" ), 'pinboard:date', size = 130, sort_col_id = 1)
|
|
# note
|
|
self.create_text_column( self.PinboardView, _( "Note" ), 'pinboard:note', size = 200, expand = True)
|
|
|
|
def create_text_column( self, view, hdr, property, size, sortcol = None, expand = False, set_height = 0, cell_data_func = None, sort_col_id = -1):
|
|
if cell_data_func == None: cell_data_func = self.get_data_text
|
|
cell = gtk.CellRendererText()
|
|
if set_height: cell.set_property('height', set_height)
|
|
column = gtk.TreeViewColumn( hdr, cell )
|
|
column.set_resizable( True )
|
|
column.set_cell_data_func( cell, cell_data_func, property )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( size )
|
|
column.set_expand(expand)
|
|
column.set_sort_column_id( sort_col_id )
|
|
view.append_column( column )
|
|
return column
|
|
|
|
def queue_pixbuf( self, column, cell, model, myiter ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if isinstance(obj,dict):
|
|
st = self.get_status_from_queue_item(obj.copy())
|
|
if st != None:
|
|
cell.set_property('stock-id',st)
|
|
|
|
def pinboard_pixbuf( self, column, cell, model, myiter ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if isinstance(obj,dict):
|
|
if obj['done']:
|
|
cell.set_property('stock-id','gtk-apply')
|
|
else:
|
|
cell.set_property('stock-id','gtk-cancel')
|
|
|
|
def spm_package_obj_to_cell(self, obj, cell):
|
|
use_data = []
|
|
if obj.has_key('use'):
|
|
if obj['use'].has_key('use_string'):
|
|
use_data = obj['use']['use_string'].split()
|
|
max_chars = 100
|
|
use_string = []
|
|
for use in use_data:
|
|
max_chars -= len(use)
|
|
use_string.append(use)
|
|
if max_chars < 0:
|
|
use_string.append("\n")
|
|
max_chars = 100
|
|
use_string = ' '.join(use_string).strip()
|
|
installed_string = ''
|
|
available_string = ''
|
|
if obj.has_key('installed_atom'):
|
|
installed_string = '<b>%s</b>: %s\n' % (_("Installed"),cleanMarkupString(str(obj['installed_atom'])),)
|
|
if obj.has_key('available_atom'):
|
|
available_string = '<b>%s</b>: %s\n' % (_("Available"),cleanMarkupString(str(obj['available_atom'])),)
|
|
|
|
atom = obj.get('atom')
|
|
key = obj.get('key')
|
|
slot = obj.get('slot')
|
|
description = obj.get('description')
|
|
|
|
txt = "<i>%s</i>\n<small><b>%s</b>: %s, <b>%s</b>: %s\n" % (
|
|
cleanMarkupString(atom),
|
|
_("Key"),
|
|
cleanMarkupString(key),
|
|
_("Slot"),
|
|
cleanMarkupString(slot),
|
|
)
|
|
txt += installed_string
|
|
txt += available_string
|
|
if len(use_string) > 160:
|
|
use_string = use_string[:160]
|
|
txt += "<b>%s</b>: %s\n<b>%s</b>: %s</small>" % (
|
|
_("Description"),
|
|
cleanMarkupString(description),
|
|
_("USE Flags"),
|
|
cleanMarkupString(use_string),
|
|
)
|
|
cell.set_property('markup',txt)
|
|
|
|
def entropy_package_obj_to_cell(self, obj, cell):
|
|
mytxt = '<small><i>%s</i>\n%s\n<b>%s</b>: %s | <b>%s</b>: %s | <b>%s</b>: %s | <b>%s</b>: %s | <b>%s</b>: %s\n<b>%s</b>: %s</small>' % (
|
|
obj['atom'],
|
|
cleanMarkupString(obj['description']),
|
|
_("Size"),
|
|
self.entropyTools.bytes_into_human(obj['size']),
|
|
_("Branch"),
|
|
obj['branch'],
|
|
_("Slot"),
|
|
cleanMarkupString(obj['slot']),
|
|
_("Tag"),
|
|
cleanMarkupString(obj['versiontag']),
|
|
_("Injected"),
|
|
obj['injected'],
|
|
_("Homepage"),
|
|
cleanMarkupString(obj['homepage']),
|
|
)
|
|
cell.set_property('markup',mytxt)
|
|
|
|
def get_status_from_queue_item(self, item):
|
|
if item.has_key('errored_ts'):
|
|
return "gtk-cancel"
|
|
elif item.has_key('processed_ts'):
|
|
return "gtk-apply"
|
|
elif item.has_key('processing_ts'):
|
|
return "gtk-refresh"
|
|
elif item.has_key('queue_ts'):
|
|
return "gtk-up"
|
|
return "gtk-apply"
|
|
|
|
def get_ts_from_queue_item(self, item):
|
|
if item.has_key('errored_ts'):
|
|
return item['errored_ts']
|
|
elif item.has_key('processed_ts'):
|
|
return item['processed_ts']
|
|
elif item.has_key('processing_ts'):
|
|
return item['processing_ts']
|
|
elif item.has_key('queue_ts'):
|
|
return item['queue_ts']
|
|
return None
|
|
|
|
def get_data_text( self, column, cell, model, myiter, property ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if isinstance(obj,dict):
|
|
if property == "queue:ts":
|
|
cell.set_property('markup',self.get_ts_from_queue_item(obj))
|
|
elif property == "queue:command_text":
|
|
cell.set_property('markup',cleanMarkupString(obj['command_text']))
|
|
elif property == "queue:command_name":
|
|
cell.set_property('markup',cleanMarkupString(obj['command_name']))
|
|
elif property == "commands:command":
|
|
cell.set_property('markup',obj['key'])
|
|
elif property == "commands:desc":
|
|
cell.set_property('markup',obj['myinfo'])
|
|
elif property == "pinboard:date":
|
|
cell.set_property('markup',unicode(obj['ts']))
|
|
elif property == "pinboard:note":
|
|
cell.set_property('markup',cleanMarkupString(obj['note']))
|
|
|
|
def connection_verification_callback(self, host, port, username, password, ssl):
|
|
self.Service.setup_connection(
|
|
host,
|
|
int(port),
|
|
username,
|
|
password,
|
|
ssl
|
|
)
|
|
# test connection
|
|
srv = self.Service.get_service_connection(timeout = 5)
|
|
if srv == None:
|
|
return False, _("No connection to host, please check your data")
|
|
try:
|
|
session = srv.open_session()
|
|
if session == None:
|
|
return False, _("Unable to create a remote session. Try again later.")
|
|
try:
|
|
logged, error = self.Service.login(srv, session)
|
|
if not logged:
|
|
return False, _("Login failed. Please retry.")
|
|
except Exception, e:
|
|
self.entropyTools.print_traceback()
|
|
return False, "%s: %s" % (_("Connection Error"),e,)
|
|
srv.close_session(session)
|
|
srv.disconnect()
|
|
self.connection_done = True
|
|
return True, None
|
|
except SSLError:
|
|
return False,_("SSL Error, are you sure the server supports SSL?")
|
|
|
|
def load(self):
|
|
|
|
my = RemoteConnectionMenu(self.Entropy, self.connection_verification_callback, self.window)
|
|
my.load()
|
|
login_data = my.run()
|
|
if not login_data:
|
|
return False
|
|
|
|
self.sm_ui.repositoryManager.show_all()
|
|
self.hide_all_data_view_buttons()
|
|
|
|
# spawn parallel tasks
|
|
self.QueueUpdater.start()
|
|
self.OutputUpdater.start()
|
|
self.PinboardUpdater.start()
|
|
|
|
# ui will be unlocked by the thread below
|
|
self.uiLock(True)
|
|
self.EntropyRepositoryComboLoader.start()
|
|
return True
|
|
|
|
def get_item_by_queue_id(self, queue_id):
|
|
with self.QueueLock:
|
|
for key in self.Queue:
|
|
if key not in self.dict_queue_keys:
|
|
continue
|
|
item = self.Queue[key].get(queue_id)
|
|
if item != None:
|
|
return item, key
|
|
return None, None
|
|
|
|
def service_status_message(self, e):
|
|
self.entropyTools.print_traceback()
|
|
def do_ok():
|
|
okDialog(self.sm_ui.repositoryManager, unicode(e),
|
|
title = _("Communication error"))
|
|
return False
|
|
gobject.idle_add(do_ok)
|
|
|
|
def get_available_repositories(self):
|
|
with self.BufferLock:
|
|
try:
|
|
status, repo_info = self.Service.Methods.get_available_repositories()
|
|
if not status: return None
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
return repo_info
|
|
|
|
def load_available_repositories(self, repo_info = None):
|
|
|
|
if repo_info == None:
|
|
repo_info = self.get_available_repositories()
|
|
if not repo_info: return
|
|
|
|
if isinstance(repo_info,dict):
|
|
|
|
def task(repo_info):
|
|
|
|
self.EntropyRepositories = repo_info.copy()
|
|
self.EntropyRepositoryStore.clear()
|
|
for repoid in self.EntropyRepositories['available'].keys():
|
|
item = self.EntropyRepositoryStore.append( (repoid,) )
|
|
if repoid == self.EntropyRepositories['current']:
|
|
self.EntropyRepositoryCombo.set_active_iter(item)
|
|
mytxt = "<small><b>%s</b>: %s [<b>%s</b>: %s | <b>%s</b>: %s | <b>%s</b>: %s | <b>%s</b>: %s]</small>" % (
|
|
_("Current"),
|
|
self.EntropyRepositories['current'],
|
|
_("c.mode"),
|
|
self.EntropyRepositories['community_mode'],
|
|
_("branch"),
|
|
self.EntropyRepositories['branch'],
|
|
_("supported branches"),
|
|
','.join(self.EntropyRepositories['branches']),
|
|
_("repositories"),
|
|
len(self.EntropyRepositories['available']),
|
|
)
|
|
try:
|
|
self.sm_ui.repoManagerCurrentRepoLabel.set_markup(mytxt)
|
|
except AttributeError: # user might have closed the win
|
|
pass
|
|
if not self.repos_loaded:
|
|
self.repos_loaded = True
|
|
self.uiLock(False)
|
|
return False
|
|
|
|
gobject.idle_add(task, repo_info)
|
|
|
|
def update_queue_view(self):
|
|
|
|
def task():
|
|
self.do_update_queue_view()
|
|
|
|
t = ParallelTask(task)
|
|
t.start()
|
|
|
|
def do_update_queue_view(self):
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue = self.Service.Methods.get_queue()
|
|
if not status:
|
|
return
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
with self.QueueLock:
|
|
if queue == self.Queue: return
|
|
self.Queue = queue.copy()
|
|
gobject.idle_add(self.fill_queue_view, queue)
|
|
|
|
def fill_queue_view(self, queue):
|
|
|
|
self.QueueStore.clear()
|
|
keys = queue.keys()
|
|
|
|
if "processing_order" in keys:
|
|
for queue_id in queue['processing_order']:
|
|
item = queue['processing'].get(queue_id)
|
|
if item == None: continue
|
|
item = item.copy()
|
|
item['from'] = "processing"
|
|
self.QueueStore.append((item,item['queue_ts'],))
|
|
if not queue['processing']:
|
|
self.is_processing = None
|
|
self.is_writing_output = False
|
|
else:
|
|
self.is_processing = None
|
|
self.is_writing_output = False
|
|
|
|
if "processed_order" in keys:
|
|
mylist = queue['processed_order'][:]
|
|
mylist.reverse()
|
|
for queue_id in mylist:
|
|
item = queue['processed'].get(queue_id)
|
|
if item == None: continue
|
|
item = item.copy()
|
|
item['from'] = "processed"
|
|
self.QueueStore.append((item,item['queue_ts'],))
|
|
|
|
if "queue_order" in keys:
|
|
for queue_id in queue['queue_order']:
|
|
item = queue['queue'].get(queue_id)
|
|
if item == None: continue
|
|
item = item.copy()
|
|
item['from'] = "queue"
|
|
self.QueueStore.append((item,item['queue_ts'],))
|
|
|
|
if "errored_order" in keys:
|
|
mylist = queue['errored_order'][:]
|
|
mylist.reverse()
|
|
for queue_id in mylist:
|
|
item = queue['errored'].get(queue_id)
|
|
if item == None: continue
|
|
item = item.copy()
|
|
item['from'] = "errored"
|
|
self.QueueStore.append((item,item['queue_ts'],))
|
|
|
|
return False
|
|
|
|
def update_pinboard_view(self, force = False):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, pindata = self.Service.Methods.get_pinboard_data()
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if (pindata == self.PinboardData) and (not force):
|
|
return
|
|
|
|
if isinstance(pindata,dict):
|
|
def task(pindata):
|
|
self.fill_pinboard_view(pindata)
|
|
self.PinboardData = pindata.copy()
|
|
return False
|
|
gobject.idle_add(task, pindata)
|
|
|
|
def fill_pinboard_view(self, pinboard_data):
|
|
if isinstance(pinboard_data,dict):
|
|
gtk.gdk.threads_enter()
|
|
self.PinboardStore.clear()
|
|
identifiers = sorted(pinboard_data.keys())
|
|
for identifier in identifiers:
|
|
item = pinboard_data[identifier].copy()
|
|
item['pinboard_id'] = identifier
|
|
self.PinboardStore.append((item,item['ts'],))
|
|
gtk.gdk.threads_leave()
|
|
|
|
def update_output_view(self, force = False, queue_id = None, n_bytes = 40000):
|
|
|
|
def clean_output(myin):
|
|
s = ''
|
|
for x in myin:
|
|
if ord(x) < 8:
|
|
continue
|
|
s += x
|
|
return s
|
|
|
|
with self.OutputLock:
|
|
|
|
if self.output_pause and not force: return
|
|
|
|
if not queue_id:
|
|
if self.is_processing == None: return
|
|
if not self.is_writing_output: return
|
|
obj = self.is_processing.copy()
|
|
if not obj.has_key('queue_id'): return
|
|
queue_id = obj['queue_id']
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, stdout = self.Service.Methods.get_queue_id_stdout(queue_id, n_bytes)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if not status: return
|
|
stdout = stdout[-1*n_bytes:]
|
|
if (stdout == self.Output) and (not force): return
|
|
self.Output = stdout
|
|
|
|
self.clear_console()
|
|
|
|
mytxt = []
|
|
slice_count = self.console.get_column_count()
|
|
while stdout:
|
|
my = stdout[:slice_count]
|
|
stdout = stdout[slice_count:]
|
|
mytxt.append(my)
|
|
|
|
for txt in mytxt: self.std_output.write(txt)
|
|
|
|
return False
|
|
|
|
def load_queue_info_menu(self, obj):
|
|
my = SmQueueMenu(self.window)
|
|
my.load(obj)
|
|
|
|
def clear_data_view(self):
|
|
self.debug_print("clear_data_view","enter")
|
|
self.setup_data_view()
|
|
ts_mode = self.DataView.get_selection().get_mode()
|
|
if ts_mode != self.data_tree_selection_mode:
|
|
self.DataView.get_selection().set_mode(self.data_tree_selection_mode)
|
|
self.debug_print("clear_data_view","ts_mode set")
|
|
self.DataView.set_rubber_banding(False)
|
|
self.debug_print("clear_data_view","rubber banding set")
|
|
self.debug_print("clear_data_view","exit")
|
|
|
|
def collect_data_view_iters(self):
|
|
self.debug_print("collect_data_view_iters","enter")
|
|
model, paths = self.DataView.get_selection().get_selected_rows()
|
|
if not model:
|
|
self.debug_print("collect_data_view_iters","quit (nothing)")
|
|
return [], model
|
|
data = []
|
|
for path in paths:
|
|
myiter = model.get_iter(path)
|
|
data.append(myiter)
|
|
self.debug_print("collect_data_view_iters","quit")
|
|
return data, model
|
|
|
|
def wait_queue_id_to_complete(self, queue_id):
|
|
|
|
self.debug_print("wait_queue_id_to_complete","waiting for queue id %s" % (queue_id,))
|
|
|
|
key = None
|
|
while key not in ("processed","errored",):
|
|
item, key = self.get_item_by_queue_id(queue_id)
|
|
time.sleep(0.5)
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, (result,extended_result,) = self.Service.Methods.get_queue_id_result(queue_id)
|
|
if not status:
|
|
return
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
self.debug_print("wait_queue_id_to_complete","done waiting for queue id %s" % (queue_id,))
|
|
|
|
item = item.copy()
|
|
|
|
if extended_result != None:
|
|
item['result'] = True, extended_result
|
|
|
|
if key == "errored":
|
|
return
|
|
return item
|
|
|
|
def glsa_data_view(self, data):
|
|
|
|
self.debug_print("glsa_data_view","enter")
|
|
|
|
self.clear_data_view()
|
|
self.debug_print("glsa_data_view","setting GFX")
|
|
|
|
self.debug_print("glsa_data_view","all buttons hidden")
|
|
self.show_data_view_buttons_cat('glsa')
|
|
self.debug_print("glsa_data_view","all glsa buttons shown")
|
|
self.DataView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
|
self.DataView.set_rubber_banding(True)
|
|
self.debug_print("glsa_data_view","done setting DataView rb")
|
|
|
|
self.debug_print("glsa_data_view","done setting GFX")
|
|
|
|
def is_affected(obj):
|
|
if obj['status'] == "[A]":
|
|
return False
|
|
elif obj['status'] == "[N]":
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def my_data_text( column, cell, model, myiter, property ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
if property == "glsa_id":
|
|
cell.set_property('markup',cleanMarkupString(obj['number']))
|
|
elif property == "title":
|
|
cell.set_property('markup',cleanMarkupString(obj['title']))
|
|
cell.set_property('cell-background',obj['color'])
|
|
|
|
def my_data_pix( column, cell, model, myiter ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
affected = is_affected(obj)
|
|
if affected:
|
|
cell.set_property( 'stock-id', 'gtk-cancel' )
|
|
else:
|
|
cell.set_property( 'stock-id', 'gtk-apply' )
|
|
cell.set_property('cell-background',obj['color'])
|
|
|
|
def package_info_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
atoms = set()
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
for atom in obj['packages']:
|
|
for atom_info in obj['packages'][atom]:
|
|
if atom_info.has_key('unaff_atoms'):
|
|
atoms |= set(atom_info['unaff_atoms'])
|
|
if atoms:
|
|
self.on_repoManagerPkgInfo_clicked(None, atoms = atoms, clear = True)
|
|
|
|
def adv_info_button_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
my = SecurityAdvisoryMenu(self.window)
|
|
item = obj['number'], is_affected(obj), obj
|
|
my.load(item)
|
|
|
|
self.debug_print("glsa_data_view","done setting functions")
|
|
# Package information
|
|
h1 = self.DataViewButtons['glsa']['package_info_button'].connect('clicked',package_info_clicked)
|
|
# GLSA information button
|
|
h2 = self.DataViewButtons['glsa']['adv_info_button'].connect('clicked',adv_info_button_clicked)
|
|
self.DataViewButtons['glsa']['handler_ids'].extend([h1,h2])
|
|
self.debug_print("glsa_data_view","done connecting buttons")
|
|
|
|
# selection pixmap
|
|
cell = gtk.CellRendererPixbuf()
|
|
column = gtk.TreeViewColumn( _("Status"), cell )
|
|
column.set_cell_data_func( cell, my_data_pix )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( 80 )
|
|
column.set_sort_column_id( -1 )
|
|
self.debug_print("glsa_data_view","appending status img to DataView")
|
|
self.DataView.append_column( column )
|
|
|
|
self.debug_print("glsa_data_view","creating glsa column")
|
|
# glsa id
|
|
self.create_text_column( self.DataView, _( "GLSA Id." ), 'glsa_id', size = 80, cell_data_func = my_data_text)
|
|
self.debug_print("glsa_data_view","creating title column")
|
|
# glsa title
|
|
self.create_text_column( self.DataView, _( "Title" ), 'title', size = 300, cell_data_func = my_data_text, expand = True)
|
|
|
|
self.debug_print("glsa_data_view","done setting DataView columns")
|
|
|
|
colors = ["#CDEEFF","#AFCBDA"]
|
|
counter = 0
|
|
for myid in data:
|
|
counter += 1
|
|
obj = data[myid].copy()
|
|
obj['color'] = colors[counter%len(colors)]
|
|
self.DataStore.append( None, (obj,) )
|
|
|
|
self.debug_print("glsa_data_view","done adding to DataStore")
|
|
self.set_notebook_page(self.notebook_pages['data'])
|
|
self.debug_print("glsa_data_view","done switching page")
|
|
self.show_data_view()
|
|
self.debug_print("glsa_data_view","done unmasking widgets")
|
|
self.debug_print("glsa_data_view","exit")
|
|
return False
|
|
|
|
def retrieve_entropy_idpackage_data_and_show(self, idpackage, repoid):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
self.debug_print("retrieve_entropy_idpackage_data_and_show","called for: %s, %s" % (idpackage,repoid,))
|
|
status, package_data = self.Service.Methods.get_entropy_idpackage_information(idpackage, repoid)
|
|
self.debug_print("retrieve_entropy_idpackage_data_and_show","done for: %s, %s" % (idpackage,repoid,))
|
|
if not status: return
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if not package_data: return
|
|
pkg = packages.EntropyPackage((idpackage,repoid,), remote = package_data)
|
|
mymenu = PkgInfoMenu(self.Entropy, pkg, self.window)
|
|
mymenu.load(remote = True)
|
|
|
|
def remove_entropy_packages(self, matched_atoms, reload_func = None):
|
|
|
|
rc = self.Entropy.askQuestion(_("Are you sure you want to remove the selected packages ? (For EVA!)"))
|
|
if rc != "Yes": return
|
|
|
|
rc = self.Entropy.askQuestion(_("This is your last chance, are you really really really sure?"))
|
|
if rc != "Yes": return
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, msg = self.Service.Methods.remove_entropy_packages(matched_atoms)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if not status:
|
|
self.service_status_message(msg)
|
|
return
|
|
|
|
if status and callable(reload_func):
|
|
reload_func()
|
|
|
|
def handle_uses_for_atoms(self, atoms, use):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = []
|
|
data = {}
|
|
data['atoms'] = atoms
|
|
data['use'] = use
|
|
if not atoms:
|
|
input_params.append(('atoms',_('Atoms, space separated'),fake_callback,False),)
|
|
if not use:
|
|
input_params.append(('use',_('USE flags, space separated'),fake_callback,False),)
|
|
if input_params:
|
|
mydata = self.Entropy.inputBox(
|
|
_('Insert command parameters'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
data.update(mydata)
|
|
if not atoms:
|
|
data['atoms'] = data['atoms'].split()
|
|
if not use:
|
|
data['use'] = data['use'].split()
|
|
return data
|
|
|
|
def run_get_notice_board(self, repoid):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.get_notice_board(repoid)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id, repoid):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, repo_data = item['result']
|
|
if not status: return
|
|
self.update_notice_board_data_view(repo_data, repoid)
|
|
|
|
if status:
|
|
t = ParallelTask(task, queue_id, repoid)
|
|
t.start()
|
|
|
|
def run_write_to_running_command_pipe(self, queue_id, write_to_stdout, txt):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, data = self.Service.Methods.write_to_running_command_pipe(queue_id, write_to_stdout, txt)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def run_remove_from_pinboard(self, remove_ids):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.remove_from_pinboard(remove_ids)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.on_repoManagerPinboardRefreshButton_clicked(None)
|
|
|
|
def run_add_to_pinboard(self, note, extended_text):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, err_msg = self.Service.Methods.add_to_pinboard(note,extended_text)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.on_repoManagerPinboardRefreshButton_clicked(None)
|
|
else:
|
|
self.service_status_message(err_msg)
|
|
|
|
def run_run_custom_shell_command(self, command):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.run_custom_shell_command(command)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id}
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
|
|
def run_get_spm_categories_installed(self, categories, world):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.get_spm_categories_installed(categories)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id, categories, world):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, data = item['result']
|
|
if not status: return
|
|
def reload_function():
|
|
self.on_repoManagerInstalledPackages_clicked(None,
|
|
categories = categories, world = world)
|
|
return False
|
|
gobject.idle_add(self.categories_updates_data_view, data,
|
|
categories, True, reload_function)
|
|
|
|
if status:
|
|
t = ParallelTask(task, queue_id, categories, world)
|
|
t.start()
|
|
|
|
def run_sync_spm(self):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, data = self.Service.Methods.sync_spm()
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
|
|
def run_spm_remove_atoms(self, data):
|
|
|
|
def task(data):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.spm_remove_atoms(
|
|
data['atoms'],
|
|
data['pretend'],
|
|
data['verbose'],
|
|
data['nocolor'],
|
|
)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id}
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
|
|
t = ParallelTask(task, data)
|
|
t.start()
|
|
|
|
def run_compile_atoms(self, data):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.compile_atoms(
|
|
data['atoms'],
|
|
data['pretend'],
|
|
data['oneshot'],
|
|
data['verbose'],
|
|
data['nocolor'],
|
|
data['fetchonly'],
|
|
data['buildonly'],
|
|
data['nodeps'],
|
|
data['custom_use'],
|
|
data['ldflags'],
|
|
data['cflags'],
|
|
)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id}
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
|
|
def run_spm_info(self):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.run_spm_info()
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id}
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
|
|
# fine without ParallelTask
|
|
def run_enable_uses_for_atoms(self, atoms, use, load_view):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.enable_uses_for_atoms(atoms, use)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if load_view and status:
|
|
self.on_repoManagerPkgInfo_clicked(None, atoms = atoms)
|
|
|
|
return status
|
|
|
|
# fine without ParallelTask
|
|
def run_disable_uses_for_atoms(self, atoms, use, load_view):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.disable_uses_for_atoms(atoms, use)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if load_view and status:
|
|
self.clear_data_store_and_view()
|
|
self.on_repoManagerPkgInfo_clicked(None, atoms = atoms)
|
|
return status
|
|
|
|
def run_get_spm_atoms_info(self, categories, atoms, clear):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.get_spm_atoms_info(atoms)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(categories, atoms):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, data = item['result']
|
|
if not status: return
|
|
def reload_function():
|
|
self.on_repoManagerPkgInfo_clicked(None, atoms = atoms, clear = clear)
|
|
gobject.idle_add(self.categories_updates_data_view, data,
|
|
categories, True, reload_function)
|
|
|
|
if status:
|
|
t = ParallelTask(task, categories, atoms)
|
|
t.start()
|
|
|
|
def run_kill_processing_queue_id(self, queue_id):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
self.Service.Methods.kill_processing_queue_id(queue_id)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def run_remove_queue_ids(self, queue_ids):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
self.Service.Methods.remove_queue_ids(queue_ids)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def run_spm_categories_updates(self, categories, expand):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.get_spm_categories_updates(categories)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id, categories, expand):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, data = item['result']
|
|
if not status: return
|
|
gobject.idle_add(self.categories_updates_data_view, data,
|
|
categories, expand)
|
|
|
|
if status:
|
|
t = ParallelTask(queue_id, task, categories, expand)
|
|
t.start()
|
|
|
|
def run_entropy_deptest(self):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.run_entropy_dependency_test()
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id }
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def run_entropy_treeupdates(self, repoid):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.run_entropy_treeupdates(repoid)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id }
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def run_entropy_checksum_test(self, repoid, mode):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.run_entropy_checksum_test(repoid, mode)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id }
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def run_entropy_mirror_updates(self, repos):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.scan_entropy_mirror_updates(repos)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id, repos):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, repo_data = item['result']
|
|
if not status: return
|
|
gobject.idle_add(self.entropy_mirror_updates_data_view,
|
|
repo_data)
|
|
|
|
if status:
|
|
t = ParallelTask(task, queue_id, repos)
|
|
t.start()
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def execute_entropy_mirror_updates(self, repo_data):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.run_entropy_mirror_updates(repo_data)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id }
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def run_entropy_libtest(self):
|
|
|
|
with self.BufferLock:
|
|
status = False
|
|
data = {}
|
|
try:
|
|
status, queue_id = self.Service.Methods.run_entropy_library_test()
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
# enable output
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id }
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def run_package_search(self, search_type, search_string, repoid):
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, data = self.Service.Methods.search_entropy_packages(search_type, search_string, repoid)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if status:
|
|
def reload_func():
|
|
self.run_package_search(search_type, search_string, repoid)
|
|
gobject.idle_add(self.entropy_available_packages_data_view,
|
|
data, repoid, reload_func)
|
|
else:
|
|
self.service_status_message(data)
|
|
|
|
def move_entropy_packages(self, matches, reload_function):
|
|
|
|
idpackages = []
|
|
repoids = set()
|
|
for idpackage, repoid in matches:
|
|
repoids.add(repoid)
|
|
idpackages.append(idpackage)
|
|
|
|
if len(repoids) > 1:
|
|
self.service_status_message(_("Cannot move/copy packages from different repositories"))
|
|
return
|
|
|
|
from_repo = list(repoids)[0]
|
|
|
|
avail_repos = self.EntropyRepositories['available'].keys()
|
|
if not avail_repos: return
|
|
|
|
def fake_callback_repos(s):
|
|
entryid, myrepoid = s
|
|
if myrepoid == from_repo:
|
|
return False
|
|
return True
|
|
|
|
def fake_callback_cb(s):
|
|
return True
|
|
|
|
input_params = [
|
|
('to_repo',('combo',(_('To repository'),avail_repos),),fake_callback_repos,False),
|
|
('do_copy',('checkbox',_('Execute copy'),),fake_callback_cb,False),
|
|
]
|
|
data = self.Entropy.inputBox(
|
|
_('Entropy packages move/copy'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
|
|
data['to_repo'] = data['to_repo'][1]
|
|
|
|
with self.BufferLock:
|
|
status = False
|
|
try:
|
|
status, queue_id = self.Service.Methods.move_entropy_packages_to_repository(idpackages, from_repo, data['to_repo'], do_copy = data['do_copy'])
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
if not status:
|
|
self.service_status_message(queue_id)
|
|
return
|
|
|
|
self.reload_after_package_move(queue_id, reload_function)
|
|
|
|
|
|
def reload_after_package_move(self, queue_id, reload_func):
|
|
|
|
def task(queue_id, reload_func):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, data = item['result']
|
|
if not status: return
|
|
gobject.idle_add(reload_func)
|
|
|
|
t = ParallelTask(task, queue_id, reload_func)
|
|
t.start()
|
|
|
|
def run_entropy_database_updates_scan(self):
|
|
|
|
with self.BufferLock:
|
|
status = False
|
|
data = {}
|
|
try:
|
|
status, queue_id = self.Service.Methods.scan_entropy_packages_database_changes()
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, data = item['result']
|
|
if not status: return
|
|
gobject.idle_add(self.entropy_database_updates_data_view,
|
|
data)
|
|
|
|
if status:
|
|
t = ParallelTask(task, queue_id)
|
|
t.start()
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def run_entropy_database_updates(self, to_add, to_remove, to_inject, reload_func = None):
|
|
|
|
if reload_func == None:
|
|
def reload_func():
|
|
return False
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.run_entropy_database_updates(to_add, to_remove, to_inject)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id, reload_func):
|
|
self.reload_after_package_move(queue_id, reload_func)
|
|
|
|
if status:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id }
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
t = ParallelTask(task, queue_id, reload_func)
|
|
t.start()
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def run_add_notice_board_entry(self, repoid, title, notice_text, link, reload_func = None):
|
|
|
|
if reload_func == None:
|
|
def reload_func():
|
|
return False
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.add_notice_board_entry(repoid, title, notice_text, link)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id, repoid, title, notice_text, link, reload_func):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, result = item['result']
|
|
if not status: return
|
|
gobject.idle_add(reload_func)
|
|
|
|
if status:
|
|
t = ParallelTask(task, queue_id, repoid, title, notice_text, link, reload_func)
|
|
t.start()
|
|
|
|
def run_remove_notice_board_entries(self, repoid, ids, reload_func = None):
|
|
|
|
if reload_func == None:
|
|
def reload_func():
|
|
return False
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.remove_notice_board_entries(repoid, list(ids))
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id, repoid, ids, reload_func):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
status, result = item['result']
|
|
if not status: return
|
|
gobject.idle_add(reload_func)
|
|
|
|
if status:
|
|
t = ParallelTask(task, queue_id, repoid, ids, reload_func)
|
|
t.start()
|
|
|
|
def update_notice_board_data_view(self, repo_data, repoid):
|
|
|
|
self.clear_data_view()
|
|
self.show_data_view_buttons_cat('notice_board')
|
|
self.DataView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
|
self.DataView.set_rubber_banding(True)
|
|
|
|
def my_data_text( column, cell, model, myiter, property ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
mytxt = '<b><u>%s</u></b>\n<small><b>%s</b>: %s</small>' % (
|
|
cleanMarkupString(obj['pubDate']),
|
|
_("Title"),
|
|
cleanMarkupString(obj['title']),
|
|
)
|
|
cell.set_property('markup',mytxt)
|
|
cell.set_property('cell-background',obj['color'])
|
|
|
|
def add_button_clicked(widget):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = [
|
|
('title',_('Notice title'),fake_callback,False),
|
|
('link',_('Link (URL)'),fake_callback,False),
|
|
('notice_text',("text",_('Notice text'),),fake_callback,False),
|
|
]
|
|
data = self.Entropy.inputBox(
|
|
_('Insert your new notice board entry'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
def reload_func():
|
|
self.on_repoManagerNoticeBoardButton_clicked(None, repoid = repoid)
|
|
self.run_add_notice_board_entry(repoid, data['title'], data['notice_text'], data['link'], reload_func)
|
|
|
|
def remove_button_clicked(widget):
|
|
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
ids = set()
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
ids.add(obj['id'])
|
|
if ids:
|
|
def reload_func():
|
|
self.on_repoManagerNoticeBoardButton_clicked(None, repoid = repoid)
|
|
self.run_remove_notice_board_entries(repoid, ids, reload_func)
|
|
|
|
def refresh_button_clicked(widget):
|
|
self.on_repoManagerNoticeBoardButton_clicked(None, repoid = repoid)
|
|
|
|
def view_button_clicked(widget):
|
|
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
my = RmNoticeBoardMenu(self.window)
|
|
my.load(obj)
|
|
|
|
h1 = self.DataViewButtons['notice_board']['add_button'].connect('clicked',add_button_clicked)
|
|
h2 = self.DataViewButtons['notice_board']['remove_button'].connect('clicked',remove_button_clicked)
|
|
h3 = self.DataViewButtons['notice_board']['refresh_button'].connect('clicked',refresh_button_clicked)
|
|
h4 = self.DataViewButtons['notice_board']['view_button'].connect('clicked',view_button_clicked)
|
|
self.DataViewButtons['notice_board']['handler_ids'].extend([h1,h2,h3,h4])
|
|
|
|
self.create_text_column( self.DataView, _( "Notice board" ), 'nb', size = 300, cell_data_func = my_data_text, expand = True, set_height = 36)
|
|
self.fill_notice_board_view(repo_data)
|
|
|
|
self.set_notebook_page(self.notebook_pages['data'])
|
|
self.show_data_view()
|
|
|
|
def fill_notice_board_view(self, repo_data):
|
|
colors = ["#CDEEFF","#AFCBDA"]
|
|
counter = 0
|
|
items, lenght = repo_data
|
|
keys = sorted(items.keys())
|
|
for key in keys:
|
|
counter += 1
|
|
item = items[key].copy()
|
|
item['color'] = colors[counter%len(colors)]
|
|
item['id'] = key
|
|
self.DataStore.append( None, (item,) )
|
|
|
|
|
|
def entropy_mirror_updates_data_view(self, repo_data):
|
|
|
|
self.clear_data_view()
|
|
self.show_data_view_buttons_cat('mirror_updates')
|
|
self.DataView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
|
self.DataView.set_rubber_banding(True)
|
|
|
|
def my_data_text( column, cell, model, myiter, property ):
|
|
obj = model.get_value( myiter, 0 ) # cleanMarkupString
|
|
if obj:
|
|
if obj.has_key('is_master'):
|
|
if obj['from'] == "repoid":
|
|
cell.set_property('markup',"<big><b>%s</b>: <i>%s</i></big>" % (_("Repository"),cleanMarkupString(obj['text']),))
|
|
elif obj['from'] == "pkg_master":
|
|
cell.set_property('markup',"<b>%s</b>: <i>%s</i>" % (_("Action"),cleanMarkupString(obj['text']),))
|
|
elif obj['from'] == "uri":
|
|
cell.set_property('markup',"<b>%s</b>: <u>%s</u>" % (_("Server"),cleanMarkupString(obj['text']),))
|
|
elif obj['from'] == "db":
|
|
yes = _("Yes")
|
|
no = _("No")
|
|
up_action = yes
|
|
if not obj['upload_queue']: up_action = no
|
|
down_action = yes
|
|
if not obj['download_latest']: down_action = no
|
|
cell.set_property('markup',"<b>%s</b>: %s: %s, %s: %s, %s: %s, %s: %s" % (
|
|
_("Database"),
|
|
_("current revision"),
|
|
obj['current_revision'],
|
|
_("remote revision"),
|
|
obj['remote_revision'],
|
|
_("upload"),
|
|
up_action,
|
|
_("download"),
|
|
down_action,
|
|
)
|
|
)
|
|
else:
|
|
if obj['from'] == "pkg":
|
|
cell.set_property('markup',"%s [%s]" % (cleanMarkupString(obj['filename']),cleanMarkupString(obj['size']),))
|
|
|
|
cell.set_property('cell-background',obj['color'])
|
|
|
|
def execute_button_clicked(widget):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = [
|
|
('exec_type',('combo',(_('Execution mode'),[_("Execute all"),_("Execute only selected")]),),fake_callback,False)
|
|
]
|
|
mydata = self.Entropy.inputBox(
|
|
_('Choose the execution mode'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
myiters = []
|
|
if mydata['exec_type'][0] == 0:
|
|
self.DataView.get_selection().select_all()
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
|
|
objects = []
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
#if not obj.has_key('is_master'): continue
|
|
objects.append(obj)
|
|
|
|
run_data = {}
|
|
for obj in objects:
|
|
repoid, dbsync, pkgsync = obj['run']
|
|
if run_data.has_key(repoid): continue
|
|
run_data[repoid] = {
|
|
'db': dbsync,
|
|
'pkg': pkgsync,
|
|
'pretend': True,
|
|
'mirrors': [],
|
|
}
|
|
if not run_data: return
|
|
|
|
def fake_callback_cb(s):
|
|
return True
|
|
|
|
def fake_callback(s):
|
|
return True
|
|
|
|
# now ask for mirrors
|
|
for repoid in run_data.keys():
|
|
|
|
input_params = [
|
|
('commit_msg',_("Commit message"),fake_callback,False,),
|
|
('do_pretend',('checkbox',_("Pretend mode"),),fake_callback_cb,False,),
|
|
('pkg_check',('checkbox',_("Packages check"),),fake_callback_cb,False,),
|
|
]
|
|
|
|
data = self.Entropy.inputBox(
|
|
"[%s] %s" % (repoid,_('Choose sync options'),),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None:
|
|
run_data.pop(repoid)
|
|
continue
|
|
|
|
run_data[repoid]['pretend'] = data['do_pretend']
|
|
run_data[repoid]['pkg_check'] = data['pkg_check']
|
|
run_data[repoid]['commit_msg'] = data['commit_msg']
|
|
|
|
if run_data:
|
|
self.clear_data_store_and_view()
|
|
t = ParallelTask(self.execute_entropy_mirror_updates, run_data)
|
|
t.start()
|
|
|
|
h1 = self.DataViewButtons['mirror_updates']['execute_button'].connect('clicked',execute_button_clicked)
|
|
self.DataViewButtons['mirror_updates']['handler_ids'].extend([h1])
|
|
|
|
self.create_text_column( self.DataView, _( "Mirror updates information" ), 'info', size = 300, cell_data_func = my_data_text, expand = True)
|
|
self.fill_mirror_updates_view(repo_data)
|
|
self.set_notebook_page(self.notebook_pages['data'])
|
|
self.show_data_view()
|
|
return False
|
|
|
|
def entropy_database_updates_data_view(self, data):
|
|
|
|
self.clear_data_view()
|
|
self.show_data_view_buttons_cat('database_updates')
|
|
self.DataView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
|
self.DataView.set_rubber_banding(True)
|
|
|
|
def my_data_text( column, cell, model, myiter, property ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
if property == "package":
|
|
is_cat = False
|
|
if obj.has_key('is_master'):
|
|
is_cat = True
|
|
if is_cat:
|
|
mytxt = "<big><b>%s</b></big>" % (obj['text'],)
|
|
cell.set_property('markup',mytxt)
|
|
elif obj['from'] == "add":
|
|
self.spm_package_obj_to_cell(obj,cell)
|
|
else:
|
|
self.entropy_package_obj_to_cell(obj, cell)
|
|
|
|
elif property == "repoid":
|
|
if obj.has_key('repoid'):
|
|
cell.set_property('markup',"<small>%s</small>" % (cleanMarkupString(obj['repoid']),))
|
|
else:
|
|
cell.set_property('markup','')
|
|
|
|
elif property == "toggle":
|
|
cell.set_active(obj['select'])
|
|
|
|
cell.set_property('cell-background',obj['color'])
|
|
|
|
def package_info_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj.has_key('is_master'): continue
|
|
if obj['from'] != "add":
|
|
self.retrieve_entropy_idpackage_data_and_show(obj['idpackage'], obj['repoid'])
|
|
|
|
def change_repo_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
|
|
avail_repos = self.EntropyRepositories['available'].keys()
|
|
if not avail_repos: return
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = [
|
|
('repoid',('combo',(_('Repository'),avail_repos),),fake_callback,False)
|
|
]
|
|
|
|
objects = []
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj.has_key('is_master'): continue
|
|
if obj['from'] != "add": continue
|
|
objects.append(obj)
|
|
|
|
if objects:
|
|
mydata = self.Entropy.inputBox(
|
|
_('Choose the destination repository'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
to_repoid = mydata['repoid'][1]
|
|
for obj in objects:
|
|
obj['repoid'] = to_repoid
|
|
|
|
self.DataView.queue_draw()
|
|
|
|
def execute_button_clicked(widget):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = [
|
|
('exec_type',('combo',(_('Execution mode'),[_("Execute all"),_("Execute only selected")]),),fake_callback,False)
|
|
]
|
|
mydata = self.Entropy.inputBox(
|
|
_('Choose the execution mode'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
myiters = []
|
|
if mydata['exec_type'][0] == 0:
|
|
self.DataView.get_selection().select_all()
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
|
|
objects = []
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj.has_key('is_master'): continue
|
|
objects.append(obj)
|
|
|
|
to_add = []
|
|
to_remove = []
|
|
to_inject = []
|
|
for obj in objects:
|
|
if obj['from'] == "add":
|
|
to_add.append(obj['match_key']+(obj['repoid'],))
|
|
elif obj['from'] == "remove":
|
|
to_remove.append(obj['match_key'])
|
|
elif obj['from'] == "inject":
|
|
to_inject.append(obj['match_key'])
|
|
|
|
if to_add or to_remove or to_inject:
|
|
def reload_func():
|
|
self.on_repoManagerEntropyDbUpdatesButton_clicked(None)
|
|
self.clear_data_store_and_view()
|
|
self.run_entropy_database_updates(to_add, to_remove, to_inject, reload_func)
|
|
|
|
|
|
h1 = self.DataViewButtons['database_updates']['change_repo_button'].connect('clicked',change_repo_clicked)
|
|
h2 = self.DataViewButtons['database_updates']['package_info_button'].connect('clicked',package_info_clicked)
|
|
h3 = self.DataViewButtons['database_updates']['execute_button'].connect('clicked',execute_button_clicked)
|
|
self.DataViewButtons['database_updates']['handler_ids'].extend([h1,h2,h3])
|
|
|
|
cell_height = 80
|
|
|
|
# package
|
|
self.create_text_column( self.DataView, _( "Package" ), 'package', size = 300, set_height = cell_height, cell_data_func = my_data_text, expand = True)
|
|
# repository
|
|
self.create_text_column( self.DataView, _( "Repository" ), 'repoid', size = 130, set_height = cell_height, cell_data_func = my_data_text)
|
|
self.fill_db_updates_view(data)
|
|
self.set_notebook_page(self.notebook_pages['data'])
|
|
self.show_data_view()
|
|
return False
|
|
|
|
|
|
def fill_db_updates_view(self, data):
|
|
|
|
master_add = {
|
|
'is_master': True,
|
|
'type': "add",
|
|
'text': _("To be added"),
|
|
'color': '#CDEEFF',
|
|
'select': True,
|
|
}
|
|
master_remove = {
|
|
'is_master': True,
|
|
'type': "remove",
|
|
'text': _("To be removed"),
|
|
'color': '#CDEEFF',
|
|
'select': True,
|
|
}
|
|
master_inject = {
|
|
'is_master': True,
|
|
'type': "inject",
|
|
'text': _("To be injected"),
|
|
'color': '#CDEEFF',
|
|
'select': True,
|
|
}
|
|
|
|
add_cats_data = {}
|
|
for spm_atom, spm_counter in data['add_data']:
|
|
cat = self.entropyTools.dep_getkey(spm_atom).split("/")[0]
|
|
if not add_cats_data.has_key(cat):
|
|
add_cats_data[cat] = []
|
|
item = data['add_data'][(spm_atom, spm_counter,)]
|
|
item['repoid'] = self.EntropyRepositories['current']
|
|
item['select'] = True
|
|
item['match_key'] = (spm_atom, spm_counter,)
|
|
add_cats_data[cat].append(item)
|
|
|
|
remove_cats_data = {}
|
|
for idpackage, repoid in data['remove_data']:
|
|
if not data['remove_data'].has_key((idpackage, repoid,)):
|
|
continue
|
|
item = data['remove_data'][(idpackage, repoid,)]
|
|
if not item: continue
|
|
item['select'] = True
|
|
item['match_key'] = (idpackage, repoid,)
|
|
cat = item['category']
|
|
if not remove_cats_data.has_key(cat):
|
|
remove_cats_data[cat] = []
|
|
remove_cats_data[cat].append(item)
|
|
|
|
inject_cats_data = {}
|
|
for idpackage, repoid in data['inject_data']:
|
|
if not data['inject_data'].has_key((idpackage, repoid,)):
|
|
continue
|
|
item = data['inject_data'][(idpackage, repoid,)]
|
|
if not item: continue
|
|
item['select'] = True
|
|
item['match_key'] = (idpackage, repoid,)
|
|
cat = item['category']
|
|
if not inject_cats_data.has_key(cat):
|
|
inject_cats_data[cat] = []
|
|
inject_cats_data[cat].append(item)
|
|
|
|
colors = ["#CDEEFF","#AFCBDA"]
|
|
cat_counter = 0
|
|
counter = 0
|
|
add_cat_keys = sorted(add_cats_data.keys())
|
|
remove_cat_keys = sorted(remove_cats_data.keys())
|
|
inject_cat_keys = sorted(inject_cats_data.keys())
|
|
|
|
# first add
|
|
if add_cats_data: add_parent = self.DataStore.append( None, (master_add,) )
|
|
if remove_cats_data: remove_parent = self.DataStore.append( None, (master_remove,) )
|
|
if inject_cats_data: inject_parent = self.DataStore.append( None, (master_inject,) )
|
|
|
|
for category in add_cat_keys:
|
|
cat_counter += 1
|
|
mydict = {
|
|
'color': colors[cat_counter%len(colors)],
|
|
'is_master': True,
|
|
'type': "category",
|
|
'text': category,
|
|
'select': True,
|
|
}
|
|
myparent = self.DataStore.append( add_parent, (mydict,) )
|
|
for item in add_cats_data[category]:
|
|
counter += 1
|
|
item['color'] = colors[counter%len(colors)]
|
|
item['from'] = 'add'
|
|
item['select'] = True
|
|
self.DataStore.append( myparent, (item,) )
|
|
|
|
cat_counter = 0
|
|
counter = 0
|
|
for category in remove_cat_keys:
|
|
cat_counter += 1
|
|
mydict = {
|
|
'color': colors[cat_counter%len(colors)],
|
|
'is_master': True,
|
|
'type': "category",
|
|
'text': category,
|
|
'select': True,
|
|
}
|
|
myparent = self.DataStore.append( remove_parent, (mydict,) )
|
|
for item in remove_cats_data[category]:
|
|
counter += 1
|
|
item['color'] = colors[counter%len(colors)]
|
|
item['from'] = 'remove'
|
|
item['select'] = True
|
|
self.DataStore.append( myparent, (item,) )
|
|
|
|
cat_counter = 0
|
|
counter = 0
|
|
for category in inject_cat_keys:
|
|
cat_counter += 1
|
|
mydict = {
|
|
'color': colors[cat_counter%len(colors)],
|
|
'is_master': True,
|
|
'type': "category",
|
|
'text': category,
|
|
'select': True,
|
|
}
|
|
myparent = self.DataStore.append( inject_parent, (mydict,) )
|
|
for item in inject_cats_data[category]:
|
|
counter += 1
|
|
item['color'] = colors[counter%len(colors)]
|
|
item['from'] = 'inject'
|
|
item['select'] = True
|
|
self.DataStore.append( myparent, (item,) )
|
|
|
|
self.DataView.expand_all()
|
|
|
|
|
|
def fill_mirror_updates_view(self, data):
|
|
|
|
color_odd = '#FFF7C2'
|
|
color_even = '#E6FFCA'
|
|
|
|
|
|
repos = data.keys()
|
|
for repoid in repos:
|
|
color = color_odd
|
|
master = {
|
|
'is_master': True,
|
|
'text': repoid,
|
|
'from': "repoid",
|
|
'color': color,
|
|
'repoid': repoid,
|
|
'run': (repoid,True,True,) # repoid, dbsync, pkgsync
|
|
}
|
|
parent = self.DataStore.append( None, (master,))
|
|
|
|
for uri in data[repoid]:
|
|
|
|
color = color_odd
|
|
if not data[repoid][uri].has_key('packages'):
|
|
color = color_even
|
|
|
|
uri_master = {
|
|
'is_master': True,
|
|
'text': uri,
|
|
'from': "uri",
|
|
'color': color,
|
|
'repoid': repoid,
|
|
'run': (repoid,True,True,) # repoid, dbsync, pkgsync
|
|
}
|
|
uri_parent = self.DataStore.append( parent, (uri_master,))
|
|
|
|
# db
|
|
db_item = data[repoid][uri]['database']
|
|
db_color = "#FFF7C2"
|
|
if db_item['remote_revision'] == db_item['current_revision']:
|
|
db_color = "#E6FFCA"
|
|
db_item['color'] = db_color
|
|
db_item['from'] = "db"
|
|
db_item['is_master'] = True
|
|
db_item['repoid'] = repoid
|
|
db_item['run'] = (repoid,True,True,) # repoid, dbsync, pkgsync
|
|
|
|
self.DataStore.append( uri_parent, (db_item,))
|
|
if data[repoid][uri].has_key('packages'):
|
|
|
|
for action in data[repoid][uri]['packages']:
|
|
|
|
if data[repoid][uri]['packages'][action]:
|
|
pkgmaster = {
|
|
'is_master': True,
|
|
'text': action,
|
|
'from': "pkg_master",
|
|
'color': color,
|
|
'repoid': repoid,
|
|
'run': (repoid,False,True,)
|
|
}
|
|
pkg_parent = self.DataStore.append( uri_parent, (pkgmaster,))
|
|
|
|
for mypath, mysize in data[repoid][uri]['packages'][action]:
|
|
pkg_item = {
|
|
'from': "pkg",
|
|
'filename': os.path.basename(mypath),
|
|
'size': self.entropyTools.bytes_into_human(mysize),
|
|
'color': color,
|
|
'repoid': repoid,
|
|
'run': (repoid,False,True,)
|
|
}
|
|
self.DataStore.append( pkg_parent, (pkg_item,))
|
|
|
|
self.DataView.expand_all()
|
|
|
|
|
|
def entropy_available_packages_data_view(self, packages_data, repoid, reload_func = None):
|
|
|
|
if not isinstance(packages_data,dict):
|
|
return
|
|
|
|
if reload_func == None:
|
|
def reload_func():
|
|
self.on_repoManagerAvailablePackagesButton_clicked(None, repoid = repoid)
|
|
|
|
self.clear_data_view()
|
|
self.show_data_view_buttons_cat('available_packages')
|
|
self.DataView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
|
self.DataView.set_rubber_banding(True)
|
|
|
|
def my_data_text( column, cell, model, myiter, property ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
if property == "package":
|
|
is_cat = False
|
|
if obj.has_key('is_cat'):
|
|
is_cat = True
|
|
if is_cat:
|
|
mytxt = "<big><b>%s</b></big>" % (obj['name'],)
|
|
cell.set_property('markup',mytxt)
|
|
else:
|
|
self.entropy_package_obj_to_cell(obj, cell)
|
|
elif property == "repoid":
|
|
cell.set_property('markup',"<small>%s</small>" % (cleanMarkupString(obj['repoid']),))
|
|
cell.set_property('cell-background',obj['color'])
|
|
|
|
def package_info_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj.has_key('is_cat'): continue
|
|
self.retrieve_entropy_idpackage_data_and_show(obj['idpackage'], obj['repoid'])
|
|
|
|
def remove_package_button_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
items = []
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj.has_key('is_cat'): continue
|
|
items.append((obj['idpackage'],obj['repoid'],))
|
|
if items:
|
|
self.remove_entropy_packages(items, reload_func = reload_func)
|
|
|
|
def move_package_button_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
if model == None: return
|
|
items = []
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj.has_key('is_cat'): continue
|
|
items.append((obj['idpackage'],obj['repoid'],))
|
|
if items:
|
|
self.move_entropy_packages(items, reload_func)
|
|
|
|
|
|
h1 = self.DataViewButtons['available_packages']['package_info_button'].connect('clicked',package_info_clicked)
|
|
h2 = self.DataViewButtons['available_packages']['remove_package_button'].connect('clicked',remove_package_button_clicked)
|
|
h3 = self.DataViewButtons['available_packages']['move_package_button'].connect('clicked',move_package_button_clicked)
|
|
self.DataViewButtons['available_packages']['handler_ids'].extend([h1,h2,h3])
|
|
|
|
# glsa id
|
|
self.create_text_column( self.DataView, _( "Package" ), 'package', size = 300, set_height = 60, cell_data_func = my_data_text, expand = True)
|
|
|
|
# glsa title
|
|
self.create_text_column( self.DataView, _( "Repository" ), 'repoid', size = 130, set_height = 60, cell_data_func = my_data_text)
|
|
|
|
cats_data = {}
|
|
for idpackage in packages_data['ordered_idpackages']:
|
|
item = packages_data['data'].get(idpackage)
|
|
if item == None: continue
|
|
mycat = item['category']
|
|
if not cats_data.has_key(mycat):
|
|
cats_data[mycat] = []
|
|
cats_data[mycat].append(item)
|
|
|
|
colors = ["#CDEEFF","#AFCBDA"]
|
|
counter = 0
|
|
cat_keys = sorted(cats_data.keys())
|
|
|
|
for category in cat_keys:
|
|
counter += 1
|
|
mydict = {
|
|
'is_cat': True,
|
|
'name': category,
|
|
'color': colors[0],
|
|
'repoid': repoid,
|
|
}
|
|
parent = self.DataStore.append( None, (mydict,) )
|
|
for item in cats_data[category]:
|
|
counter += 1
|
|
item['color'] = colors[counter%len(colors)]
|
|
item['repoid'] = repoid
|
|
self.DataStore.append( parent, (item,) )
|
|
|
|
self.set_notebook_page(self.notebook_pages['data'])
|
|
self.show_data_view()
|
|
return False
|
|
|
|
|
|
def categories_updates_data_view(self, data, categories, expand = False, reload_function = None):
|
|
|
|
if reload_function == None:
|
|
def reload_function():
|
|
self.on_repoManagerCategoryUpdButton_clicked(None, categories = categories, expand = True)
|
|
return False
|
|
|
|
self.clear_data_view()
|
|
self.show_data_view_buttons_cat('categories_updates')
|
|
self.DataView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
|
self.DataView.set_rubber_banding(True)
|
|
|
|
def my_data_text( column, cell, model, myiter, property ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
if obj.has_key('is_cat'):
|
|
txt = "<big><b>%s</b></big>" % (obj['name'],)
|
|
cell.set_property('markup',txt)
|
|
else:
|
|
self.spm_package_obj_to_cell(obj, cell)
|
|
cell.set_property('cell-background',obj['color'])
|
|
|
|
def compile_button_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
atoms = []
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj:
|
|
if obj.has_key('available_atom'):
|
|
if not obj['available_atom']:
|
|
continue
|
|
atom = obj['available_atom']
|
|
else:
|
|
atom = obj['atom']
|
|
atoms.append("="+atom)
|
|
if atoms:
|
|
self.on_compileAtom_clicked(None,atoms)
|
|
|
|
def add_use_button_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
atoms = []
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj.has_key('key') and obj.has_key('slot'):
|
|
atom_string = "%s:%s" % (obj['key'],obj['slot'],)
|
|
atoms.append(atom_string)
|
|
if atoms:
|
|
status = self.on_addUseAtom_clicked(None, atoms = atoms, load_view = False, parallel = False)
|
|
if status:
|
|
gobject.idle_add(reload_function)
|
|
|
|
def remove_use_button_clicked(widget):
|
|
myiters, model = self.collect_data_view_iters()
|
|
atoms = []
|
|
for myiter in myiters:
|
|
obj = model.get_value(myiter, 0)
|
|
if obj.has_key('key') and obj.has_key('slot'):
|
|
atom_string = "%s:%s" % (obj['key'],obj['slot'],)
|
|
atoms.append(atom_string)
|
|
if atoms:
|
|
status = self.on_removeUseAtom_clicked(None, atoms = atoms, load_view = False, parallel = False)
|
|
if status:
|
|
gobject.idle_add(reload_function)
|
|
|
|
h1 = self.DataViewButtons['categories_updates']['compile_button'].connect('clicked',compile_button_clicked)
|
|
h2 = self.DataViewButtons['categories_updates']['add_use_button'].connect('clicked',add_use_button_clicked)
|
|
h3 = self.DataViewButtons['categories_updates']['remove_use_button'].connect('clicked',remove_use_button_clicked)
|
|
self.DataViewButtons['categories_updates']['handler_ids'].extend([h1,h2,h3])
|
|
|
|
# atom
|
|
self.create_text_column( self.DataView, _( "Atom" ), 'atom', size = 220, cell_data_func = my_data_text, set_height = 150, expand = True)
|
|
|
|
colors = ["#D2FFB9","#B0D69B"]
|
|
|
|
counter = 0
|
|
for category in data:
|
|
counter += 1
|
|
master = {'is_cat': True, 'name': category, 'color': colors[counter%len(colors)]}
|
|
parent = self.DataStore.append( None, (master,) )
|
|
for atom in data[category]:
|
|
counter += 1
|
|
obj = data[category][atom].copy()
|
|
obj['atom'] = atom
|
|
obj['color'] = colors[counter%len(colors)]
|
|
self.DataStore.append( parent, (obj,) )
|
|
if expand:
|
|
self.DataView.expand_all()
|
|
|
|
self.set_notebook_page(self.notebook_pages['data'])
|
|
self.show_data_view()
|
|
return False
|
|
|
|
def on_repoManagerQueueDown_clicked(self, widget):
|
|
|
|
( model, iterator ) = self.QueueView.get_selection().get_selected()
|
|
if not iterator: return
|
|
|
|
next_iterator = model.iter_next(iterator)
|
|
if iterator and next_iterator:
|
|
item1 = model.get_value(iterator, 0)
|
|
item2 = model.get_value(next_iterator, 0)
|
|
if item1 and item2:
|
|
item1 = item1.copy()
|
|
item2 = item2.copy()
|
|
def task():
|
|
with self.BufferLock:
|
|
try:
|
|
status, msg = self.Service.Methods.swap_items_in_queue(item1['queue_id'],item2['queue_id'])
|
|
self.debug_print("on_repoManagerQueueDown_clicked","%s, %s" % (status,msg,))
|
|
self.debug_print("on_repoManagerQueueDown_clicked","%s, %s" % (item1,item2,))
|
|
if status:
|
|
self.QueueStore.swap(iterator,next_iterator)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
self.update_queue_view()
|
|
t = ParallelTask(task)
|
|
t.start()
|
|
|
|
def on_repoManagerQueueUp_clicked(self, widget):
|
|
|
|
( model, next_iterator ) = self.QueueView.get_selection().get_selected()
|
|
if not next_iterator: return
|
|
|
|
path = model.get_path(next_iterator)[0]
|
|
iterator = model.get_iter(path-1)
|
|
|
|
if iterator and next_iterator:
|
|
item1 = model.get_value(iterator, 0)
|
|
item2 = model.get_value(next_iterator, 0)
|
|
if item1 and item2:
|
|
item1 = item1.copy()
|
|
item2 = item2.copy()
|
|
def task():
|
|
with self.BufferLock:
|
|
try:
|
|
status, msg = self.Service.Methods.swap_items_in_queue(item1['queue_id'],item2['queue_id'])
|
|
self.debug_print("on_repoManagerQueueUp_clicked","%s, %s" % (status,msg,))
|
|
self.debug_print("on_repoManagerQueueUp_clicked","%s, %s" % (item1,item2,))
|
|
if status:
|
|
self.QueueStore.swap(iterator,next_iterator)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
self.update_queue_view()
|
|
t = ParallelTask(task)
|
|
t.start()
|
|
|
|
def on_repoManagerCategoryUpdButton_clicked(self, widget, categories = [], expand = False):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = []
|
|
if not categories:
|
|
input_params += [
|
|
('categories',_('Categories, space separated'),fake_callback,False),
|
|
]
|
|
data = {}
|
|
data['categories'] = categories
|
|
if input_params:
|
|
mydata = self.Entropy.inputBox(
|
|
_('Insert categories'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
data.update(mydata)
|
|
if not categories:
|
|
data['categories'] = data['categories'].split()
|
|
|
|
if data['categories']:
|
|
self.clear_data_store_and_view()
|
|
self.run_spm_categories_updates(data['categories'], expand)
|
|
|
|
def on_repoManagerCustomRunButton_clicked(self, widget):
|
|
command = self.sm_ui.repoManagerCustomCmdEntry.get_text().strip()
|
|
if not command: return
|
|
self.run_run_custom_shell_command(command)
|
|
|
|
def on_repoManagerInstalledPackages_clicked(self, widget, categories = [], world = False):
|
|
|
|
def fake_callback_true(s):
|
|
return True
|
|
|
|
if world: categories = []
|
|
input_params = []
|
|
if not world:
|
|
input_params += [
|
|
('categories',_('Categories, space separated'),fake_callback_true,False),
|
|
]
|
|
data = {}
|
|
data['categories'] = categories
|
|
if input_params:
|
|
mydata = self.Entropy.inputBox(
|
|
_('Insert categories (if you want)'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
data.update(mydata)
|
|
if not categories:
|
|
data['categories'] = data['categories'].split()
|
|
|
|
self.clear_data_store_and_view()
|
|
self.run_get_spm_categories_installed(data['categories'], world)
|
|
|
|
|
|
def on_repoManagerRunButton_clicked(self, widget):
|
|
|
|
command = self.sm_ui.repoManagerRunEntry.get_text().strip()
|
|
if not command: return
|
|
command = command.split()
|
|
cmd = command[0]
|
|
|
|
avail_cmds = self.Service.get_available_client_commands()
|
|
if cmd not in avail_cmds:
|
|
okDialog(self.window, _("Invalid Command"), title = _("Custom command Error"))
|
|
return
|
|
|
|
cmd_data = avail_cmds.get(cmd)
|
|
params = command[1:]
|
|
mandatory_cmds = []
|
|
for item in cmd_data['params']:
|
|
if item[3]: mandatory_cmds.append(item)
|
|
|
|
evalued_params = []
|
|
for param in params:
|
|
try:
|
|
evalued_params.append(eval(param))
|
|
except (NameError, SyntaxError):
|
|
evalued_params.append(param)
|
|
except TypeError:
|
|
pass
|
|
|
|
if len(evalued_params) < len(mandatory_cmds):
|
|
okDialog(self.window, _("Not enough parameters"), title = _("Custom command Error"))
|
|
return
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
cmd_data['call'](*evalued_params)
|
|
except Exception, e:
|
|
okDialog(self.window, "%s: %s" % (_("Error executing call"),e,), title = _("Custom command Error"))
|
|
|
|
def on_repoManagerPauseQueueButton_toggled(self, widget):
|
|
with self.BufferLock:
|
|
try:
|
|
do_pause = not self.queue_pause
|
|
self.Service.Methods.pause_queue(do_pause)
|
|
self.queue_pause = do_pause
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def on_repoManagerQueueView_row_activated(self, treeview, path, column):
|
|
( model, iterator ) = treeview.get_selection().get_selected()
|
|
if model != None and iterator != None:
|
|
obj = model.get_value( iterator, 0 )
|
|
if obj:
|
|
self.load_queue_info_menu(obj)
|
|
|
|
def on_repoManagerOutputPauseButton_toggled(self, widget):
|
|
if not self.output_pause:
|
|
if isinstance(self.is_processing,dict):
|
|
try:
|
|
self.paused_queue_id = self.is_processing['queue_id']
|
|
except:
|
|
pass
|
|
else:
|
|
# back from pause, schedule refresh
|
|
gobject.idle_add(self.update_output_view, True,
|
|
self.paused_queue_id)
|
|
self.paused_queue_id = None
|
|
self.output_pause = not self.output_pause
|
|
|
|
def on_repoManagerQueueRefreshButton_clicked(self, widget):
|
|
self.Queue = {}
|
|
self.do_update_queue_view()
|
|
|
|
def on_repoManagerOutputCleanButton_clicked(self, widget):
|
|
self.Output = None
|
|
self.clear_console()
|
|
|
|
def on_repoManagerCleanQueue_clicked(self, widget):
|
|
clear_ids = set()
|
|
for item in self.QueueStore:
|
|
obj = item[0]
|
|
if obj['from'] not in ("processed","errored"):
|
|
continue
|
|
clear_ids.add(obj['queue_id'])
|
|
if clear_ids: self.run_remove_queue_ids(clear_ids)
|
|
|
|
def on_repoManagerClose_clicked(self, *args, **kwargs):
|
|
self.QueueUpdater.kill()
|
|
self.OutputUpdater.kill()
|
|
self.PinboardUpdater.kill()
|
|
self.destroy()
|
|
|
|
def on_portageSync_clicked(self, widget):
|
|
self.run_sync_spm()
|
|
|
|
def on_removeAtom_clicked(self, widget, atoms = [], pretend = True, verbose = True, nocolor = True):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
def fake_bool_cb(s):
|
|
return True
|
|
def fake_true_callback(s):
|
|
return True
|
|
|
|
input_params = []
|
|
data = {}
|
|
data['atoms'] = atoms
|
|
data['pretend'] = pretend
|
|
data['verbose'] = verbose
|
|
data['nocolor'] = nocolor
|
|
if not atoms:
|
|
input_params.append(('atoms',_('Atoms, space separated'),fake_callback,False),)
|
|
input_params += [
|
|
('pretend',('checkbox',_('Pretend'),),fake_bool_cb,pretend,),
|
|
('verbose',('checkbox',_('Verbose'),),fake_bool_cb,verbose,),
|
|
('nocolor',('checkbox',_('No color'),),fake_bool_cb,nocolor,),
|
|
]
|
|
mydata = self.Entropy.inputBox(
|
|
_('Insert packages removal parameters'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
data.update(mydata)
|
|
if not atoms:
|
|
data['atoms'] = data['atoms'].split()
|
|
|
|
if data['atoms']:
|
|
self.run_spm_remove_atoms(data)
|
|
|
|
|
|
def on_compileAtom_clicked(self, widget, atoms = [], pretend = False, oneshot = False, verbose = True, nocolor = True, fetchonly = False, buildonly = False, nodeps = False, custom_use = '', ldflags = '', cflags = ''):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
def fake_bool_cb(s):
|
|
return True
|
|
def fake_true_callback(s):
|
|
return True
|
|
|
|
input_params = []
|
|
data = {}
|
|
data['atoms'] = atoms
|
|
data['pretend'] = pretend
|
|
data['oneshot'] = oneshot
|
|
data['verbose'] = verbose
|
|
data['nocolor'] = nocolor
|
|
data['fetchonly'] = fetchonly
|
|
data['buildonly'] = buildonly
|
|
data['nodeps'] = nodeps
|
|
data['custom_use'] = custom_use
|
|
data['ldflags'] = ldflags
|
|
data['cflags'] = cflags
|
|
if not atoms:
|
|
input_params.append(('atoms',_('Atoms, space separated'),fake_callback,False),)
|
|
input_params += [
|
|
('pretend',('checkbox',_('Pretend'),),fake_bool_cb,pretend,),
|
|
('oneshot',('checkbox',_('Oneshot'),),fake_bool_cb,oneshot,),
|
|
('verbose',('checkbox',_('Verbose'),),fake_bool_cb,verbose,),
|
|
('nocolor',('checkbox',_('No color'),),fake_bool_cb,nocolor,),
|
|
('fetchonly',('checkbox',_('Fetch only'),),fake_bool_cb,fetchonly,),
|
|
('buildonly',('checkbox',_('Build only'),),fake_bool_cb,buildonly,),
|
|
('nodeps',('checkbox',_('No dependencies'),),fake_bool_cb,nodeps,),
|
|
('custom_use',_('Custom USE flags'),fake_true_callback,False),
|
|
('ldflags',_('Custom LDFLAGS'),fake_true_callback,False),
|
|
('cflags',_('Custom CFLAGS'),fake_true_callback,False),
|
|
]
|
|
mydata = self.Entropy.inputBox(
|
|
_('Insert compilation parameters'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
data.update(mydata)
|
|
if not atoms:
|
|
data['atoms'] = data['atoms'].split()
|
|
|
|
if data['atoms']:
|
|
self.run_compile_atoms(data)
|
|
|
|
def on_repoManagerSpmInfo_clicked(self, widget):
|
|
self.run_spm_info()
|
|
|
|
def on_addUseAtom_clicked(self, widget, atoms = [], use = [], load_view = True, parallel = True):
|
|
data = self.handle_uses_for_atoms(atoms, use)
|
|
if data == None: return False
|
|
self.set_notebook_page(self.notebook_pages['data'])
|
|
if data['atoms'] and data['use']:
|
|
if parallel:
|
|
def do_add():
|
|
self.run_enable_uses_for_atoms(data['atoms'], data['use'], load_view)
|
|
return False
|
|
gobject.idle_add(do_add)
|
|
else:
|
|
return self.run_enable_uses_for_atoms(data['atoms'], data['use'], load_view)
|
|
|
|
def on_removeUseAtom_clicked(self, widget, atoms = [], use = [], load_view = True, parallel = True):
|
|
data = self.handle_uses_for_atoms(atoms, use)
|
|
if data == None: return False
|
|
self.set_notebook_page(self.notebook_pages['data'])
|
|
if data['atoms'] and data['use']:
|
|
if parallel:
|
|
def do_remove():
|
|
self.run_disable_uses_for_atoms(data['atoms'], data['use'], load_view)
|
|
return False
|
|
gobject.idle_add(do_remove)
|
|
else:
|
|
return self.run_disable_uses_for_atoms(data['atoms'], data['use'], load_view)
|
|
|
|
def on_repoManagerPkgInfo_clicked(self, widget, atoms = [], clear = True):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = []
|
|
data = {}
|
|
data['atoms'] = atoms
|
|
if not atoms:
|
|
input_params.append(('atoms',_('Atoms, space separated'),fake_callback,False),)
|
|
if input_params:
|
|
mydata = self.Entropy.inputBox(
|
|
_('Insert Package Information parameters'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
data.update(mydata)
|
|
if not atoms:
|
|
data['atoms'] = data['atoms'].split()
|
|
|
|
if data['atoms']:
|
|
categories = []
|
|
for atom in data['atoms']:
|
|
categories.append(self.entropyTools.dep_getkey(atom).split("/")[0])
|
|
if clear: self.clear_data_store_and_view()
|
|
self.run_get_spm_atoms_info(categories, data['atoms'], clear)
|
|
|
|
def on_repoManagerRemoveButton_clicked(self, widget):
|
|
model, myiter = self.QueueView.get_selection().get_selected()
|
|
if myiter:
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj and (obj['from'] != "processing"):
|
|
self.run_remove_queue_ids([obj['queue_id']])
|
|
|
|
def on_repoManagerStopButton_clicked(self, widget):
|
|
model, myiter = self.QueueView.get_selection().get_selected()
|
|
if myiter:
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj and (obj['from'] == "processing"):
|
|
self.run_kill_processing_queue_id(obj['queue_id'])
|
|
|
|
def on_repoManagerQueueGetOutputButton_clicked(self, widget, queue_id = None, myfrom = None):
|
|
|
|
def fake_callback_cb(s):
|
|
return True
|
|
|
|
model, myiter = self.QueueView.get_selection().get_selected()
|
|
if myiter:
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
queue_id = obj['queue_id']
|
|
myfrom = obj['from']
|
|
|
|
if not queue_id: return
|
|
|
|
input_params = [
|
|
('full',("checkbox",_('Full output'),),fake_callback_cb,False),
|
|
]
|
|
if myfrom == "processing":
|
|
input_params.append(('autorefresh', ("checkbox",_('Auto refresh'),),fake_callback_cb,True))
|
|
data = self.Entropy.inputBox(
|
|
_('Insert output parameters'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
|
|
if data.has_key('autorefresh'):
|
|
if data['autorefresh']:
|
|
self.is_writing_output = True
|
|
self.is_processing = {'queue_id': queue_id}
|
|
|
|
self.set_notebook_page(self.notebook_pages['output'])
|
|
if data.get('full'):
|
|
gobject.idle_add(self.update_output_view, True, queue_id, 0)
|
|
else:
|
|
gobject.idle_add(self.update_output_view, True, queue_id)
|
|
|
|
|
|
def on_repoManagerPinboardRefreshButton_clicked(self, widget):
|
|
self.update_pinboard_view(force = True)
|
|
|
|
def on_repoManagerPinboardAddButton_clicked(self, widget):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = [
|
|
('note',_('Note'),fake_callback,False),
|
|
('extended_text',("text",_('Extended note'),),fake_callback,False),
|
|
]
|
|
data = self.Entropy.inputBox(
|
|
_('Insert your new pinboard item'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
|
|
self.run_add_to_pinboard(data['note'], data['extended_text'])
|
|
|
|
def collect_pinboard_view_iters(self):
|
|
model, paths = self.PinboardView.get_selection().get_selected_rows()
|
|
if not model:
|
|
return [], model
|
|
data = []
|
|
for path in paths:
|
|
myiter = model.get_iter(path)
|
|
data.append(myiter)
|
|
return data, model
|
|
|
|
def on_repoManagerPinboardRemoveButton_clicked(self, widget):
|
|
|
|
myiters, model = self.collect_pinboard_view_iters()
|
|
if model == None: return
|
|
remove_ids = []
|
|
for myiter in myiters:
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
remove_ids.append(obj['pinboard_id'])
|
|
|
|
if remove_ids:
|
|
self.run_remove_from_pinboard(remove_ids)
|
|
|
|
def on_repoManagerPinboardDoneButton_clicked(self, widget):
|
|
self._set_pinboard_items_status(widget, True)
|
|
|
|
def on_repoManagerPinboardNotDoneButton_clicked(self, widget):
|
|
self._set_pinboard_items_status(widget, False)
|
|
|
|
def _set_pinboard_items_status(self, widget, status):
|
|
|
|
myiters, model = self.collect_pinboard_view_iters()
|
|
if model == None: return
|
|
done_ids = []
|
|
for myiter in myiters:
|
|
obj = model.get_value( myiter, 0 )
|
|
if obj:
|
|
done_ids.append(obj['pinboard_id'])
|
|
|
|
def set_pinboard_status(done_ids, status):
|
|
if done_ids:
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.set_pinboard_items_done(done_ids, status)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
if status:
|
|
self.on_repoManagerPinboardRefreshButton_clicked(widget)
|
|
|
|
set_pinboard_status(done_ids, status)
|
|
|
|
def on_repoManagerPinboardView_row_activated(self, treeview, path, column):
|
|
model = treeview.get_model()
|
|
myiter = model.get_iter(path)
|
|
obj = model.get_value(myiter, 0)
|
|
if obj:
|
|
my = SmPinboardMenu(self.window)
|
|
my.load(obj.copy())
|
|
|
|
def on_repoManagerSecurityUpdatesButton_clicked(self, widget):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = [
|
|
('list_type',('combo',(_('List type'),['affected', 'new', 'all']),),fake_callback,False),
|
|
]
|
|
data = self.Entropy.inputBox(
|
|
_('Choose what kind of list you want to see'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
self.clear_data_store_and_view()
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.get_spm_glsa_data(data['list_type'][1])
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(queue_id, data):
|
|
item = self.wait_queue_id_to_complete(queue_id)
|
|
if item == None: return
|
|
try:
|
|
status, data = item['result']
|
|
except TypeError:
|
|
status = False
|
|
if not status: return
|
|
gobject.idle_add(self.glsa_data_view, data)
|
|
|
|
if status:
|
|
t = ParallelTask(task, queue_id, data)
|
|
t.start()
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def on_repoManagerSwitchRepoButton_clicked(self, widget):
|
|
|
|
# get current combo iter
|
|
model = self.EntropyRepositoryStore
|
|
myiter = self.EntropyRepositoryCombo.get_active_iter()
|
|
repoid = model.get_value(myiter, 0)
|
|
if not repoid: return
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, queue_id = self.Service.Methods.set_default_repository(repoid)
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task():
|
|
repo_info = self.get_available_repositories()
|
|
if repo_info:
|
|
gobject.idle_add(self.load_available_repositories,
|
|
repo_info)
|
|
|
|
if status:
|
|
t = ParallelTask(task)
|
|
t.start()
|
|
else:
|
|
self.service_status_message(queue_id)
|
|
|
|
def on_repoManagerAvailablePackagesButton_clicked(self, widget, repoid = None):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
data = {}
|
|
data['repoid'] = repoid
|
|
avail_repos = self.EntropyRepositories['available'].keys()
|
|
if not avail_repos: return
|
|
input_params = []
|
|
if not repoid:
|
|
input_params.append(('repoid',('combo',(_('Repository'),avail_repos),),fake_callback,False))
|
|
|
|
if input_params:
|
|
mydata = self.Entropy.inputBox(
|
|
_('Choose from which repository'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if mydata == None: return
|
|
mydata['repoid'] = mydata['repoid'][1]
|
|
data.update(mydata)
|
|
|
|
self.clear_data_store_and_view()
|
|
|
|
with self.BufferLock:
|
|
try:
|
|
status, repo_data = self.Service.Methods.get_available_entropy_packages(data['repoid'])
|
|
except Exception, e:
|
|
self.service_status_message(e)
|
|
return
|
|
|
|
def task(repo_data, data):
|
|
def reload_func():
|
|
self.on_repoManagerAvailablePackagesButton_clicked(widget,
|
|
repoid = data['repoid'])
|
|
gobject.idle_add(self.entropy_available_packages_data_view,
|
|
repo_data, data['repoid'], reload_func)
|
|
|
|
if status:
|
|
t = ParallelTask(task, repo_data, data)
|
|
t.start()
|
|
else:
|
|
self.service_status_message(repo_data)
|
|
|
|
def on_repoManagerPackageSearchButton_clicked(self, widget):
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
avail_repos = self.EntropyRepositories['available'].keys()
|
|
if not avail_repos: return
|
|
|
|
search_reference = {
|
|
0: 'atom',
|
|
1: 'needed',
|
|
2: 'depends',
|
|
3: 'tag',
|
|
4: 'file',
|
|
5: 'description',
|
|
6: 'eclass',
|
|
}
|
|
search_types = [
|
|
_("Atom"), _("Needed Libraries") , _("Reverse dependencies"), _("Tag"), _("File"), _("Description"), _("Eclass")
|
|
]
|
|
input_params = [
|
|
('repoid',('combo',(_('Repository'),avail_repos),),fake_callback,False),
|
|
('search_type',('combo',(_('Search type'),search_types),),fake_callback,False),
|
|
('search_string',_('Search string'),fake_callback,False)
|
|
]
|
|
data = self.Entropy.inputBox(
|
|
_('Entropy Search'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
data['search_type'] = search_reference.get(data['search_type'][0])
|
|
data['repoid'] = data['repoid'][1]
|
|
self.clear_data_store_and_view()
|
|
self.run_package_search(data['search_type'], data['search_string'], data['repoid'])
|
|
|
|
def on_repoManagerEntropyDbUpdatesButton_clicked(self, widget):
|
|
self.clear_data_store_and_view()
|
|
self.run_entropy_database_updates_scan()
|
|
|
|
def on_repoManagerDepTestButton_clicked(self, widget):
|
|
self.run_entropy_deptest()
|
|
|
|
def on_repoManagerLibTestButton_clicked(self, widget):
|
|
self.run_entropy_libtest()
|
|
|
|
def on_repoManagerSpmTreeupdatesButton_clicked(self, widget):
|
|
|
|
avail_repos = self.EntropyRepositories['available'].keys()
|
|
if not avail_repos: return
|
|
|
|
def fake_callback_cb(s):
|
|
return True
|
|
|
|
input_params = [
|
|
('repoid',('combo',(_('Repository'),avail_repos),),fake_callback_cb,False),
|
|
]
|
|
|
|
data = self.Entropy.inputBox(
|
|
_('Choose the repository'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
data['repoid'] = data['repoid'][1]
|
|
|
|
self.run_entropy_treeupdates(data['repoid'])
|
|
|
|
def on_repoManagerMirrorUpdatesButton_clicked(self, widget):
|
|
|
|
avail_repos = self.EntropyRepositories['available'].keys()
|
|
if not avail_repos: return
|
|
|
|
def fake_callback_cb(s):
|
|
return True
|
|
|
|
input_params = []
|
|
for repo in avail_repos:
|
|
input_params.append((repo,('checkbox',"%s: %s" % (_('Repository'),repo,),),fake_callback_cb,False))
|
|
|
|
data = self.Entropy.inputBox(
|
|
_('Choose the repositories you want to scan'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
repos = []
|
|
for key in data:
|
|
if data[key]:
|
|
repos.append(key)
|
|
if not repos: return
|
|
|
|
self.clear_data_store_and_view()
|
|
self.run_entropy_mirror_updates(repos)
|
|
|
|
def on_repoManagerChecksumTestButton_clicked(self, widget):
|
|
|
|
avail_repos = self.EntropyRepositories['available'].keys()
|
|
if not avail_repos: return
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = [
|
|
('repoid',('combo',(_('Repository'),avail_repos),),fake_callback,False),
|
|
('mode',('combo',(_('Choose mode'),[_("Server check"),_("Mirrors check")]),),fake_callback,False),
|
|
]
|
|
data = self.Entropy.inputBox(
|
|
_('Choose what kind of test you would like to run'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
if data['mode'][0] == 0:
|
|
mode = "local"
|
|
else:
|
|
mode = "remote"
|
|
data['repoid'] = data['repoid'][1]
|
|
self.run_entropy_checksum_test(data['repoid'], mode)
|
|
|
|
def on_repoManagerStdinExecButton_clicked(self, widget):
|
|
self.sm_ui.repoManagerStdinEntry.activate()
|
|
|
|
def on_repoManagerStdinEntry_activate(self, widget, write_to_stdout = True, txt = ''):
|
|
if not self.is_processing: return
|
|
try: queue_id = self.is_processing.get('queue_id')
|
|
except: return
|
|
if not txt:
|
|
txt = self.sm_ui.repoManagerStdinEntry.get_text()
|
|
if not txt: return
|
|
self.sm_ui.repoManagerStdinEntry.set_text('')
|
|
self.run_write_to_running_command_pipe(queue_id, write_to_stdout, txt)
|
|
|
|
def on_repoManagerNoticeBoardButton_clicked(self, widget, repoid = None):
|
|
|
|
avail_repos = self.EntropyRepositories['available'].keys()
|
|
if not avail_repos: return
|
|
|
|
def fake_callback(s):
|
|
return s
|
|
|
|
input_params = []
|
|
if not repoid:
|
|
input_params += [
|
|
('repoid',('combo',(_('Repository'),avail_repos),),fake_callback,False),
|
|
]
|
|
if input_params:
|
|
data = self.Entropy.inputBox(
|
|
_('Choose what notice board you want to see'),
|
|
input_params,
|
|
cancel_button = True
|
|
)
|
|
if data == None: return
|
|
repoid = data['repoid'][1]
|
|
|
|
if repoid in avail_repos:
|
|
self.run_get_notice_board(repoid)
|
|
|
|
def destroy(self):
|
|
self.sm_ui.repositoryManager.destroy()
|
|
|
|
class SmPinboardMenu(MenuSkel):
|
|
|
|
def __init__(self, window):
|
|
|
|
self.window = window
|
|
self.sm_ui = UI( const.GLADE_FILE, 'smPinboardInfo', 'entropy' )
|
|
self.sm_ui.signal_autoconnect(self._getAllMethods())
|
|
self.sm_ui.smPinboardInfo.set_transient_for(self.window)
|
|
self.sm_ui.smPinboardInfo.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
|
|
def on_smPinboardCloseButton_clicked(self, widget):
|
|
self.sm_ui.smPinboardInfo.hide()
|
|
|
|
def destroy(self):
|
|
self.sm_ui.smPinboardInfo.destroy()
|
|
|
|
def load(self, item):
|
|
|
|
na = _("N/A")
|
|
self.sm_ui.smPinboardId.set_text(unicode(item['pinboard_id']))
|
|
self.sm_ui.smPinboardDate.set_text(unicode(item['ts']))
|
|
self.sm_ui.smPinboardDone.set_text(unicode(item['done']))
|
|
self.sm_ui.smPinboardNote.set_text(unicode(item['note']))
|
|
mybuffer = gtk.TextBuffer()
|
|
mybuffer.set_text(unicode(item['extended_text']))
|
|
self.sm_ui.smPinboardExtendedNote.set_buffer(mybuffer)
|
|
|
|
bold_items = [
|
|
self.sm_ui.smPinboardIdLabel,
|
|
self.sm_ui.smPinboardDateLabel,
|
|
self.sm_ui.smPinboardDoneLabel,
|
|
self.sm_ui.smPinboardNoteLabel,
|
|
self.sm_ui.smPinboardExtendedNoteLabel
|
|
]
|
|
small_items = [
|
|
self.sm_ui.smPinboardId,
|
|
self.sm_ui.smPinboardDate,
|
|
self.sm_ui.smPinboardDone,
|
|
self.sm_ui.smPinboardNote,
|
|
]
|
|
for item in bold_items:
|
|
t = item.get_text()
|
|
item.set_markup("<small><b>%s</b></small>" % (t,))
|
|
for item in small_items:
|
|
t = item.get_text()
|
|
item.set_markup("<small>%s</small>" % (t,))
|
|
|
|
self.sm_ui.smPinboardInfo.show_all()
|
|
|
|
|
|
class RmNoticeBoardMenu(MenuSkel):
|
|
|
|
def __init__(self, window):
|
|
|
|
self.window = window
|
|
self.rm_ui = UI( const.GLADE_FILE, 'rmNoticeBoardInfo', 'entropy' )
|
|
self.rm_ui.signal_autoconnect(self._getAllMethods())
|
|
self.rm_ui.rmNoticeBoardInfo.set_transient_for(self.window)
|
|
self.rm_ui.rmNoticeBoardInfo.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
self.url = None
|
|
gtk.link_button_set_uri_hook(self.load_url, data=self.url)
|
|
|
|
def load_url(self, widget, url, extra):
|
|
import subprocess
|
|
f = open("/dev/null","w")
|
|
subprocess.call(['xdg-open',url], stdout = f, stderr = f)
|
|
f.close()
|
|
|
|
def on_rmNoticeBoardCloseButton_clicked(self, widget):
|
|
self.rm_ui.rmNoticeBoardInfo.hide()
|
|
self.rm_ui.rmNoticeBoardInfo.destroy()
|
|
|
|
def destroy(self):
|
|
self.rm_ui.rmNoticeBoardInfo.destroy()
|
|
|
|
def load(self, item):
|
|
|
|
na = _("N/A")
|
|
self.rm_ui.rmNoticeBoardIdLabel.set_text(unicode(item['id']))
|
|
self.rm_ui.rmNoticeBoardDateLabel.set_text(cleanMarkupString(unicode(item['pubDate'])))
|
|
self.rm_ui.rmNoticeBoardTitleLabel.set_text(cleanMarkupString(item['title']))
|
|
self.rm_ui.rmNoticeBoardLinkLabel.set_label(item['link'])
|
|
self.rm_ui.rmNoticeBoardLinkLabel.set_uri(item['link'])
|
|
self.url = item['link']
|
|
self.rm_ui.rmNoticeBoardTextLabel.set_text(cleanMarkupString(item['description']))
|
|
|
|
bold_items = [
|
|
self.rm_ui.rmNoticeBoardId,
|
|
self.rm_ui.rmNoticeBoardDate,
|
|
self.rm_ui.rmNoticeBoardTitle,
|
|
self.rm_ui.rmNoticeBoardLink
|
|
]
|
|
small_items = [
|
|
self.rm_ui.rmNoticeBoardIdLabel,
|
|
self.rm_ui.rmNoticeBoardDateLabel,
|
|
self.rm_ui.rmNoticeBoardTitleLabel,
|
|
]
|
|
for item in bold_items:
|
|
t = item.get_text()
|
|
item.set_markup("<span foreground='%s'><small><b>%s</b></small></span>" % (SpritzConf.color_title,t,))
|
|
for item in small_items:
|
|
t = item.get_text()
|
|
item.set_markup("<span foreground='%s'><small>%s</small></span>" % (SpritzConf.color_pkgsubtitle,t,))
|
|
t = self.rm_ui.rmNoticeBoardTextLabel.get_text()
|
|
self.rm_ui.rmNoticeBoardTextLabel.set_markup("<span foreground='%s'><small>%s</small></span>" % (SpritzConf.color_subdesc,t,))
|
|
self.rm_ui.rmNoticeBoardInfo.show_all()
|
|
|
|
class SmQueueMenu(MenuSkel):
|
|
|
|
def __init__(self, window):
|
|
|
|
self.window = window
|
|
self.sm_ui = UI( const.GLADE_FILE, 'smQueueInfo', 'entropy' )
|
|
self.sm_ui.signal_autoconnect(self._getAllMethods())
|
|
self.sm_ui.smQueueInfo.set_transient_for(self.window)
|
|
self.sm_ui.smQueueInfo.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
|
|
def on_smQueueCloseButton_clicked(self, widget):
|
|
self.sm_ui.smQueueInfo.hide()
|
|
|
|
def destroy(self):
|
|
self.sm_ui.smQueueInfo.destroy()
|
|
|
|
def load(self, item):
|
|
|
|
na = _("N/A")
|
|
self.sm_ui.smQueueIdL.set_text(unicode(item['queue_id']))
|
|
self.sm_ui.smCommandNameL.set_text(item['command_name'])
|
|
self.sm_ui.smCommandDescL.set_text(item['command_desc'])
|
|
args = "None"
|
|
if isinstance(item['args'],list):
|
|
args = ' '.join([unicode(x) for x in item['args']])
|
|
self.sm_ui.smCommandArgsL.set_text(args)
|
|
self.sm_ui.smCallL.set_text(item['call'])
|
|
self.sm_ui.smUserGroupL.set_text("%s / %s " % (item.get('user_id'),item.get('group_id'),))
|
|
self.sm_ui.smQueuedAtL.set_text(unicode(item['queue_ts']))
|
|
self.sm_ui.smProcessingAtL.set_text(unicode(item.get('processing_ts')))
|
|
self.sm_ui.smCompletedAtL.set_text(unicode(item.get('completed_ts')))
|
|
self.sm_ui.smErroredAtL.set_text(unicode(item.get('errored_ts')))
|
|
self.sm_ui.smStdoutFileL.set_text(unicode(item['stdout']))
|
|
self.sm_ui.smProcessResultL.set_text(unicode(item.get('result')))
|
|
|
|
bold_items = [
|
|
|
|
self.sm_ui.smQueueIdLabel,
|
|
self.sm_ui.smCommandNameLabel,
|
|
self.sm_ui.smCommandDescLabel,
|
|
self.sm_ui.smCommandArgsLabel,
|
|
self.sm_ui.smCallLabel,
|
|
self.sm_ui.smUserGroupLabel,
|
|
self.sm_ui.smQueuedAtLabel,
|
|
self.sm_ui.smProcessingAtLabel,
|
|
self.sm_ui.smCompletedAtLabel,
|
|
self.sm_ui.smErroredAtLabel,
|
|
self.sm_ui.smStdoutFileLabel,
|
|
self.sm_ui.smProcessResultLabel
|
|
|
|
]
|
|
small_items = [
|
|
self.sm_ui.smQueueIdL,
|
|
self.sm_ui.smCommandNameL,
|
|
self.sm_ui.smCommandDescL,
|
|
self.sm_ui.smCommandArgsL,
|
|
self.sm_ui.smCallL,
|
|
self.sm_ui.smUserGroupL,
|
|
self.sm_ui.smQueuedAtL,
|
|
self.sm_ui.smProcessingAtL,
|
|
self.sm_ui.smCompletedAtL,
|
|
self.sm_ui.smErroredAtL,
|
|
self.sm_ui.smStdoutFileL,
|
|
self.sm_ui.smProcessResultL
|
|
]
|
|
for item in bold_items:
|
|
t = item.get_text()
|
|
item.set_markup("<small><b>%s</b></small>" % (t,))
|
|
for item in small_items:
|
|
t = item.get_text()
|
|
item.set_markup("<small>%s</small>" % (t,))
|
|
|
|
self.sm_ui.smQueueInfo.show_all()
|
|
|
|
class PkgInfoMenu(MenuSkel):
|
|
|
|
import entropy.tools as entropyTools
|
|
def __init__(self, Entropy, pkg, window):
|
|
|
|
self.pkg_pixmap = const.pkg_pixmap
|
|
self.ugc_small_pixmap = const.ugc_small_pixmap
|
|
self.ugc_pixmap = const.ugc_pixmap
|
|
self.refresh_pixmap = const.refresh_pixmap
|
|
self.star_normal_pixmap = const.star_normal_pixmap
|
|
self.star_selected_pixmap = const.star_selected_pixmap
|
|
self.star_empty_pixmap = const.star_empty_pixmap
|
|
|
|
self.loading_pix = gtk.image_new_from_file(const.loading_pix)
|
|
self.ugc_data = None
|
|
self.ugc_status_message = None
|
|
self.pkg = pkg
|
|
self.vote = 0
|
|
self.window = window
|
|
self.Entropy = Entropy
|
|
self.repository = None
|
|
self.pkgkey = None
|
|
self.ugc_page_idx = 5
|
|
self.switched_to_ugc_page = False
|
|
self.pkginfo_ui = UI( const.GLADE_FILE, 'pkgInfo', 'entropy' )
|
|
self.pkginfo_ui.signal_autoconnect(self._getAllMethods())
|
|
if self.window:
|
|
self.pkginfo_ui.pkgInfo.set_transient_for(self.window)
|
|
self.pkginfo_ui.pkgInfo.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
# noeeees! otherwise voting won't work
|
|
#self.pkginfo_ui.pkgInfo.connect('button-press-event', self.on_button_press)
|
|
self.setupPkgPropertiesView()
|
|
|
|
def set_pixbuf_to_cell(self, cell, path):
|
|
try:
|
|
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
|
|
cell.set_property( 'pixbuf', pixbuf )
|
|
except gobject.GError:
|
|
pass
|
|
|
|
def ugc_pixbuf( self, column, cell, model, myiter ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if isinstance(obj,dict):
|
|
if obj.has_key('preview_path'):
|
|
self.set_pixbuf_to_cell(cell,obj['preview_path'])
|
|
else:
|
|
self.set_pixbuf_to_cell(cell,obj['image_path'])
|
|
self.set_colors_to_cell(cell, obj)
|
|
|
|
def ugc_content( self, column, cell, model, myiter ):
|
|
obj = model.get_value( myiter, 0 )
|
|
if isinstance(obj,dict):
|
|
self.set_colors_to_cell(cell,obj)
|
|
|
|
if obj.has_key('is_cat'):
|
|
cell.set_property('markup',"<b>%s</b>\n<small>%s</small>" % (obj['parent_desc'],_("Expand to browse"),))
|
|
else:
|
|
title = _("N/A")
|
|
if obj['title']:
|
|
title = unicode(obj['title'],'raw_unicode_escape')
|
|
description = _("N/A")
|
|
if obj['description']:
|
|
description = obj['description']
|
|
if obj['iddoctype'] in (etpConst['ugc_doctypes']['comments'], etpConst['ugc_doctypes']['bbcode_doc'],):
|
|
myddata = obj['ddata']
|
|
if not isinstance(obj['ddata'],basestring):
|
|
myddata = myddata.tostring()
|
|
description = unicode(myddata,'raw_unicode_escape')
|
|
if len(description) > 100:
|
|
description = description[:100].strip()+"..."
|
|
mytxt = "<small><b>%s</b>: %s, %s: %s\n<b>%s</b>: %s, <i>%s</i>\n<b>%s</b>: %s\n<b>%s</b>: <i>%s</i>\n<b>%s</b>: %s</small>" % (
|
|
_("Identifier"),
|
|
obj['iddoc'],
|
|
_("Size"),
|
|
self.entropyTools.bytes_into_human(obj['size']),
|
|
_("Author"),
|
|
obj['username'],
|
|
obj['ts'],
|
|
_("Title"),
|
|
title,
|
|
_("Description"),
|
|
description,
|
|
_("Keywords"),
|
|
', '.join(obj['keywords']),
|
|
)
|
|
cell.set_property('markup',mytxt)
|
|
|
|
def set_colors_to_cell(self, cell, obj):
|
|
odd = 0
|
|
if obj.has_key('counter'):
|
|
odd = obj['counter']%2
|
|
if obj.has_key('background'):
|
|
cell.set_property('cell-background',obj['background'][odd])
|
|
else:
|
|
cell.set_property('cell-background',None)
|
|
try:
|
|
if obj.has_key('foreground'):
|
|
cell.set_property('foreground',obj['foreground'])
|
|
else:
|
|
cell.set_property('foreground',None)
|
|
except TypeError:
|
|
pass
|
|
|
|
|
|
def on_button_press(self, widget, event):
|
|
self.pkginfo_ui.pkgInfo.begin_move_drag(
|
|
event.button,
|
|
int(event.x_root),
|
|
int(event.y_root),
|
|
event.time)
|
|
|
|
def on_showContentButton_clicked( self, widget ):
|
|
content = self.pkg.contentExt
|
|
for x in content:
|
|
self.contentModel.append(None,[x[0],x[1]])
|
|
|
|
def on_closeInfo_clicked(self, widget):
|
|
self.reset_ugc_data()
|
|
self.pkginfo_ui.pkgInfo.hide()
|
|
|
|
def on_pkgInfo_delete_event(self, widget, path):
|
|
self.reset_ugc_data()
|
|
self.pkginfo_ui.pkgInfo.hide()
|
|
return True
|
|
|
|
def on_loadUgcButton_clicked(self, widget, force = True):
|
|
self.spawn_ugc_load(force = force)
|
|
|
|
def on_ugcRemoveButton_released(self, widget):
|
|
if self.Entropy.UGC == None: return
|
|
if self.repository == None: return
|
|
model, myiter = self.ugcView.get_selection().get_selected()
|
|
if myiter == None: return
|
|
obj = model.get_value( myiter, 0 )
|
|
if not isinstance(obj,dict): return
|
|
if obj.has_key('is_cat'): return
|
|
self.show_loading()
|
|
self.Entropy.UGC.remove_document_autosense(self.repository, int(obj['iddoc']), obj['iddoctype'])
|
|
self.hide_loading()
|
|
self.reset_ugc_data()
|
|
self.spawn_ugc_load(force = True)
|
|
self.refresh_ugc_view()
|
|
|
|
def on_ugc_doubleclick(self, widget, path, view):
|
|
self.on_ugcShowButton_clicked(widget)
|
|
|
|
def on_ugcShowButton_clicked(self, widget):
|
|
if self.Entropy.UGC == None: return
|
|
if self.repository == None: return
|
|
model, myiter = self.ugcView.get_selection().get_selected()
|
|
if myiter == None: return
|
|
obj = model.get_value( myiter, 0 )
|
|
if not isinstance(obj,dict): return
|
|
if obj.has_key('is_cat'): return
|
|
my = UGCInfoMenu(self.Entropy, obj, self.repository, self.pkginfo_ui.pkgInfo)
|
|
my.load()
|
|
|
|
def on_ugcAddButton_clicked(self, widget):
|
|
if self.Entropy.UGC == None: return
|
|
if self.repository == None: return
|
|
if self.pkgkey == None: return
|
|
my = UGCAddMenu(self.Entropy, self.pkgkey, self.repository, self.pkginfo_ui.pkgInfo, self.refresh_view_cb)
|
|
my.load()
|
|
|
|
def refresh_view_cb(self):
|
|
self.spawn_ugc_load(force = True)
|
|
|
|
def reset_ugc_data(self):
|
|
del self.ugc_data
|
|
self.ugc_data = None
|
|
|
|
def show_loading(self):
|
|
self.pkginfo_ui.ugcButtonBox.hide()
|
|
self.pkginfo_ui.loadUgcButton.set_sensitive(False)
|
|
self.pkginfo_ui.scrolledView.hide()
|
|
self.pkginfo_ui.ugcView.hide()
|
|
self.pkginfo_ui.ugcLoadingEvent.show_all()
|
|
self.pkginfo_ui.ugcLoadingEvent.add(self.loading_pix)
|
|
self.pkginfo_ui.ugcLoadingEvent.show_all()
|
|
self.pkginfo_ui.pkgInfo.queue_draw()
|
|
|
|
def hide_loading(self):
|
|
self.pkginfo_ui.ugcLoadingEvent.remove(self.loading_pix)
|
|
self.pkginfo_ui.scrolledView.show()
|
|
self.pkginfo_ui.ugcView.show()
|
|
self.pkginfo_ui.ugcLoadingEvent.hide()
|
|
self.pkginfo_ui.loadUgcButton.set_sensitive(True)
|
|
self.pkginfo_ui.ugcButtonBox.show_all()
|
|
|
|
def spawn_ugc_load(self, force = False):
|
|
|
|
if (self.ugc_data != None) and (not force):
|
|
return
|
|
if self.Entropy.UGC == None:
|
|
return
|
|
if not (self.pkgkey and self.repository):
|
|
return
|
|
|
|
self.show_loading()
|
|
|
|
docs_cache = None
|
|
if not force:
|
|
docs_cache = self.Entropy.UGC.UGCCache.get_alldocs_cache(self.pkgkey, self.repository)
|
|
if docs_cache == None:
|
|
docs_data, err_msg = self.Entropy.UGC.get_docs(self.repository, self.pkgkey)
|
|
if not isinstance(docs_data,tuple):
|
|
self.ugc_data = {}
|
|
else:
|
|
self.ugc_data = self.digest_remote_docs_data(docs_data)
|
|
self.ugc_status_message = err_msg
|
|
else:
|
|
self.ugc_data = self.digest_remote_docs_data(docs_cache)
|
|
|
|
self.refresh_ugc_view()
|
|
self.hide_loading()
|
|
|
|
def digest_remote_docs_data(self, data):
|
|
newdata = {}
|
|
for mydict in data:
|
|
if not mydict:
|
|
continue
|
|
if not newdata.has_key(mydict['iddoctype']):
|
|
newdata[mydict['iddoctype']] = []
|
|
newdata[mydict['iddoctype']].append(mydict)
|
|
return newdata
|
|
|
|
def refresh_ugc_view(self):
|
|
self.ugcModel.clear()
|
|
if self.ugc_data == None: return
|
|
self.populate_ugc_view()
|
|
#self.ugcView.expand_all()
|
|
|
|
def spawn_docs_fetch(self):
|
|
if self.ugc_data == None: return
|
|
if self.repository == None: return
|
|
|
|
for doc_type in self.ugc_data:
|
|
if int(doc_type) not in (etpConst['ugc_doctypes']['image'],):
|
|
continue
|
|
for mydoc in self.ugc_data[doc_type]:
|
|
if not mydoc.has_key('store_url'):
|
|
continue
|
|
if not mydoc['store_url']:
|
|
continue
|
|
store_path = self.Entropy.UGC.UGCCache.get_stored_document(mydoc['iddoc'], self.repository, mydoc['store_url'])
|
|
if store_path == None:
|
|
self.Entropy.UGC.UGCCache.store_document(mydoc['iddoc'], self.repository, mydoc['store_url'])
|
|
store_path = self.Entropy.UGC.UGCCache.get_stored_document(mydoc['iddoc'], self.repository, mydoc['store_url'])
|
|
if (store_path != None) and os.access(store_path,os.R_OK):
|
|
try:
|
|
preview_path = store_path+".preview"
|
|
if not os.path.isfile(preview_path) and (os.stat(store_path)[6] < 1024000):
|
|
# resize pix
|
|
img = gtk.Image()
|
|
img.set_from_file(store_path)
|
|
img_buf = img.get_pixbuf()
|
|
w, h = img_buf.get_width(),img_buf.get_height()
|
|
new_w = 64.0
|
|
new_h = new_w*h/w
|
|
img_buf = img_buf.scale_simple(int(new_w),int(new_h),gtk.gdk.INTERP_BILINEAR)
|
|
img_buf.save(preview_path, "png")
|
|
del img, img_buf
|
|
if os.path.isfile(preview_path):
|
|
mydoc['preview_path'] = preview_path
|
|
except:
|
|
continue
|
|
|
|
def populate_ugc_view(self):
|
|
|
|
if self.ugc_data == None: return
|
|
|
|
spawn_fetch = False
|
|
doc_types = self.ugc_data.keys()
|
|
doc_type_image_map = {
|
|
1: const.ugc_text_pix,
|
|
2: const.ugc_text_pix,
|
|
3: const.ugc_image_pix,
|
|
4: const.ugc_generic_pix,
|
|
5: const.ugc_video_pix,
|
|
}
|
|
doc_type_background_map = {
|
|
1:('#67AB6F','#599360'),
|
|
2:('#67AB6F','#599360'),
|
|
3:('#AB8158','#CA9968'),
|
|
4:('#BBD5B0','#99AE90'),
|
|
5:('#A5C0D5','#8EA5B7'),
|
|
}
|
|
doc_type_foreground_map = {
|
|
1:'#FFFFFF',
|
|
2:'#FFFFFF',
|
|
3:'#FFFFFF',
|
|
4:'#FFFFFF',
|
|
5:'#FFFFFF',
|
|
}
|
|
counter = 1
|
|
for doc_type in doc_types:
|
|
spawn_fetch = True
|
|
image_path = doc_type_image_map.get(int(doc_type))
|
|
cat_dict = {
|
|
'is_cat': True,
|
|
'image_path': image_path,
|
|
'parent_desc': "%s (%s)" % (etpConst['ugc_doctypes_description'].get(int(doc_type)),len(self.ugc_data[doc_type]),),
|
|
'foreground': doc_type_foreground_map.get(int(doc_type)),
|
|
'background': doc_type_background_map.get(int(doc_type)),
|
|
}
|
|
parent = self.ugcModel.append( None, (cat_dict,) )
|
|
docs_dates = {}
|
|
for mydoc in self.ugc_data[doc_type]:
|
|
ts = mydoc['ts']
|
|
if not docs_dates.has_key(ts):
|
|
docs_dates[ts] = []
|
|
docs_dates[ts].append(mydoc)
|
|
sorted_dates = sorted(docs_dates.keys())
|
|
for ts in sorted_dates:
|
|
for mydoc in docs_dates[ts]:
|
|
mydoc['image_path'] = const.ugc_pixmap_small
|
|
mydoc['foreground'] = doc_type_foreground_map.get(int(doc_type))
|
|
mydoc['background'] = doc_type_background_map.get(int(doc_type))
|
|
mydoc['counter'] = counter
|
|
self.ugcModel.append( parent, (mydoc,) )
|
|
counter += 1
|
|
|
|
if spawn_fetch:
|
|
gobject.idle_add(self.spawn_docs_fetch)
|
|
|
|
#search_col = 0
|
|
#self.view.set_search_column( search_col )
|
|
#self.view.set_search_equal_func(self.atom_search)
|
|
self.ugcView.set_property('headers-visible',True)
|
|
self.ugcView.set_property('enable-search',True)
|
|
self.ugcView.show_all()
|
|
|
|
def on_infoBook_switch_page(self, widget, page, page_num):
|
|
if (page_num == self.ugc_page_idx) and (not self.switched_to_ugc_page):
|
|
self.switched_to_ugc_page = True
|
|
self.on_loadUgcButton_clicked(widget, force = False)
|
|
|
|
def on_showChangeLogButton_clicked(self, widget):
|
|
if not self.changelog: return
|
|
mybuffer = gtk.TextBuffer()
|
|
mybuffer.set_text(self.changelog)
|
|
xml_clread = gtk.glade.XML( const.GLADE_FILE, 'textReadWindow',domain="entropy" )
|
|
read_dialog = xml_clread.get_widget( "textReadWindow" )
|
|
okReadButton = xml_clread.get_widget( "okReadButton" )
|
|
self.changelog_read_dialog = read_dialog
|
|
okReadButton.connect( 'clicked', self.destroy_changelog_read_dialog )
|
|
clView = xml_clread.get_widget( "readTextView" )
|
|
clView.set_buffer(mybuffer)
|
|
read_dialog.set_title(_("Package ChangeLog"))
|
|
read_dialog.show_all()
|
|
|
|
def destroy_changelog_read_dialog(self, widget):
|
|
self.changelog_read_dialog.destroy()
|
|
|
|
def on_star5_enter_notify_event(self, widget, event):
|
|
self.star_enter(widget, event, 5)
|
|
|
|
def on_star4_enter_notify_event(self, widget, event):
|
|
self.star_enter(widget, event, 4)
|
|
|
|
def on_star3_enter_notify_event(self, widget, event):
|
|
self.star_enter(widget, event, 3)
|
|
|
|
def on_star2_enter_notify_event(self, widget, event):
|
|
self.star_enter(widget, event, 2)
|
|
|
|
def on_star1_enter_notify_event(self, widget, event):
|
|
self.star_enter(widget, event, 1)
|
|
|
|
def on_starsEvent_leave_notify_event(self, widget, event):
|
|
normalCursor(self.pkginfo_ui.pkgInfo)
|
|
self.set_stars(self.vote)
|
|
|
|
def on_starsEvent_enter_notify_event(self, widget, event):
|
|
busyCursor(self.pkginfo_ui.pkgInfo, cur = gtk.gdk.Cursor(gtk.gdk.CROSSHAIR))
|
|
|
|
def on_starEvent5_button_release_event(self, widget, event):
|
|
self.vote_click(5)
|
|
|
|
def on_starEvent4_button_release_event(self, widget, event):
|
|
self.vote_click(4)
|
|
|
|
def on_starEvent3_button_release_event(self, widget, event):
|
|
self.vote_click(3)
|
|
|
|
def on_starEvent2_button_release_event(self, widget, event):
|
|
self.vote_click(2)
|
|
|
|
def on_starEvent1_button_release_event(self, widget, event):
|
|
self.vote_click(1)
|
|
|
|
def vote_click(self, vote):
|
|
if self.Entropy.UGC == None:
|
|
return
|
|
if not (self.repository and self.pkgkey):
|
|
return
|
|
if not self.Entropy.UGC.is_repository_eapi3_aware(self.repository):
|
|
return
|
|
status, err_msg = self.Entropy.UGC.add_vote(self.repository, self.pkgkey, vote)
|
|
if status:
|
|
self.set_stars_from_repository()
|
|
msg = "<small><span foreground='%s'>%s</span>: %s</small>" % (SpritzConf.color_good,_("Vote registered successfully"),vote,)
|
|
else:
|
|
msg = "<small><span foreground='%s'>%s</span>: %s</small>" % (SpritzConf.color_error,_("Error registering vote"),err_msg,)
|
|
|
|
self.pkginfo_ui.ugcMessageBox.set_markup(msg)
|
|
|
|
def star_enter(self, widget, event, number):
|
|
self.set_stars(number, hover = True)
|
|
|
|
def setupPkgPropertiesView(self):
|
|
|
|
# license view
|
|
self.licenseView = self.pkginfo_ui.licenseView
|
|
self.licenseModel = gtk.TreeStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "License name" ), cell, markup = 0 )
|
|
self.licenseView.append_column( column )
|
|
self.licenseView.set_model( self.licenseModel )
|
|
|
|
# sources view
|
|
self.sourcesView = self.pkginfo_ui.sourcesView
|
|
self.sourcesModel = gtk.TreeStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Sources" ), cell, markup = 0 )
|
|
self.sourcesView.append_column( column )
|
|
self.sourcesView.set_model( self.sourcesModel )
|
|
|
|
# mirrors view
|
|
self.mirrorsReferenceView = self.pkginfo_ui.mirrorsReferenceView
|
|
self.mirrorsReferenceModel = gtk.TreeStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Mirrors" ), cell, markup = 0 )
|
|
self.mirrorsReferenceView.append_column( column )
|
|
self.mirrorsReferenceView.set_model( self.mirrorsReferenceModel )
|
|
|
|
# keywords view
|
|
self.keywordsView = self.pkginfo_ui.keywordsView
|
|
self.keywordsModel = gtk.TreeStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Keywords" ), cell, markup = 0 )
|
|
self.keywordsView.append_column( column )
|
|
self.keywordsView.set_model( self.keywordsModel )
|
|
|
|
# useflags view
|
|
self.useflagsView = self.pkginfo_ui.useflagsView
|
|
self.useflagsModel = gtk.ListStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "USE flags" ), cell, markup = 0 )
|
|
self.useflagsView.append_column( column )
|
|
self.useflagsView.set_model( self.useflagsModel )
|
|
|
|
# eclasses view
|
|
self.eclassesView = self.pkginfo_ui.eclassesView
|
|
self.eclassesModel = gtk.ListStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Eclasses" ), cell, markup = 0 )
|
|
self.eclassesView.append_column( column )
|
|
self.eclassesView.set_model( self.eclassesModel )
|
|
|
|
# dependencies view
|
|
self.dependenciesView = self.pkginfo_ui.dependenciesView
|
|
self.dependenciesModel = gtk.TreeStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Dependencies" ), cell, markup = 0 )
|
|
self.dependenciesView.append_column( column )
|
|
self.dependenciesView.set_model( self.dependenciesModel )
|
|
|
|
# depends view
|
|
self.dependsView = self.pkginfo_ui.dependsView
|
|
self.dependsModel = gtk.TreeStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Depends" ), cell, markup = 0 )
|
|
self.dependsView.append_column( column )
|
|
self.dependsView.set_model( self.dependsModel )
|
|
|
|
# needed view
|
|
self.neededView = self.pkginfo_ui.neededView
|
|
self.neededModel = gtk.TreeStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Needed libraries" ), cell, markup = 0 )
|
|
self.neededView.append_column( column )
|
|
self.neededView.set_model( self.neededModel )
|
|
|
|
# protect view
|
|
self.configProtectView = self.pkginfo_ui.configProtectView1
|
|
self.configProtectModel = gtk.TreeStore( gobject.TYPE_STRING, gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Protected item" ), cell, markup = 0 )
|
|
self.configProtectView.append_column( column )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Type" ), cell, markup = 1 )
|
|
self.configProtectView.append_column( column )
|
|
self.configProtectView.set_model( self.configProtectModel )
|
|
|
|
# content view
|
|
self.contentView = self.pkginfo_ui.contentView
|
|
self.contentModel = gtk.TreeStore( gobject.TYPE_STRING, gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "File" ), cell, markup = 0 )
|
|
column.set_resizable( True )
|
|
self.contentView.append_column( column )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Type" ), cell, markup = 1 )
|
|
column.set_resizable( True )
|
|
self.contentView.append_column( column )
|
|
self.contentView.set_model( self.contentModel )
|
|
|
|
# ugc view
|
|
self.ugcView = self.pkginfo_ui.ugcView
|
|
self.ugcModel = gtk.TreeStore( gobject.TYPE_PYOBJECT )
|
|
|
|
# Setup image column
|
|
cell = gtk.CellRendererPixbuf()
|
|
cell.set_property('height', 78)
|
|
column = gtk.TreeViewColumn( _("Type"), cell ) # Document Type
|
|
column.set_cell_data_func( cell, self.ugc_pixbuf )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( 120 )
|
|
column.set_sort_column_id( -1 )
|
|
self.ugcView.append_column( column )
|
|
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Content" ), cell )
|
|
column.set_resizable( True )
|
|
column.set_cell_data_func( cell, self.ugc_content )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( 350 )
|
|
column.set_expand(True)
|
|
column.set_sort_column_id( -1 )
|
|
self.ugcView.append_column( column )
|
|
self.ugcView.set_model( self.ugcModel )
|
|
|
|
self.ugcView.set_property('headers-visible',True)
|
|
self.ugcView.set_property('enable-search',True)
|
|
|
|
|
|
def set_stars(self, count, hover = False):
|
|
pix_path = self.star_normal_pixmap
|
|
if hover: pix_path = self.star_selected_pixmap
|
|
pix_path_empty = self.star_empty_pixmap
|
|
|
|
widgets = [
|
|
self.pkginfo_ui.vote1,
|
|
self.pkginfo_ui.vote2,
|
|
self.pkginfo_ui.vote3,
|
|
self.pkginfo_ui.vote4,
|
|
self.pkginfo_ui.vote5
|
|
]
|
|
if count > len(widgets):
|
|
count = len(widgets)
|
|
if count < 0: count = 0
|
|
idx = -1
|
|
while count > -1:
|
|
w = widgets[count-1]
|
|
w.set_from_file(pix_path)
|
|
w.show()
|
|
count -= 1
|
|
idx += 1
|
|
mycount = len(widgets) - idx
|
|
while mycount:
|
|
w = widgets[idx]
|
|
w.set_from_file(pix_path_empty)
|
|
w.show()
|
|
mycount -= 1
|
|
idx += 1
|
|
|
|
def set_stars_from_repository(self):
|
|
if not (self.repository and self.pkgkey):
|
|
return
|
|
vote = self.Entropy.UGC.UGCCache.get_package_vote(self.repository, self.pkgkey)
|
|
if isinstance(vote,float):
|
|
self.set_stars(int(vote))
|
|
self.vote = int(vote)
|
|
|
|
def load(self, remote = False):
|
|
|
|
pkg = self.pkg
|
|
dbconn = self.pkg.dbconn
|
|
avail = False
|
|
if dbconn:
|
|
avail = dbconn.isIDPackageAvailable(pkg.matched_atom[0])
|
|
if not avail:
|
|
return
|
|
from_repo = True
|
|
if isinstance(pkg.matched_atom[1],int): from_repo = False
|
|
if from_repo and (pkg.matched_atom[1] not in self.Entropy.validRepositories) and (not remote):
|
|
return
|
|
|
|
# set package image
|
|
pkgatom = pkg.name
|
|
self.vote = int(pkg.vote)
|
|
self.repository = pkg.repoid
|
|
self.pkgkey = self.entropyTools.dep_getkey(pkgatom)
|
|
self.set_stars_from_repository()
|
|
self.pkginfo_ui.pkgImage.set_from_file(self.pkg_pixmap)
|
|
self.pkginfo_ui.ugcSmallIcon.set_from_file(self.ugc_small_pixmap)
|
|
self.pkginfo_ui.ugcIcon.set_from_file(self.ugc_pixmap)
|
|
self.pkginfo_ui.refreshImage.set_from_file(self.refresh_pixmap)
|
|
|
|
self.pkginfo_ui.labelAtom.set_markup("<b>%s</b>" % (cleanMarkupString(pkgatom),))
|
|
self.pkginfo_ui.labelDescription.set_markup("<small>%s</small>" % (pkg.description,))
|
|
self.pkginfo_ui.ugcDescriptionLabel.set_markup("<small>%s\n%s</small>" % (
|
|
_("Share your opinion, your documents, your screenshots!"),
|
|
_("Be part of our Community!")
|
|
)
|
|
)
|
|
self.pkginfo_ui.ugcDownloaded.set_markup(
|
|
"<small>%s: <b>%s</b></small>" % (_("Number of downloads"), pkg.downloads,)
|
|
)
|
|
|
|
bold_items = [ self.pkginfo_ui.locationLabel,
|
|
self.pkginfo_ui.homepageLabel,
|
|
self.pkginfo_ui.versionLabel,
|
|
self.pkginfo_ui.slotLabel,
|
|
self.pkginfo_ui.tagLabel,
|
|
self.pkginfo_ui.revisionLabel,
|
|
self.pkginfo_ui.branchLabel,
|
|
self.pkginfo_ui.eapiLabel,
|
|
self.pkginfo_ui.downloadLabel,
|
|
self.pkginfo_ui.checksumLabel,
|
|
self.pkginfo_ui.downSizeLabel,
|
|
self.pkginfo_ui.installSizeLabel,
|
|
self.pkginfo_ui.creationDateLabel,
|
|
self.pkginfo_ui.chostLabel,
|
|
self.pkginfo_ui.cflagsLabel,
|
|
self.pkginfo_ui.cxxflagsLabel,
|
|
self.pkginfo_ui.maskedLabel,
|
|
self.pkginfo_ui.messagesLabel,
|
|
self.pkginfo_ui.triggerLabel,
|
|
self.pkginfo_ui.configProtectLabel,
|
|
self.pkginfo_ui.ugcTitleLabel,
|
|
self.pkginfo_ui.changeLogLabel
|
|
]
|
|
for item in bold_items:
|
|
t = item.get_text()
|
|
item.set_markup("<b>%s</b>" % (t,))
|
|
|
|
repo = pkg.matched_atom[1]
|
|
avail_repos = self.Entropy.SystemSettings['repositories']['available']
|
|
if repo == 0:
|
|
self.pkginfo_ui.location.set_markup("%s" % (_("From your Operating System"),))
|
|
else:
|
|
if remote:
|
|
self.pkginfo_ui.location.set_markup("%s: %s" % (_("Remotely"),pkg.repoid,))
|
|
else:
|
|
self.pkginfo_ui.location.set_markup("%s" % (cleanMarkupString(avail_repos[repo]['description']),))
|
|
|
|
self.pkginfo_ui.version.set_markup( "%s" % (cleanMarkupString(pkg.onlyver),) )
|
|
tag = pkg.tag
|
|
if not tag: tag = "None"
|
|
self.pkginfo_ui.tag.set_markup( "%s" % (tag,) )
|
|
self.pkginfo_ui.slot.set_markup( "%s" % (pkg.slot,) )
|
|
self.pkginfo_ui.revision.set_markup( "%s" % (pkg.revision,) )
|
|
self.pkginfo_ui.branch.set_markup( "%s" % (pkg.release,) )
|
|
self.pkginfo_ui.eapi.set_markup( "%s" % (pkg.api,) )
|
|
self.pkginfo_ui.homepage.set_markup( "%s" % (cleanMarkupString(pkg.homepage),) )
|
|
|
|
# license view
|
|
self.licenseModel.clear()
|
|
self.licenseView.set_model( self.licenseModel )
|
|
licenses = pkg.lic
|
|
licenses = licenses.split()
|
|
for x in licenses:
|
|
self.licenseModel.append(None,[x])
|
|
|
|
self.pkginfo_ui.download.set_markup( "%s" % (pkg.binurl,) )
|
|
self.pkginfo_ui.checksum.set_markup( "%s" % (pkg.digest,) )
|
|
self.pkginfo_ui.pkgsize.set_markup( "%s" % (pkg.sizeFmt,) )
|
|
self.pkginfo_ui.instsize.set_markup( "%s" % (pkg.disksizeFmt,) )
|
|
self.pkginfo_ui.creationdate.set_markup( "%s" % (pkg.epochFmt,) )
|
|
# compile flags
|
|
chost, cflags, cxxflags = pkg.compileflags
|
|
self.pkginfo_ui.cflags.set_markup( "%s" % (cflags,) )
|
|
self.pkginfo_ui.cxxflags.set_markup( "%s" % (cxxflags,) )
|
|
self.pkginfo_ui.chost.set_markup( "%s" % (chost,) )
|
|
# messages
|
|
messages = pkg.messages
|
|
mbuffer = gtk.TextBuffer()
|
|
mbuffer.set_text('\n'.join(messages))
|
|
self.pkginfo_ui.messagesTextView.set_buffer(mbuffer)
|
|
# masked ?
|
|
masked = 'False'
|
|
idpackage_masked, idmasking_reason = dbconn.idpackageValidator(pkg.matched_atom[0])
|
|
if idpackage_masked == -1:
|
|
masked = 'True, %s' % (self.Entropy.SystemSettings['pkg_masking_reasons'][idmasking_reason],)
|
|
self.pkginfo_ui.masked.set_markup( "%s" % (masked,) )
|
|
|
|
# package changelog
|
|
self.changelog = pkg.changelog
|
|
if not isinstance(self.changelog,basestring):
|
|
self.pkginfo_ui.showChangeLogButtonAlign.hide()
|
|
self.pkginfo_ui.changeLogLabel.hide()
|
|
|
|
# sources view
|
|
self.sourcesModel.clear()
|
|
self.sourcesView.set_model( self.sourcesModel )
|
|
mirrors = set()
|
|
sources = pkg.sources
|
|
for x in sources:
|
|
if x.startswith("mirror://"):
|
|
mirrors.add(x.split("/")[2])
|
|
self.sourcesModel.append(None,[x])
|
|
|
|
# mirrors view
|
|
self.mirrorsReferenceModel.clear()
|
|
self.mirrorsReferenceView.set_model(self.mirrorsReferenceModel)
|
|
for mirror in mirrors:
|
|
mirrorinfo = dbconn.retrieveMirrorInfo(mirror)
|
|
if mirrorinfo:
|
|
# add parent
|
|
parent = self.mirrorsReferenceModel.append(None,[mirror])
|
|
for info in mirrorinfo:
|
|
self.mirrorsReferenceModel.append(parent,[info])
|
|
|
|
# keywords view
|
|
self.keywordsModel.clear()
|
|
self.keywordsView.set_model( self.keywordsModel )
|
|
for x in pkg.keywords:
|
|
self.keywordsModel.append(None,[x])
|
|
|
|
# useflags view
|
|
self.useflagsModel.clear()
|
|
self.useflagsView.set_model( self.useflagsModel )
|
|
for x in pkg.useflags:
|
|
self.useflagsModel.append([cleanMarkupString(x)])
|
|
|
|
# eclasses view
|
|
self.eclassesModel.clear()
|
|
self.eclassesView.set_model( self.eclassesModel )
|
|
for x in pkg.eclasses:
|
|
self.eclassesModel.append([cleanMarkupString(x)])
|
|
|
|
# dependencies view
|
|
self.dependenciesModel.clear()
|
|
self.dependenciesView.set_model( self.dependenciesModel )
|
|
deps = pkg.dependencies
|
|
conflicts = pkg.conflicts
|
|
for x in deps:
|
|
self.dependenciesModel.append(None,[cleanMarkupString(x)])
|
|
for x in conflicts:
|
|
self.dependenciesModel.append(None,[cleanMarkupString("!"+x)])
|
|
|
|
# depends view
|
|
self.dependsModel.clear()
|
|
self.dependsView.set_model( self.dependsModel )
|
|
depends = pkg.dependsFmt
|
|
for x in depends:
|
|
self.dependsModel.append(None,[cleanMarkupString(x)])
|
|
|
|
# needed view
|
|
self.neededModel.clear()
|
|
self.neededView.set_model( self.neededModel )
|
|
neededs = pkg.needed
|
|
for x in neededs:
|
|
self.neededModel.append(None,[cleanMarkupString(x)])
|
|
|
|
# content view
|
|
self.contentModel.clear()
|
|
self.contentView.set_model( self.contentModel )
|
|
|
|
# trigger
|
|
trigger = pkg.trigger
|
|
mtrigger = gtk.TextBuffer()
|
|
mtrigger.set_text(trigger)
|
|
self.pkginfo_ui.triggerTextView.set_buffer(mtrigger)
|
|
|
|
# CONFIG_PROTECT Stuff
|
|
protect = pkg.protect
|
|
protect_mask = pkg.protect_mask
|
|
for item in protect.split():
|
|
self.configProtectModel.append(None,[item,'protect'])
|
|
for item in protect_mask.split():
|
|
self.configProtectModel.append(None,[item,'mask'])
|
|
|
|
self.pkginfo_ui.pkgInfo.show()
|
|
|
|
class SecurityAdvisoryMenu(MenuSkel):
|
|
|
|
def __init__(self, window):
|
|
|
|
self.window = window
|
|
self.advinfo_ui = UI( const.GLADE_FILE , 'advInfo', 'entropy' )
|
|
self.advinfo_ui.signal_autoconnect(self._getAllMethods())
|
|
self.advinfo_ui.advInfo.set_transient_for(self.window)
|
|
self.advinfo_ui.advInfo.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
self.setupAdvPropertiesView()
|
|
|
|
def setupAdvPropertiesView(self):
|
|
|
|
# affected view
|
|
self.affectedView = self.advinfo_ui.affectedView
|
|
self.affectedModel = gtk.TreeStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Package" ), cell, markup = 0 )
|
|
self.affectedView.append_column( column )
|
|
self.affectedView.set_model( self.affectedModel )
|
|
|
|
# bugs view
|
|
self.bugsView = self.advinfo_ui.bugsView
|
|
self.bugsModel = gtk.ListStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Bug" ), cell, markup = 0 )
|
|
self.bugsView.append_column( column )
|
|
self.bugsView.set_model( self.bugsModel )
|
|
|
|
# references view
|
|
self.referencesView = self.advinfo_ui.referencesView
|
|
self.referencesModel = gtk.ListStore( gobject.TYPE_STRING )
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( _( "Reference" ), cell, markup = 0 )
|
|
self.referencesView.append_column( column )
|
|
self.referencesView.set_model( self.referencesModel )
|
|
|
|
def load(self, item):
|
|
|
|
key, affected, data = item
|
|
|
|
adv_pixmap = const.PIXMAPS_PATH+'/button-glsa.png'
|
|
self.advinfo_ui.advImage.set_from_file(adv_pixmap)
|
|
|
|
glsa_idtext = "<b>GLSA</b>#<span foreground='%s' weight='bold'>%s</span>" % (SpritzConf.color_title,key,)
|
|
self.advinfo_ui.labelIdentifier.set_markup(glsa_idtext)
|
|
|
|
bold_items = [
|
|
self.advinfo_ui.descriptionLabel,
|
|
self.advinfo_ui.backgroundLabel,
|
|
self.advinfo_ui.impactLabel,
|
|
self.advinfo_ui.affectedLabel,
|
|
self.advinfo_ui.bugsLabel,
|
|
self.advinfo_ui.referencesLabel,
|
|
self.advinfo_ui.revisedLabel,
|
|
self.advinfo_ui.announcedLabel,
|
|
self.advinfo_ui.synopsisLabel,
|
|
self.advinfo_ui.workaroundLabel,
|
|
self.advinfo_ui.resolutionLabel
|
|
]
|
|
for item in bold_items:
|
|
t = item.get_text()
|
|
item.set_markup("<b>%s</b>" % (t,))
|
|
|
|
# packages
|
|
if data.has_key('packages'):
|
|
packages_data = data['packages']
|
|
else:
|
|
packages_data = data['affected']
|
|
glsa_packages = '\n'.join([x for x in packages_data])
|
|
glsa_packages = "<span weight='bold' size='large'>%s</span>" % (glsa_packages,)
|
|
self.advinfo_ui.labelPackages.set_markup(glsa_packages)
|
|
|
|
# title
|
|
myurl = ''
|
|
if data.has_key('url'):
|
|
myurl = data['url']
|
|
self.advinfo_ui.labelTitle.set_markup( "<small>%s\n<span foreground='%s'>%s</span></small>" % (data['title'],SpritzConf.color_title2,myurl,))
|
|
|
|
# description
|
|
desc_text = ' '.join([x.strip() for x in data['description'].split("\n")]).strip()
|
|
if data.has_key('description_items'):
|
|
if data['description_items']:
|
|
for item in data['description_items']:
|
|
desc_text += '\n\t%s %s' % ("<span foreground='%s'>(*)</span>" % (SpritzConf.color_title,),item,)
|
|
desc_text = desc_text.replace('!;\\n','')
|
|
b = gtk.TextBuffer()
|
|
b.set_text(desc_text)
|
|
self.advinfo_ui.descriptionTextLabel.set_buffer(b)
|
|
|
|
# background
|
|
back_text = ' '.join([x.strip() for x in data['background'].split("\n")]).strip()
|
|
back_text = back_text.replace('!;\\n','')
|
|
b = gtk.TextBuffer()
|
|
b.set_text(back_text)
|
|
self.advinfo_ui.backgroundTextLabel.set_buffer(b)
|
|
|
|
# impact
|
|
impact_text = ' '.join([x.strip() for x in data['impact'].split("\n")]).strip()
|
|
impact_text = impact_text.replace('!;\\n','')
|
|
b = gtk.TextBuffer()
|
|
b.set_text(back_text)
|
|
self.advinfo_ui.impactTextLabel.set_buffer(b)
|
|
|
|
t = self.advinfo_ui.impactLabel.get_text()
|
|
t = "<b>%s</b>" % (t,)
|
|
t += " [<span foreground='darkgreen'>%s</span>:<span foreground='%s'>%s</span>|<span foreground='%s'>%s</span>:<span foreground='%s'>%s</span>]" % (
|
|
_("impact"),
|
|
SpritzConf.color_title2,
|
|
data['impacttype'],
|
|
SpritzConf.color_subdesc,
|
|
_("access"),
|
|
SpritzConf.color_pkgsubtitle,
|
|
data['access'],
|
|
)
|
|
self.advinfo_ui.impactLabel.set_markup(t)
|
|
|
|
# affected packages
|
|
self.affectedModel.clear()
|
|
self.affectedView.set_model( self.affectedModel )
|
|
for key in packages_data:
|
|
affected_data = packages_data[key][0]
|
|
vul_atoms = affected_data['vul_atoms']
|
|
unaff_atoms = affected_data['unaff_atoms']
|
|
parent = self.affectedModel.append(None,[key])
|
|
if vul_atoms:
|
|
myparent = self.affectedModel.append(parent,[_('Vulnerables')])
|
|
for atom in vul_atoms:
|
|
self.affectedModel.append(myparent,[cleanMarkupString(atom)])
|
|
if unaff_atoms:
|
|
myparent = self.affectedModel.append(parent,[_('Unaffected')])
|
|
for atom in unaff_atoms:
|
|
self.affectedModel.append(myparent,[cleanMarkupString(atom)])
|
|
|
|
# bugs
|
|
self.bugsModel.clear()
|
|
self.bugsView.set_model( self.bugsModel )
|
|
for bug in data['bugs']:
|
|
self.bugsModel.append([cleanMarkupString(bug)])
|
|
|
|
self.referencesModel.clear()
|
|
self.referencesView.set_model( self.referencesModel )
|
|
for reference in data['references']:
|
|
self.referencesModel.append([cleanMarkupString(reference)])
|
|
|
|
# announcedTextLabel
|
|
self.advinfo_ui.announcedTextLabel.set_markup(data['announced'])
|
|
# revisedTextLabel
|
|
self.advinfo_ui.revisedTextLabel.set_markup(data['revised'])
|
|
|
|
# synopsis
|
|
synopsis_text = ' '.join([x.strip() for x in data['synopsis'].split("\n")]).strip()
|
|
b = gtk.TextBuffer()
|
|
b.set_text(synopsis_text)
|
|
self.advinfo_ui.synopsisTextLabel.set_buffer(b)
|
|
|
|
# workaround
|
|
workaround_text = ' '.join([x.strip() for x in data['workaround'].split("\n")]).strip()
|
|
workaround_text = workaround_text.replace('!;\\n','')
|
|
b = gtk.TextBuffer()
|
|
b.set_text(workaround_text)
|
|
self.advinfo_ui.workaroundTextLabel.set_buffer(b)
|
|
|
|
# resolution
|
|
|
|
if isinstance(data['resolution'],list):
|
|
resolution_text = []
|
|
for resolution in data['resolution']:
|
|
resolution_text.append(' '.join([x.strip() for x in resolution.split("\n")]).strip())
|
|
resolution_text = '\n'.join(resolution_text)
|
|
else:
|
|
resolution_text = data['resolution'].replace('!;\\n','')
|
|
resolution_text = '\n'.join([x for x in resolution_text.strip().split("\n")])
|
|
|
|
b = gtk.TextBuffer()
|
|
b.set_text(resolution_text)
|
|
self.advinfo_ui.resolutionTextLabel.set_buffer(b)
|
|
|
|
self.advinfo_ui.advInfo.show()
|
|
|
|
class UGCInfoMenu(MenuSkel):
|
|
|
|
import entropy.tools as entropyTools
|
|
def __init__(self, Entropy, obj, repository, window):
|
|
|
|
import subprocess
|
|
self.subprocess = subprocess
|
|
self.repository = repository
|
|
self.window = window
|
|
self.Entropy = Entropy
|
|
self.ugc_data = obj.copy()
|
|
self.ugcinfo_ui = UI( const.GLADE_FILE, 'ugcInfo', 'entropy' )
|
|
self.ugcinfo_ui.signal_autoconnect(self._getAllMethods())
|
|
self.ugcinfo_ui.ugcInfo.set_transient_for(self.window)
|
|
self.ugcinfo_ui.ugcInfo.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
|
|
def on_closeInfo_clicked(self, widget, path = None):
|
|
self.ugcinfo_ui.ugcInfo.hide()
|
|
return True
|
|
|
|
def on_getButton_clicked(self, widget):
|
|
if self.ugc_data['store_url'] != None:
|
|
self.subprocess.call(['xdg-open',self.ugc_data['store_url']])
|
|
|
|
def load(self):
|
|
|
|
pix_path = self.ugc_data['image_path']
|
|
if self.ugc_data.has_key('preview_path'):
|
|
if os.path.isfile(self.ugc_data['preview_path']) and os.access(self.ugc_data['preview_path'],os.R_OK):
|
|
pix_path = self.ugc_data['preview_path']
|
|
self.ugcinfo_ui.ugcImage.set_from_file(pix_path)
|
|
self.ugcinfo_ui.labelKey.set_markup("<b>%s</b>" % (self.ugc_data['pkgkey'],))
|
|
doc_type_desc = etpConst['ugc_doctypes_description_singular'].get(int(self.ugc_data['iddoctype']))
|
|
self.ugcinfo_ui.labelTypedesc.set_markup("<small>[<b>%s</b>:%d] <i>%s</i></small>" % (
|
|
_("Id"),
|
|
int(self.ugc_data['iddoc']),
|
|
doc_type_desc,
|
|
)
|
|
)
|
|
self.ugcinfo_ui.titleContent.set_markup("%s" % (unicode(self.ugc_data['title'],'raw_unicode_escape'),))
|
|
self.ugcinfo_ui.descriptionContent.set_markup("%s" % (unicode(self.ugc_data['description'],'raw_unicode_escape'),))
|
|
self.ugcinfo_ui.authorContent.set_markup("<i>%s</i>" % (unicode(self.ugc_data['username'],'raw_unicode_escape'),))
|
|
self.ugcinfo_ui.dateContent.set_markup("<u>%s</u>" % (self.ugc_data['ts'],))
|
|
self.ugcinfo_ui.keywordsContent.set_markup("%s" % (unicode(', '.join(self.ugc_data['keywords']),'raw_unicode_escape'),))
|
|
self.ugcinfo_ui.sizeContent.set_markup("%s" % (self.entropyTools.bytes_into_human(self.ugc_data['size']),))
|
|
|
|
bold_items = [
|
|
self.ugcinfo_ui.titleLabel,
|
|
self.ugcinfo_ui.descLabel,
|
|
self.ugcinfo_ui.authorLabel,
|
|
self.ugcinfo_ui.dateLabel,
|
|
self.ugcinfo_ui.keywordsLabel,
|
|
self.ugcinfo_ui.sizeLabel
|
|
]
|
|
for item in bold_items:
|
|
t = item.get_text()
|
|
item.set_markup("<b>%s</b>" % (t,))
|
|
|
|
small_items = bold_items
|
|
small_items += [
|
|
self.ugcinfo_ui.titleContent,
|
|
self.ugcinfo_ui.descriptionContent,
|
|
self.ugcinfo_ui.authorContent,
|
|
self.ugcinfo_ui.dateContent,
|
|
self.ugcinfo_ui.keywordsContent,
|
|
self.ugcinfo_ui.sizeContent
|
|
]
|
|
for item in small_items:
|
|
t = item.get_label()
|
|
item.set_markup("<small>%s</small>" % (t,))
|
|
|
|
if self.ugc_data['iddoctype'] in (etpConst['ugc_doctypes']['comments'], etpConst['ugc_doctypes']['bbcode_doc'],):
|
|
self.ugcinfo_ui.ugcTable.remove(self.ugcinfo_ui.descLabel)
|
|
self.ugcinfo_ui.ugcTable.remove(self.ugcinfo_ui.descriptionContent)
|
|
self.ugcinfo_ui.buttonBox.hide()
|
|
mybuf = gtk.TextBuffer()
|
|
mybuf.set_text(unicode(self.ugc_data['ddata'].tostring(),'raw_unicode_escape'))
|
|
self.ugcinfo_ui.textContent.set_buffer(mybuf)
|
|
else:
|
|
self.ugcinfo_ui.textFrame.hide()
|
|
|
|
self.ugcinfo_ui.ugcInfo.show()
|
|
|
|
|
|
class UGCAddMenu(MenuSkel):
|
|
|
|
import entropy.tools as entropyTools
|
|
def __init__(self, Entropy, pkgkey, repository, window, refresh_cb):
|
|
|
|
self.loading_pix = gtk.image_new_from_file(const.loading_pix)
|
|
self.repository = repository
|
|
self.pix_path = const.ugc_pixmap
|
|
self.pkgkey = pkgkey
|
|
self.window = window
|
|
self.Entropy = Entropy
|
|
self.ugcadd_ui = UI( const.GLADE_FILE, 'ugcAdd', 'entropy' )
|
|
self.ugcadd_ui.signal_autoconnect(self._getAllMethods())
|
|
self.ugcadd_ui.ugcAdd.set_transient_for(self.window)
|
|
self.ugcadd_ui.ugcAdd.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
self.store = None
|
|
self.refresh_cb = refresh_cb
|
|
self.text_types = (etpConst['ugc_doctypes']['comments'],etpConst['ugc_doctypes']['bbcode_doc'],)
|
|
self.file_selected = None
|
|
|
|
def on_closeAdd_clicked(self, widget, path = None):
|
|
self.ugcadd_ui.ugcAdd.hide()
|
|
return True
|
|
|
|
def on_ugcAddTypeCombo_changed(self, widget):
|
|
myiter = widget.get_active_iter()
|
|
idx = self.store.get_value( myiter, 0 )
|
|
if idx in self.text_types:
|
|
txt = "%s %s" % (_("Write your"),etpConst['ugc_doctypes_description_singular'][idx],) # write your <document type>
|
|
self.setup_text_insert()
|
|
else:
|
|
txt = "%s %s" % (_("Select your"),etpConst['ugc_doctypes_description_singular'][idx],) # select your <document type>
|
|
self.setup_file_insert(txt)
|
|
|
|
def on_ugcAddFileChooser_file_set(self, widget):
|
|
self.file_selected = widget.get_filename()
|
|
|
|
def on_submitButton_clicked(self, widget):
|
|
dialog_title = _("Submit issue")
|
|
myiter = self.ugcadd_ui.ugcAddTypeCombo.get_active_iter()
|
|
doc_type = self.store.get_value( myiter, 0 )
|
|
title = self.ugcadd_ui.ugcAddTitleEntry.get_text()
|
|
description = self.ugcadd_ui.ugcAddDescEntry.get_text()
|
|
keywords_text = self.ugcadd_ui.ugcAddKeywordsEntry.get_text()
|
|
doc_path = None
|
|
if doc_type in self.text_types:
|
|
mybuf = self.ugcadd_ui.ugcAddTextView.get_buffer()
|
|
start_iter = mybuf.get_start_iter()
|
|
end_iter = mybuf.get_end_iter()
|
|
description = mybuf.get_text(start_iter, end_iter)
|
|
if not description:
|
|
okDialog(self.window, _("Empty Document"), title = dialog_title)
|
|
return False
|
|
else:
|
|
if not description:
|
|
okDialog(self.window, _("Invalid Description"), title = dialog_title)
|
|
return False
|
|
doc_path = self.file_selected
|
|
|
|
# checking
|
|
if doc_type == None:
|
|
okDialog(self.window, _("Invalid Document Type"), title = dialog_title)
|
|
return False
|
|
if not title:
|
|
okDialog(self.window, _("Invalid Title"), title = dialog_title)
|
|
return False
|
|
|
|
# confirm ?
|
|
rc = self.Entropy.askQuestion(_("Do you confirm your submission?"))
|
|
if rc != "Yes":
|
|
return False
|
|
|
|
self.show_loading()
|
|
|
|
old_show_progress = self.Entropy.UGC.show_progress
|
|
self.Entropy.UGC.show_progress = True
|
|
bck_updateProgress = self.Entropy.updateProgress
|
|
self.Entropy.updateProgress = self.do_label_update_progress
|
|
try:
|
|
t = ParallelTask(self.do_send_document_autosense, doc_type, doc_path, title, description, keywords_text)
|
|
t.start()
|
|
while 1:
|
|
if not t.isAlive(): break
|
|
while gtk.events_pending():
|
|
gtk.main_iteration()
|
|
time.sleep(0.06)
|
|
rslt, data = t.get_rc()
|
|
finally:
|
|
self.Entropy.UGC.show_progress = old_show_progress
|
|
self.Entropy.updateProgress = bck_updateProgress
|
|
|
|
|
|
self.hide_loading()
|
|
if not rslt:
|
|
txt = "<small><span foreground='%s'><b>%s</b></span>: %s | %s</small>" % (SpritzConf.color_error,_("UGC Error"),rslt,data,)
|
|
self.ugcadd_ui.ugcAddStatusLabel.set_markup(txt)
|
|
return False
|
|
else:
|
|
okDialog(self.window, _("Document added successfully. Thank you"), title = _("Success!"))
|
|
self.on_closeAdd_clicked(None,None)
|
|
self.refresh_cb()
|
|
return True
|
|
|
|
def do_label_update_progress(self, *myargs, **mykwargs):
|
|
|
|
count = mykwargs.get("count")
|
|
percent = mykwargs.get("percent")
|
|
text = myargs[0].encode('utf-8')
|
|
|
|
count_str = ""
|
|
if count:
|
|
if len(count) > 1:
|
|
if percent:
|
|
count_str = " ("+str(round((float(count[0])/count[1])*100,1))+"%) "
|
|
else:
|
|
count_str = " (%s/%s) " % (str(count[0]),str(count[1]),)
|
|
|
|
txt = count_str+text
|
|
gtk.gdk.threads_enter()
|
|
self.ugcadd_ui.ugcAddStatusLabel.set_markup(cleanMarkupString(txt))
|
|
gtk.gdk.threads_leave()
|
|
|
|
def do_send_document_autosense(self, doc_type, doc_path, title, description, keywords_text):
|
|
try:
|
|
rslt, data = self.Entropy.UGC.send_document_autosense(
|
|
self.repository,
|
|
str(self.pkgkey),
|
|
doc_type,
|
|
doc_path,
|
|
title,
|
|
description,
|
|
keywords_text
|
|
)
|
|
except Exception, e:
|
|
rslt = False
|
|
data = e
|
|
return rslt, data
|
|
|
|
def show_loading(self):
|
|
self.ugcadd_ui.ugcAddButtonBox.hide()
|
|
self.ugcadd_ui.closeAdd.set_sensitive(False)
|
|
self.ugcadd_ui.ugcAddLoadingEvent.show_all()
|
|
self.ugcadd_ui.ugcAddLoadingEvent.add(self.loading_pix)
|
|
self.ugcadd_ui.ugcAddLoadingEvent.show_all()
|
|
self.ugcadd_ui.ugcAdd.queue_draw()
|
|
|
|
def hide_loading(self):
|
|
self.ugcadd_ui.ugcAddButtonBox.show()
|
|
self.ugcadd_ui.closeAdd.set_sensitive(True)
|
|
self.ugcadd_ui.ugcAddLoadingEvent.remove(self.loading_pix)
|
|
self.ugcadd_ui.ugcAddLoadingEvent.hide()
|
|
self.ugcadd_ui.ugcAdd.queue_draw()
|
|
|
|
def setup_text_insert(self, txt = _("Write your document")):
|
|
self.ugcadd_ui.ugcAddFileChooser.hide()
|
|
self.ugcadd_ui.ugcAddFrame.show()
|
|
self.ugcadd_ui.ugcAddDescLabel.hide()
|
|
self.ugcadd_ui.ugcAddDescEntry.hide()
|
|
self.ugcadd_ui.ugcAddTitleEntry.set_max_length(255)
|
|
self.ugcadd_ui.ugcAddInsertLabel.set_markup(txt)
|
|
|
|
def setup_file_insert(self, txt = _("Select your file")):
|
|
self.ugcadd_ui.ugcAddFileChooser.show()
|
|
self.ugcadd_ui.ugcAddFrame.hide()
|
|
self.ugcadd_ui.ugcAddDescLabel.show()
|
|
self.ugcadd_ui.ugcAddDescEntry.show()
|
|
self.ugcadd_ui.ugcAddTitleEntry.set_max_length(60)
|
|
self.ugcadd_ui.ugcAddInsertLabel.set_markup(txt)
|
|
|
|
def load(self):
|
|
|
|
self.ugcadd_ui.ugcAddImage.set_from_file(self.pix_path)
|
|
self.ugcadd_ui.labelAddKey.set_markup("<b>%s</b>" % (self.pkgkey,))
|
|
self.ugcadd_ui.labelAddRepo.set_markup("<small>%s: <b>%s</b></small>" % (_("On repository"),self.repository,))
|
|
|
|
# add types to combo
|
|
doc_types_list = sorted(etpConst['ugc_doctypes_description_singular'].keys())
|
|
self.store = gtk.ListStore( gobject.TYPE_INT, gobject.TYPE_STRING )
|
|
self.ugcadd_ui.ugcAddTypeCombo.set_model(self.store)
|
|
cell = gtk.CellRendererText()
|
|
self.ugcadd_ui.ugcAddTypeCombo.pack_start(cell, True)
|
|
self.ugcadd_ui.ugcAddTypeCombo.add_attribute(cell, 'text', 1)
|
|
for idx in doc_types_list:
|
|
# disable bbcode for now
|
|
if idx == etpConst['ugc_doctypes']['bbcode_doc']:
|
|
continue
|
|
self.store.append( (idx, etpConst['ugc_doctypes_description_singular'][idx],) )
|
|
self.ugcadd_ui.ugcAddTypeCombo.set_active(0)
|
|
|
|
# hide file chooser
|
|
self.setup_text_insert()
|
|
|
|
bold_items = [
|
|
self.ugcadd_ui.ugcAddTitleLabel,
|
|
self.ugcadd_ui.ugcAddDescLabel,
|
|
self.ugcadd_ui.ugcAddTypeLabel,
|
|
self.ugcadd_ui.ugcAddKeywordsLabel
|
|
]
|
|
for item in bold_items:
|
|
t = item.get_text()
|
|
item.set_markup("<b>%s</b>" % (t,))
|
|
|
|
self.ugcadd_ui.ugcAdd.show()
|
|
|
|
|
|
class MaskedPackagesDialog(MenuSkel):
|
|
|
|
|
|
def __init__( self, Entropy, etpbase, parent, pkgs, top_text = None, sub_text = None ):
|
|
|
|
self.Entropy = Entropy
|
|
self.etpbase = etpbase
|
|
self.parent = parent
|
|
self.docancel = True
|
|
self.mp_ui = UI( const.GLADE_FILE, 'packageMaskWindow', 'entropy' )
|
|
self.mp_ui.signal_autoconnect(self._getAllMethods())
|
|
self.window = self.mp_ui.packageMaskWindow
|
|
self.mp_ui.packageMaskWindow.set_transient_for(self.parent)
|
|
self.cancelbutton = self.mp_ui.maskDialogCancelButton
|
|
self.okbutton = self.mp_ui.maskDialogOkButton
|
|
self.enableButton = self.mp_ui.maskDialogEnableButton
|
|
self.enableAllButton = self.mp_ui.maskDialogEnableAllButton
|
|
self.propertiesButton = self.mp_ui.maskDialogPropertiesButton
|
|
self.action = self.mp_ui.maskDialogAction
|
|
self.subaction = self.mp_ui.maskDialogSubtext
|
|
self.pkg = self.mp_ui.maskDialogPkg
|
|
self.button_pressed = False
|
|
# backward compat
|
|
self.ok_button_reply = -5
|
|
self.cancel_button_reply = -6
|
|
self.rc = self.cancel_button_reply
|
|
|
|
self.okbutton.connect("clicked", self.do_ok)
|
|
self.cancelbutton.connect("clicked",self.do_cancel)
|
|
self.enableButton.connect("clicked", self.enablePackage)
|
|
self.enableAllButton.connect("clicked", self.enableAllPackages)
|
|
self.propertiesButton.connect("clicked", self.openPackageProperties)
|
|
|
|
# setup text
|
|
if top_text == None:
|
|
top_text = _("These are the packages that must be enabled to satisfy your request")
|
|
|
|
tit = "<b><span foreground='%s' size='large'>%s</span></b>\n" % (SpritzConf.color_title,_("Some packages are masked"),)
|
|
tit += top_text
|
|
self.action.set_markup( tit )
|
|
if sub_text != None: self.subaction.set_markup( sub_text )
|
|
|
|
self.pkgs = pkgs
|
|
# fill
|
|
self.model = self.setup_view( self.pkg )
|
|
self.show_data( self.model, self.pkgs )
|
|
self.pkg.expand_all()
|
|
self.pkgcount = 0
|
|
self.maxcount = len(self.pkgs)
|
|
|
|
def get_obj(self):
|
|
model, myiter = self.pkg.get_selection().get_selected()
|
|
if myiter:
|
|
return model.get_value( myiter, 0 )
|
|
return None
|
|
|
|
def openPackageProperties(self, widget):
|
|
obj = self.get_obj()
|
|
if not obj:
|
|
return
|
|
mymenu = PkgInfoMenu(self.Entropy, obj, self.window)
|
|
mymenu.load()
|
|
|
|
def enablePackage(self, widget, obj = None, do_refresh = True):
|
|
if not obj:
|
|
obj = self.get_obj()
|
|
if not obj: return
|
|
if obj.matched_atom == (0,0): return
|
|
result = self.Entropy.unmask_match(obj.matched_atom, dry_run = True)
|
|
if result:
|
|
self.etpbase.unmaskingPackages.add(obj.matched_atom)
|
|
self.pkgcount += 1
|
|
if do_refresh:
|
|
self.refresh()
|
|
return result
|
|
|
|
def enableAllPackages(self, widget):
|
|
|
|
for parent in self.model:
|
|
for child in parent.iterchildren():
|
|
for obj in child:
|
|
if not obj:
|
|
continue
|
|
if obj.dummy_type != None:
|
|
continue
|
|
self.enablePackage(None,obj,False)
|
|
self.refresh()
|
|
|
|
def refresh(self):
|
|
self.pkg.queue_draw()
|
|
self.pkg.expand_all()
|
|
|
|
def do_cancel(self, widget):
|
|
self.button_pressed = True
|
|
|
|
def do_ok(self, widget):
|
|
self.rc = self.ok_button_reply
|
|
self.button_pressed = True
|
|
|
|
def on_packageMaskWindow_destroy_event(self, *args, **kwargs):
|
|
self.button_pressed = True
|
|
|
|
def on_packageMaskWindow_delete_event(self, *args, **kwargs):
|
|
self.button_pressed = True
|
|
|
|
def run( self ):
|
|
|
|
self.window.show_all()
|
|
self.okbutton.set_sensitive(False)
|
|
|
|
while not self.button_pressed:
|
|
time.sleep(0.05)
|
|
while gtk.events_pending():
|
|
gtk.main_iteration()
|
|
continue
|
|
|
|
self.window.destroy()
|
|
|
|
return self.rc
|
|
|
|
def setup_view( self, view ):
|
|
|
|
model = gtk.TreeStore( gobject.TYPE_PYOBJECT )
|
|
view.set_model( model )
|
|
|
|
cell1 = gtk.CellRendererText()
|
|
column1 = gtk.TreeViewColumn( _( "Masked package" ), cell1 )
|
|
column1.set_cell_data_func( cell1, self.show_pkg )
|
|
column1.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column1.set_fixed_width( 410 )
|
|
column1.set_resizable( True )
|
|
view.append_column( column1 )
|
|
|
|
cell2 = gtk.CellRendererPixbuf()
|
|
column2 = gtk.TreeViewColumn( _("Enabled"), cell2 )
|
|
column2.set_cell_data_func( cell2, self.new_pixbuf )
|
|
column2.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column2.set_fixed_width( 40 )
|
|
column2.set_sort_column_id( -1 )
|
|
view.append_column( column2 )
|
|
column2.set_clickable( False )
|
|
|
|
return model
|
|
|
|
|
|
def set_pixbuf_to_cell(self, cell, do):
|
|
if do:
|
|
cell.set_property( 'stock-id', 'gtk-apply' )
|
|
elif (not do) and isinstance(do,bool):
|
|
cell.set_property( 'stock-id', 'gtk-cancel' )
|
|
else:
|
|
cell.set_property( 'stock-id', None )
|
|
|
|
def new_pixbuf( self, column, cell, model, iterator ):
|
|
|
|
if self.pkgcount >= self.maxcount:
|
|
self.okbutton.set_sensitive(True)
|
|
|
|
obj = model.get_value( iterator, 0 )
|
|
if obj.matched_atom in self.etpbase.unmaskingPackages:
|
|
self.set_pixbuf_to_cell(cell, True)
|
|
elif obj.dummy_type:
|
|
self.set_pixbuf_to_cell(cell, None)
|
|
else:
|
|
self.set_pixbuf_to_cell(cell, False)
|
|
self.set_line_status(obj, cell, stype = "cell-background")
|
|
|
|
def show_pkg( self, column, cell, model, iterator ):
|
|
obj = model.get_value( iterator, 0 )
|
|
mydata = obj.namedesc
|
|
cell.set_property('markup', mydata )
|
|
self.set_line_status(obj, cell)
|
|
|
|
def set_line_status(self, obj, cell, stype = "cell-background"):
|
|
if obj.queued == "r":
|
|
cell.set_property(stype,'#FFE2A3')
|
|
elif obj.queued == "u":
|
|
cell.set_property(stype,'#B7BEFF')
|
|
elif obj.queued == "i":
|
|
cell.set_property(stype,'#D895FF')
|
|
elif obj.queued == "rr":
|
|
cell.set_property(stype,'#B7BEFF')
|
|
elif not obj.queued:
|
|
cell.set_property(stype,None)
|
|
|
|
def show_data( self, model, pkgs ):
|
|
|
|
model.clear()
|
|
self.pkg.set_model(None)
|
|
self.pkg.set_model(model)
|
|
|
|
desc_len = 80
|
|
search_col = 0
|
|
categories = {}
|
|
|
|
for po in pkgs:
|
|
mycat = po.cat
|
|
if not categories.has_key(mycat):
|
|
categories[mycat] = []
|
|
categories[mycat].append(po)
|
|
|
|
cats = categories.keys()
|
|
cats.sort()
|
|
for category in cats:
|
|
cat_desc = _("No description")
|
|
cat_desc_data = self.Entropy.get_category_description_data(category)
|
|
if cat_desc_data.has_key(_LOCALE):
|
|
cat_desc = cat_desc_data[_LOCALE]
|
|
elif cat_desc_data.has_key('en'):
|
|
cat_desc = cat_desc_data['en']
|
|
cat_text = "<b><big>%s</big></b>\n<small>%s</small>" % (category,cleanMarkupString(cat_desc),)
|
|
mydummy = packages.DummyEntropyPackage(
|
|
namedesc = cat_text,
|
|
dummy_type = SpritzConf.dummy_category,
|
|
onlyname = category
|
|
)
|
|
mydummy.color = SpritzConf.color_package_category
|
|
parent = model.append( None, (mydummy,) )
|
|
for po in categories[category]:
|
|
model.append( parent, (po,) )
|
|
|
|
self.pkg.set_search_column( search_col )
|
|
self.pkg.set_search_equal_func(self.atom_search)
|
|
self.pkg.set_property('headers-visible',True)
|
|
self.pkg.set_property('enable-search',True)
|
|
|
|
def atom_search(self, model, column, key, iterator):
|
|
obj = model.get_value( iterator, 0 )
|
|
if obj:
|
|
return not obj.onlyname.startswith(key)
|
|
return True
|
|
|
|
def destroy( self ):
|
|
return self.window.destroy()
|
|
|
|
class TextReadDialog(MenuSkel):
|
|
|
|
|
|
def __init__(self, title, text, read_only = True, rw_save_path = None):
|
|
|
|
self.rw_save_path = rw_save_path
|
|
self.txt_buffer = text
|
|
if not isinstance(text, gtk.TextBuffer):
|
|
self.txt_buffer = gtk.TextBuffer()
|
|
self.txt_buffer.set_text(text)
|
|
if not read_only and (rw_save_path == None):
|
|
raise AttributeError("rw_save_path must be vaild if not read_only")
|
|
|
|
xml_read = gtk.glade.XML(const.GLADE_FILE, 'textReadWindow',
|
|
domain="entropy")
|
|
self.__read_dialog = xml_read.get_widget( "textReadWindow" )
|
|
ok_read = xml_read.get_widget( "okReadButton" )
|
|
ok_read.connect( 'clicked', self.ok_button )
|
|
ok_save = xml_read.get_widget("okSaveButton")
|
|
ok_cancel = xml_read.get_widget("okCancelButton")
|
|
self.txt_view = xml_read.get_widget( "readTextView" )
|
|
self.txt_view.set_buffer(self.txt_buffer)
|
|
self.__read_dialog.set_title(title)
|
|
self.__read_dialog.show_all()
|
|
self.done_reading = False
|
|
|
|
ok_save.hide()
|
|
ok_cancel.hide()
|
|
if not read_only:
|
|
self.txt_view.set_editable(True)
|
|
self.txt_view.set_cursor_visible(True)
|
|
ok_read.hide()
|
|
ok_save.connect( 'clicked', self.ok_save_button )
|
|
ok_cancel.connect( 'clicked', self.ok_cancel_button )
|
|
ok_save.show()
|
|
ok_cancel.show()
|
|
|
|
def get_content(self):
|
|
start = self.txt_buffer.get_start_iter()
|
|
end = self.txt_buffer.get_end_iter()
|
|
return self.txt_buffer.get_text(start, end)
|
|
|
|
def ok_save_button(self, widget):
|
|
source_f = open(self.rw_save_path+".etp_tmp","w")
|
|
cont = self.get_content()
|
|
source_f.write(cont)
|
|
source_f.flush()
|
|
source_f.close()
|
|
os.rename(self.rw_save_path+".etp_tmp", self.rw_save_path)
|
|
self.ok_button(widget)
|
|
|
|
def ok_cancel_button(self, widget):
|
|
self.ok_button(widget)
|
|
|
|
def ok_button(self, widget):
|
|
self.done_reading = True
|
|
self.__read_dialog.destroy()
|
|
|
|
def run( self ):
|
|
""" you don't have to run this if you're looking for non-blocking d. """
|
|
while not self.done_reading:
|
|
time.sleep(0.1)
|
|
while gtk.events_pending():
|
|
gtk.main_iteration()
|
|
continue
|
|
|
|
|
|
|
|
class ConfirmationDialog:
|
|
|
|
def __init__( self, parent, pkgs, top_text = None, bottom_text = None, bottom_data = None, sub_text = None, cancel = True, simpleList = False, simpleDict = False ):
|
|
|
|
self.xml = gtk.glade.XML( const.GLADE_FILE, 'confirmation', domain="entropy" )
|
|
self.dialog = self.xml.get_widget( "confirmation" )
|
|
self.dialog.set_transient_for( parent )
|
|
self.action = self.xml.get_widget( "confAction" )
|
|
self.subaction = self.xml.get_widget( "confSubtext" )
|
|
self.bottomTitle = self.xml.get_widget( "bottomTitle" )
|
|
self.bottomData = self.xml.get_widget( "bottomData" )
|
|
self.cancelbutton = self.xml.get_widget( "cancelbutton2" )
|
|
self.okbutton = self.xml.get_widget( "okbutton2" )
|
|
self.bottomtext = self.xml.get_widget( "bottomTitle" )
|
|
self.lowerhbox = self.xml.get_widget( "hbox63" )
|
|
|
|
self.dobottomtext = bottom_text
|
|
self.dobottomdata = bottom_data
|
|
self.docancel = cancel
|
|
self.simpleList = simpleList
|
|
self.simpleDict = simpleDict
|
|
|
|
# setup text
|
|
if top_text == None:
|
|
top_text = _("Please confirm the actions above")
|
|
|
|
if sub_text == None:
|
|
sub_text = ""
|
|
|
|
tit = "<b>%s</b>" % (top_text,)
|
|
self.action.set_markup( tit )
|
|
if bottom_text != None: self.bottomTitle.set_markup( bottom_text )
|
|
if bottom_data != None: self.bottomData.set_text( bottom_data )
|
|
if sub_text != None: self.subaction.set_text( sub_text )
|
|
|
|
self.pkgs = pkgs
|
|
self.pkg = self.xml.get_widget( "confPkg" )
|
|
if self.simpleList:
|
|
self.pkgModel = self.setup_simple_view( self.pkg )
|
|
self.show_data_simple( self.pkgModel, pkgs )
|
|
elif self.simpleDict:
|
|
self.pkgModel = self.setup_simple_view( self.pkg )
|
|
self.show_data_simpledict( self.pkgModel, pkgs )
|
|
else:
|
|
self.pkgModel = self.setup_view( self.pkg )
|
|
self.show_data( self.pkgModel, pkgs )
|
|
self.pkg.expand_all()
|
|
|
|
def run( self ):
|
|
self.dialog.show_all()
|
|
if not self.docancel:
|
|
self.cancelbutton.hide()
|
|
if not self.dobottomtext:
|
|
self.bottomtext.hide()
|
|
if not self.dobottomdata:
|
|
self.lowerhbox.hide()
|
|
return self.dialog.run()
|
|
|
|
def setup_view( self, view ):
|
|
model = gtk.TreeStore( gobject.TYPE_STRING )
|
|
model.set_sort_column_id( 0, gtk.SORT_ASCENDING )
|
|
view.set_model( model )
|
|
self.create_text_column( _( "Package" ), view, 0 )
|
|
return model
|
|
|
|
def setup_simple_view(self, view ):
|
|
model = gtk.TreeStore( gobject.TYPE_STRING )
|
|
view.set_model( model )
|
|
self.create_text_column( _( "Item" ), view, 0 )
|
|
return model
|
|
|
|
def create_text_column( self, hdr, view, colno, min_width=0, max_width=0 ):
|
|
cell = gtk.CellRendererText() # Size Column
|
|
column = gtk.TreeViewColumn( hdr, cell, markup=colno )
|
|
column.set_resizable( True )
|
|
if min_width:
|
|
column.set_min_width( min_width )
|
|
if max_width:
|
|
column.set_max_width( max_width )
|
|
view.append_column( column )
|
|
|
|
def show_data_simpledict( self, model, pkgs ):
|
|
model.clear()
|
|
if pkgs.has_key("reinstall"):
|
|
if pkgs['reinstall']:
|
|
label = "<b>%s</b>" % _("To be reinstalled")
|
|
parent = model.append( None, [label] )
|
|
for pkg in pkgs['reinstall']:
|
|
model.append( parent, [pkg] )
|
|
if pkgs.has_key("install"):
|
|
if pkgs['install']:
|
|
label = "<b>%s</b>" % _("To be installed")
|
|
parent = model.append( None, [label] )
|
|
for pkg in pkgs['install']:
|
|
model.append( parent, [pkg] )
|
|
if pkgs.has_key("update"):
|
|
if pkgs['update']:
|
|
label = "<b>%s</b>" % _("To be updated")
|
|
parent = model.append( None, [label] )
|
|
for pkg in pkgs['update']:
|
|
model.append( parent, [pkg] )
|
|
if pkgs.has_key("downgrade"):
|
|
if pkgs['downgrade']:
|
|
label = "<b>%s</b>" % _("To be downgraded")
|
|
parent = model.append( None, [label] )
|
|
for pkg in pkgs['downgrade']:
|
|
model.append( parent, [pkg] )
|
|
if pkgs.has_key("remove"):
|
|
if pkgs['remove']:
|
|
label = "<b>%s</b>" % _("To be removed")
|
|
parent = model.append( None, [label] )
|
|
for pkg in pkgs['remove']:
|
|
model.append( parent, [pkg] )
|
|
|
|
def show_data_simple( self, model, pkgs ):
|
|
model.clear()
|
|
for pkg in pkgs:
|
|
model.append( None, [pkg] )
|
|
|
|
def show_data( self, model, pkgs ):
|
|
model.clear()
|
|
desc_len = 80
|
|
install = [x for x in pkgs if x.action == "i"]
|
|
update = [x for x in pkgs if x.action == "u"]
|
|
remove = [x for x in pkgs if x.action == "r"]
|
|
reinstall = [x for x in pkgs if x.action == "rr"]
|
|
if remove:
|
|
label = "<b>%s</b>" % _("To be removed")
|
|
level1 = model.append( None, [label] )
|
|
for pkg in remove:
|
|
desc = pkg.description[:desc_len].rstrip()+"..."
|
|
desc = cleanMarkupString(desc)
|
|
if not desc.strip():
|
|
desc = _("No description")
|
|
mydesc = "\n<small><span foreground='%s'>%s</span></small>" % (SpritzConf.color_pkgdesc,desc,)
|
|
mypkg = "<span foreground='%s'>%s</span>" % (SpritzConf.color_remove,str(pkg),)
|
|
model.append( level1, [mypkg+mydesc] )
|
|
if reinstall:
|
|
label = "<b>%s</b>" % _("To be reinstalled")
|
|
level1 = model.append( None, [label] )
|
|
for pkg in reinstall:
|
|
desc = pkg.description[:desc_len].rstrip()+"..."
|
|
desc = cleanMarkupString(desc)
|
|
if not desc.strip():
|
|
desc = _("No description")
|
|
mydesc = "\n<small><span foreground='%s'>%s</span></small>" % (SpritzConf.color_pkgdesc,desc,)
|
|
mypkg = "<span foreground='%s'>%s</span>" % (SpritzConf.color_reinstall,str(pkg),)
|
|
model.append( level1, [mypkg+mydesc] )
|
|
if install:
|
|
label = "<b>%s</b>" % _("To be installed")
|
|
level1 = model.append( None, [label] )
|
|
for pkg in install:
|
|
desc = pkg.description[:desc_len].rstrip()+"..."
|
|
desc = cleanMarkupString(desc)
|
|
if not desc.strip():
|
|
desc = _("No description")
|
|
mydesc = "\n<small><span foreground='%s'>%s</span></small>" % (SpritzConf.color_pkgdesc,desc,)
|
|
mypkg = "<span foreground='%s'>%s</span>" % (SpritzConf.color_install,str(pkg),)
|
|
model.append( level1, [mypkg+mydesc] )
|
|
if update:
|
|
label = "<b>%s</b>" % _("To be updated")
|
|
level1 = model.append( None, [label] )
|
|
for pkg in update:
|
|
desc = pkg.description[:desc_len].rstrip()+"..."
|
|
desc = cleanMarkupString(desc)
|
|
if not desc.strip():
|
|
desc = _("No description")
|
|
mydesc = "\n<small><span foreground='%s'>%s</span></small>" % (SpritzConf.color_pkgdesc,desc,)
|
|
mypkg = "<span foreground='%s'>%s</span>" % (SpritzConf.color_update,str(pkg),)
|
|
model.append( level1, [mypkg+mydesc] )
|
|
|
|
def destroy( self ):
|
|
return self.dialog.destroy()
|
|
|
|
class ErrorDialog:
|
|
|
|
def __init__( self, parent, title, text, longtext, modal ):
|
|
self.xml = gtk.glade.XML( const.GLADE_FILE, "errDialog",domain="entropy" )
|
|
self.dialog = self.xml.get_widget( "errDialog" )
|
|
self.parent = parent
|
|
if parent:
|
|
self.dialog.set_transient_for( parent )
|
|
#self.dialog.set_icon_name( 'gtk-dialog-error' )
|
|
self.dialog.set_title( title )
|
|
self.text = self.xml.get_widget( "errText" )
|
|
self.longtext = self.xml.get_widget( "errTextView" )
|
|
self.nameInput = self.xml.get_widget( "nameEntry" )
|
|
self.mailInput = self.xml.get_widget( "mailEntry" )
|
|
self.reportLabel = self.xml.get_widget( "reportLabel" )
|
|
self.errorButton = self.xml.get_widget( "errorButton" )
|
|
self.actionInput = self.xml.get_widget( "actionEntry" )
|
|
self.reportTable = self.xml.get_widget( "reportTable" )
|
|
self.style_err = gtk.TextTag( "error" )
|
|
self.style_err.set_property( "style", pango.STYLE_ITALIC )
|
|
self.style_err.set_property( "foreground", "#760000" )
|
|
self.style_err.set_property( "family", "Monospace" )
|
|
self.style_err.set_property( "size_points", 8 )
|
|
self.longtext.get_buffer().get_tag_table().add( self.style_err )
|
|
|
|
if modal:
|
|
self.dialog.set_modal( True )
|
|
if text != "":
|
|
self.set_text( text )
|
|
if longtext != "" and longtext != None:
|
|
self.set_long_text( longtext )
|
|
|
|
def set_text( self, text ):
|
|
self.text.set_markup( text )
|
|
|
|
def set_long_text( self, longtext ):
|
|
mybuffer = self.longtext.get_buffer()
|
|
start, end = mybuffer.get_bounds()
|
|
mybuffer.insert_with_tags( end, longtext, self.style_err )
|
|
|
|
def run( self, showreport = False ):
|
|
self.dialog.show_all()
|
|
if not showreport:
|
|
self.hide_report_widgets()
|
|
return self.dialog.run()
|
|
|
|
def hide_report_widgets(self):
|
|
self.reportTable.hide_all()
|
|
self.errorButton.hide()
|
|
self.reportLabel.hide()
|
|
|
|
def get_entries( self ):
|
|
mail = self.mailInput.get_text()
|
|
name = self.nameInput.get_text()
|
|
desc = self.actionInput.get_text()
|
|
return name,mail,desc
|
|
|
|
def destroy( self ):
|
|
return self.dialog.destroy()
|
|
|
|
class infoDialog:
|
|
def __init__( self, parent, title, text ):
|
|
self.xml = gtk.glade.XML( const.GLADE_FILE, "msg",domain="entropy" )
|
|
self.dialog = self.xml.get_widget( "msg" )
|
|
self.parent = parent
|
|
self.dialog.set_transient_for( parent )
|
|
#self.dialog.set_icon_name( 'gtk-dialog-error' )
|
|
self.dialog.set_title( title )
|
|
self.text = self.xml.get_widget( "msgText" )
|
|
self.dialog.set_modal( True )
|
|
self.set_text( text )
|
|
|
|
def set_text( self, text ):
|
|
self.text.set_markup( "<span size='large'>%s</span>" % text )
|
|
|
|
def run( self ):
|
|
self.dialog.show_all()
|
|
return self.dialog.run()
|
|
|
|
def destroy( self ):
|
|
return self.dialog.destroy()
|
|
|
|
|
|
class EntryDialog:
|
|
def __init__( self, parent, title, text ):
|
|
self.xml = gtk.glade.XML( const.GLADE_FILE, "EntryDialog",domain="entropy" )
|
|
self.dialog = self.xml.get_widget( "EntryDialog" )
|
|
self.parent = parent
|
|
#self.dialog.set_transient_for( parent )
|
|
#self.dialog.set_icon_name( 'gtk-dialog-error' )
|
|
self.dialog.set_title( title )
|
|
self.text = self.xml.get_widget( "inputLabel" )
|
|
self.entry = self.xml.get_widget( "inputEntry" )
|
|
self.dialog.set_modal( True )
|
|
self.text.set_text( text )
|
|
|
|
def run( self ):
|
|
self.dialog.show_all()
|
|
rc = self.dialog.run()
|
|
if rc == gtk.RESPONSE_OK:
|
|
return self.entry.get_text()
|
|
else:
|
|
return None
|
|
|
|
def destroy( self ):
|
|
return self.dialog.destroy()
|
|
|
|
class AboutDialog(gtk.Window):
|
|
|
|
""" Class for a fancy "About" dialog.
|
|
Mostly ripped from the one in gDesklets
|
|
"""
|
|
|
|
def __init__(self, gfx, creditText, title = "Spritz Package Manager"):
|
|
|
|
self.__is_stopped = True
|
|
self.__scroller_values = ()
|
|
|
|
|
|
gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
|
|
self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
|
self.set_position(gtk.WIN_POS_CENTER)
|
|
self.set_resizable(False)
|
|
self.set_title("%s %s" % (_("About"),title,))
|
|
self.connect("button-press-event", self.__on_close)
|
|
self.connect("key-press-event", self.__on_close)
|
|
self.connect("delete-event", self.__on_close)
|
|
self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
|
|
self.set_decorated(False)
|
|
|
|
fixed = gtk.Fixed()
|
|
self.add(fixed)
|
|
|
|
img = gtk.Image()
|
|
img.set_from_file(gfx)
|
|
fixed.put(img, 0, 0)
|
|
|
|
width, height = img.size_request()
|
|
|
|
scroller = gtk.Fixed()
|
|
scroller.set_size_request(width, height - 32)
|
|
fixed.put(scroller, 0, 32)
|
|
|
|
text = ""
|
|
for header, body in creditText:
|
|
text += "<b>" + header + "</b>\n\n"
|
|
text += "\n".join(body)
|
|
text += "\n\n\n\n"
|
|
text = "<big>" + text.strip() + "</big>"
|
|
|
|
mycredits = gtk.Label("<span foreground='#FFFFFF'>%s</span>" % (text,))
|
|
mycredits.set_use_markup(True)
|
|
mycredits.set_justify(gtk.JUSTIFY_CENTER)
|
|
|
|
lbl_width, lbl_height = mycredits.size_request()
|
|
scroller.put(mycredits, (width - lbl_width) / 2, height)
|
|
|
|
self.__scroller = scroller
|
|
self.__credits = mycredits
|
|
|
|
self.__scroller_values = (height - 32, -lbl_height,
|
|
(width - lbl_width) / 2)
|
|
|
|
|
|
def __scroll(self, ycoord):
|
|
|
|
begin, end, xcoord = self.__scroller_values
|
|
self.__scroller.move(self.__credits, xcoord, ycoord)
|
|
ycoord -= 1
|
|
|
|
if (ycoord < end):
|
|
ycoord = begin
|
|
|
|
if (not self.__is_stopped):
|
|
gobject.timeout_add(50, self.__scroll, ycoord)
|
|
|
|
return False
|
|
|
|
|
|
def __on_close(self, *args):
|
|
|
|
self.__is_stopped = True
|
|
self.hide()
|
|
return True
|
|
|
|
|
|
def show(self):
|
|
|
|
if (not self.__is_stopped):
|
|
return
|
|
|
|
self.show_all()
|
|
|
|
self.__is_stopped = False
|
|
begin, end, xcoord = self.__scroller_values
|
|
gobject.idle_add(self.__scroll, begin)
|
|
|
|
|
|
def inputBox( parent, title, text, input_text = None):
|
|
dlg = EntryDialog(parent, title, text)
|
|
if input_text:
|
|
dlg.entry.set_text(input_text)
|
|
rc = dlg.run()
|
|
dlg.destroy()
|
|
return rc
|
|
|
|
def FileChooser(basedir = None, pattern = None, action = gtk.FILE_CHOOSER_ACTION_OPEN, buttons = (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)):
|
|
# open file selector
|
|
dialog = gtk.FileChooserDialog(
|
|
title = None,
|
|
action = action,
|
|
buttons = buttons
|
|
)
|
|
if not basedir:
|
|
basedir = os.getenv('HOME')
|
|
if not basedir:
|
|
basedir = "/tmp"
|
|
|
|
fn = None
|
|
dialog.set_current_folder(basedir)
|
|
if pattern:
|
|
myfilter = gtk.FileFilter()
|
|
myfilter.add_pattern(pattern)
|
|
dialog.set_filter(myfilter)
|
|
response = dialog.run()
|
|
if response == gtk.RESPONSE_OK:
|
|
fn = dialog.get_filename()
|
|
dialog.destroy()
|
|
return fn
|
|
|
|
def errorMessage( parent, title, text, longtext=None, modal= True, showreport = False ):
|
|
dlg = ErrorDialog( parent, title, text, longtext, modal )
|
|
rc = dlg.run(showreport)
|
|
entries = dlg.get_entries()
|
|
dlg.destroy()
|
|
return rc, entries
|
|
|
|
def infoMessage( parent, title, text ):
|
|
dlg = infoDialog( parent, title, text )
|
|
rc = dlg.run()
|
|
dlg.destroy()
|
|
return not rc == gtk.RESPONSE_OK
|
|
|
|
def questionDialog(parent, msg, title = _("Spritz Question"), get_response = False):
|
|
dlg = gtk.MessageDialog(
|
|
parent=parent,
|
|
type = gtk.MESSAGE_QUESTION,
|
|
buttons = gtk.BUTTONS_YES_NO,
|
|
message_format = _("Hey!")
|
|
)
|
|
dlg.set_title(title)
|
|
dlg.format_secondary_markup(cleanMarkupString(msg))
|
|
rc = dlg.run()
|
|
dlg.destroy()
|
|
if get_response:
|
|
return rc
|
|
if rc == gtk.RESPONSE_YES:
|
|
return True
|
|
return False
|
|
|
|
def choiceDialog(parent, msg, title, buttons):
|
|
return MessageDialog(parent, title, msg, type = "custom", custom_buttons = buttons).getrc()
|
|
|
|
def inputDialog(parent, title, input_parameters, cancel):
|
|
w = InputDialog(parent, title, input_parameters, cancel)
|
|
return w.run()
|
|
|
|
def okDialog(parent, msg, title = None):
|
|
dlg = gtk.MessageDialog(parent=parent,
|
|
type=gtk.MESSAGE_INFO,
|
|
buttons=gtk.BUTTONS_OK)
|
|
dlg.set_markup(msg)
|
|
if not title:
|
|
title = _("Attention")
|
|
dlg.set_title( title )
|
|
dlg.run()
|
|
dlg.destroy()
|
|
|
|
|
|
|
|
class InputDialog:
|
|
|
|
parameters = {}
|
|
button_pressed = False
|
|
main_window = None
|
|
parent = None
|
|
def __init__(self, parent, title, input_parameters, cancel = True):
|
|
|
|
mywin = gtk.Window()
|
|
# avoids to taint the returning elements
|
|
# when running nested
|
|
self.parameters = self.parameters.copy()
|
|
|
|
mywin.set_title(_("Please fill the following form"))
|
|
myvbox = gtk.VBox()
|
|
mylabel = gtk.Label()
|
|
mylabel.set_markup(cleanMarkupString(title))
|
|
myhbox = gtk.HBox()
|
|
myvbox.pack_start(mylabel, expand = False, fill = False)
|
|
mytable = gtk.Table(rows = len(input_parameters), columns = 2)
|
|
self.identifiers_table = {}
|
|
self.cb_table = {}
|
|
self.entry_text_table = {}
|
|
row_count = 0
|
|
for input_id, input_text, input_cb, passworded in input_parameters:
|
|
|
|
if isinstance(input_text,tuple):
|
|
|
|
input_type, text = input_text
|
|
combo_options = []
|
|
if isinstance(text,tuple):
|
|
text, combo_options = text
|
|
|
|
input_label = gtk.Label()
|
|
input_label.set_line_wrap(True)
|
|
input_label.set_alignment(0.0,0.5)
|
|
input_label.set_markup(text)
|
|
|
|
if input_type == "checkbox":
|
|
|
|
input_widget = gtk.CheckButton(text)
|
|
input_widget.set_alignment(0.0,0.5)
|
|
input_widget.set_active(passworded)
|
|
|
|
elif input_type == "combo":
|
|
|
|
input_widget = gtk.combo_box_new_text()
|
|
for opt in combo_options:
|
|
input_widget.append_text(opt)
|
|
if combo_options:
|
|
input_widget.set_active(0)
|
|
mytable.attach(input_label, 0, 1, row_count, row_count+1)
|
|
|
|
elif input_type == "list":
|
|
|
|
myhbox_l = gtk.HBox()
|
|
input_widget = gtk.ListStore(gobject.TYPE_STRING)
|
|
view = gtk.TreeView()
|
|
cell = gtk.CellRendererText()
|
|
column = gtk.TreeViewColumn( text, cell, markup = 0 )
|
|
column.set_resizable( True )
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_expand(True)
|
|
view.append_column( column )
|
|
view.set_model(input_widget)
|
|
for opt in combo_options:
|
|
input_widget.append((opt,))
|
|
myhbox_l.pack_start(view, expand = True, fill = True)
|
|
|
|
myvbox_l = gtk.VBox()
|
|
add_button = gtk.Button()
|
|
add_image = gtk.Image()
|
|
add_image.set_from_stock("gtk-add", gtk.ICON_SIZE_BUTTON)
|
|
add_button.add(add_image)
|
|
rm_button = gtk.Button()
|
|
rm_image = gtk.Image()
|
|
rm_image.set_from_stock("gtk-remove", gtk.ICON_SIZE_BUTTON)
|
|
rm_button.add(rm_image)
|
|
myvbox_l.pack_start(add_button, expand = False, fill = False)
|
|
myvbox_l.pack_start(rm_button, expand = False, fill = False)
|
|
|
|
def on_add_button(widget):
|
|
mydata = inputDialog(mywin, _("Add atom"), [('atom',_('Atom'),input_cb,False)], True)
|
|
if mydata == None: return
|
|
atom = mydata.get('atom')
|
|
input_widget.append((atom,))
|
|
|
|
def on_remove_button(widget):
|
|
model, iterator = view.get_selection().get_selected()
|
|
if iterator == None: return
|
|
model.remove(iterator)
|
|
|
|
add_button.connect("clicked",on_add_button)
|
|
rm_button.connect("clicked",on_remove_button)
|
|
|
|
myhbox_l.pack_start(myvbox_l, expand = False, fill = False)
|
|
mytable.attach(myhbox_l, 0, 2, row_count, row_count+1)
|
|
|
|
elif input_type == "text":
|
|
|
|
def rescroll_output(adj, scroll):
|
|
adj.set_value(adj.upper-adj.page_size)
|
|
scroll.set_vadjustment(adj)
|
|
|
|
scrolled_win = gtk.ScrolledWindow()
|
|
scrolled_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
|
scrolled_win.set_placement(gtk.CORNER_BOTTOM_LEFT)
|
|
# textview
|
|
input_widget = gtk.TextBuffer()
|
|
output_scroll_vadj = scrolled_win.get_vadjustment()
|
|
output_scroll_vadj.connect('changed', lambda a, s=scrolled_win: rescroll_output(a,s))
|
|
|
|
my_tv = gtk.TextView()
|
|
my_tv.set_buffer(input_widget)
|
|
my_tv.set_wrap_mode(gtk.WRAP_WORD)
|
|
my_tv.set_editable(True)
|
|
my_tv.set_accepts_tab(True)
|
|
scrolled_win.add_with_viewport(my_tv)
|
|
mytable.attach(input_label, 0, 1, row_count, row_count+1)
|
|
mytable.attach(scrolled_win, 1, 2, row_count, row_count+1)
|
|
|
|
else:
|
|
continue
|
|
|
|
self.entry_text_table[input_id] = text
|
|
self.identifiers_table[input_id] = input_widget
|
|
if input_type in ["list"]:
|
|
def input_cb(s): return s
|
|
self.cb_table[input_widget] = input_cb
|
|
if input_type not in ["text","list"]:
|
|
mytable.attach(input_widget, 1, 2, row_count, row_count+1)
|
|
|
|
|
|
else:
|
|
|
|
input_label = gtk.Label()
|
|
input_label.set_line_wrap(True)
|
|
input_label.set_alignment(0.0,0.5)
|
|
input_label.set_markup(input_text)
|
|
self.entry_text_table[input_id] = input_text
|
|
mytable.attach(input_label, 0, 1, row_count, row_count+1)
|
|
input_entry = gtk.Entry()
|
|
if passworded: input_entry.set_visibility(False)
|
|
|
|
self.identifiers_table[input_id] = input_entry
|
|
self.cb_table[input_entry] = input_cb
|
|
mytable.attach(input_entry, 1, 2, row_count, row_count+1)
|
|
|
|
row_count += 1
|
|
myvbox.pack_start(mytable)
|
|
bbox = gtk.HButtonBox()
|
|
bbox.set_layout(gtk.BUTTONBOX_END)
|
|
bbox.set_spacing(10)
|
|
myok = gtk.Button(stock = "gtk-ok")
|
|
myok.connect('clicked', self.do_ok )
|
|
bbox.pack_start(myok, padding = 10)
|
|
if cancel:
|
|
mycancel = gtk.Button(stock = "gtk-cancel")
|
|
mycancel.connect('clicked', self.do_cancel )
|
|
bbox.pack_start(mycancel)
|
|
myvbox.pack_start(bbox, expand = False, fill = False)
|
|
myvbox.set_spacing(10)
|
|
myvbox.show()
|
|
myhbox.pack_start(myvbox, padding = 10)
|
|
myhbox.show()
|
|
mywin.add(myhbox)
|
|
self.main_window = mywin
|
|
self.parent = parent
|
|
mywin.set_keep_above(True)
|
|
mywin.set_urgency_hint(True)
|
|
if parent == None:
|
|
mywin.set_position(gtk.WIN_POS_CENTER)
|
|
else:
|
|
mywin.set_transient_for(parent)
|
|
mywin.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
|
mywin.set_default_size(350,-1)
|
|
mywin.show_all()
|
|
|
|
|
|
def do_ok(self, widget):
|
|
# fill self.parameters
|
|
for input_id in self.identifiers_table:
|
|
mywidget = self.identifiers_table.get(input_id)
|
|
if isinstance(mywidget,gtk.Entry):
|
|
content = mywidget.get_text()
|
|
elif isinstance(mywidget,gtk.CheckButton):
|
|
content = mywidget.get_active()
|
|
elif isinstance(mywidget,gtk.ComboBox):
|
|
content = mywidget.get_active(),mywidget.get_active_text()
|
|
elif isinstance(mywidget,gtk.TextBuffer):
|
|
content = mywidget.get_text(mywidget.get_start_iter(),mywidget.get_end_iter(), True)
|
|
elif isinstance(mywidget,(gtk.ListStore,gtk.TreeStore,)):
|
|
myiter = mywidget.get_iter_first()
|
|
content = []
|
|
while myiter:
|
|
content.append(mywidget.get_value(myiter, 0))
|
|
myiter = mywidget.iter_next(myiter)
|
|
else:
|
|
continue
|
|
verify_cb = self.cb_table.get(mywidget)
|
|
valid = verify_cb(content)
|
|
if not valid:
|
|
okDialog(self.parent, "%s: %s" % (_("Invalid entry"),self.entry_text_table[input_id],) , title = _("Invalid entry"))
|
|
self.parameters.clear()
|
|
return
|
|
self.parameters[input_id] = content
|
|
self.button_pressed = True
|
|
|
|
def do_cancel(self, widget):
|
|
self.parameters = None
|
|
self.button_pressed = True
|
|
|
|
def run(self):
|
|
self.parameters.clear()
|
|
while not self.button_pressed:
|
|
time.sleep(0.05)
|
|
while gtk.events_pending():
|
|
gtk.main_iteration()
|
|
continue
|
|
self.main_window.destroy()
|
|
return self.parameters
|
|
|
|
class MessageDialog:
|
|
"""
|
|
courtesy of Anaconda :-) Copyright 1999-2005 Red Hat, Inc.
|
|
Matt Wilson <msw@redhat.com>
|
|
Michael Fulbright <msf@redhat.com>
|
|
"""
|
|
|
|
def getrc(self):
|
|
return self.rc
|
|
|
|
def __init__ (self, parent, title, text, type = "ok", default=None, custom_buttons=None, custom_icon=None):
|
|
self.rc = None
|
|
docustom = 0
|
|
if type == 'ok':
|
|
buttons = gtk.BUTTONS_OK
|
|
style = gtk.MESSAGE_INFO
|
|
elif type == 'warning':
|
|
buttons = gtk.BUTTONS_OK
|
|
style = gtk.MESSAGE_WARNING
|
|
elif type == 'okcancel':
|
|
buttons = gtk.BUTTONS_OK_CANCEL
|
|
style = gtk.MESSAGE_WARNING
|
|
elif type == 'yesno':
|
|
buttons = gtk.BUTTONS_YES_NO
|
|
style = gtk.MESSAGE_QUESTION
|
|
elif type == 'custom':
|
|
docustom = 1
|
|
buttons = gtk.BUTTONS_NONE
|
|
style = gtk.MESSAGE_QUESTION
|
|
|
|
if custom_icon == "warning":
|
|
style = gtk.MESSAGE_WARNING
|
|
elif custom_icon == "question":
|
|
style = gtk.MESSAGE_QUESTION
|
|
elif custom_icon == "error":
|
|
style = gtk.MESSAGE_ERROR
|
|
elif custom_icon == "info":
|
|
style = gtk.MESSAGE_INFO
|
|
|
|
dialog = gtk.MessageDialog(parent, 0, style, buttons, text)
|
|
|
|
if docustom:
|
|
rid=0
|
|
for button in custom_buttons:
|
|
if button == _("Cancel"):
|
|
tbutton = "gtk-cancel"
|
|
else:
|
|
tbutton = button
|
|
|
|
widget = dialog.add_button(tbutton, rid)
|
|
rid = rid + 1
|
|
|
|
defaultchoice = rid - 1
|
|
else:
|
|
if default == "no":
|
|
defaultchoice = 0
|
|
elif default == "yes" or default == "ok":
|
|
defaultchoice = 1
|
|
else:
|
|
defaultchoice = 0
|
|
|
|
dialog.set_title(title)
|
|
#dialog.format_secondary_markup(cleanMarkupString(text))
|
|
dialog.set_position (gtk.WIN_POS_CENTER)
|
|
dialog.set_default_response(defaultchoice)
|
|
dialog.show_all ()
|
|
|
|
rc = dialog.run()
|
|
|
|
if rc == gtk.RESPONSE_OK or rc == gtk.RESPONSE_YES:
|
|
self.rc = 1
|
|
elif (rc == gtk.RESPONSE_CANCEL or rc == gtk.RESPONSE_NO
|
|
or rc == gtk.RESPONSE_CLOSE):
|
|
self.rc = 0
|
|
elif rc == gtk.RESPONSE_DELETE_EVENT:
|
|
self.rc = 0
|
|
else:
|
|
self.rc = rc
|
|
dialog.destroy()
|
|
|
|
class LicenseDialog:
|
|
def __init__( self, spritz_app, entropy, licenses ):
|
|
|
|
self.parent = spritz_app.ui.main
|
|
self.Spritz = spritz_app
|
|
self.Entropy = entropy
|
|
self.xml = gtk.glade.XML( const.GLADE_FILE, 'licenseWindow',domain="entropy" )
|
|
self.xml_licread = gtk.glade.XML( const.GLADE_FILE, 'textReadWindow',domain="entropy" )
|
|
self.dialog = self.xml.get_widget( "licenseWindow" )
|
|
self.dialog.set_transient_for( self.parent )
|
|
self.read_dialog = self.xml_licread.get_widget( "textReadWindow" )
|
|
self.read_dialog.connect( 'delete-event', self.close_read_text_window )
|
|
#self.read_dialog.set_transient_for( self.dialog )
|
|
self.licenseView = self.xml_licread.get_widget( "readTextView" )
|
|
self.okReadButton = self.xml_licread.get_widget( "okReadButton" )
|
|
self.okReadButton.connect( "clicked", self.close_read_text )
|
|
|
|
|
|
self.okButton = self.xml.get_widget( "confirmLicense" )
|
|
self.stopButton = self.xml.get_widget( "discardLicense" )
|
|
self.acceptLicense = self.xml.get_widget( "acceptLicense" )
|
|
self.acceptLicense.connect( "clicked", self.accept_selected_license )
|
|
self.readLicense = self.xml.get_widget( "readLicense" )
|
|
self.readLicense.connect( "clicked", self.read_selected_license )
|
|
|
|
self.view = self.xml.get_widget( "licenseView1" )
|
|
self.model = self.setup_view()
|
|
self.show_data( licenses )
|
|
self.view.expand_all()
|
|
self.licenses = licenses
|
|
self.accepted = set()
|
|
|
|
|
|
def close_read_text_window(self, widget, path):
|
|
self.read_dialog.hide()
|
|
return True
|
|
|
|
def close_read_text(self, widget ):
|
|
self.read_dialog.hide()
|
|
|
|
def run( self ):
|
|
self.dialog.show_all()
|
|
return self.dialog.run()
|
|
|
|
def destroy( self ):
|
|
return self.dialog.destroy()
|
|
|
|
def setup_view(self):
|
|
model = gtk.TreeStore( gobject.TYPE_STRING, gobject.TYPE_PYOBJECT )
|
|
self.view.set_model( model )
|
|
self.create_text_column( _( "License" ), 0, size = 200 )
|
|
|
|
cell2 = gtk.CellRendererPixbuf() # new
|
|
column2 = gtk.TreeViewColumn( _("Accepted"), cell2 )
|
|
column2.set_cell_data_func( cell2, self.new_pixbuf )
|
|
column2.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column2.set_fixed_width( 20 )
|
|
column2.set_sort_column_id( -1 )
|
|
self.view.append_column( column2 )
|
|
column2.set_clickable( False )
|
|
|
|
return model
|
|
|
|
def set_pixbuf_to_cell(self, cell, do):
|
|
if do:
|
|
cell.set_property( 'stock-id', 'gtk-apply' )
|
|
elif (not do) and isinstance(do,bool):
|
|
cell.set_property( 'stock-id', 'gtk-cancel' )
|
|
else:
|
|
cell.set_property( 'stock-id', None )
|
|
|
|
def new_pixbuf( self, column, cell, model, iterator ):
|
|
license_identifier = model.get_value( iterator, 0 )
|
|
chief = model.get_value( iterator, 1 )
|
|
if (license_identifier in self.accepted) and chief:
|
|
self.set_pixbuf_to_cell(cell, True)
|
|
elif chief:
|
|
self.set_pixbuf_to_cell(cell, False)
|
|
elif chief == None:
|
|
self.set_pixbuf_to_cell(cell, None)
|
|
|
|
def create_text_column( self, hdr, colno, size = None ):
|
|
cell = gtk.CellRendererText() # Size Column
|
|
column = gtk.TreeViewColumn( hdr, cell, markup=colno )
|
|
if size != None:
|
|
column.set_sizing( gtk.TREE_VIEW_COLUMN_FIXED )
|
|
column.set_fixed_width( size )
|
|
column.set_resizable( False )
|
|
self.view.append_column( column )
|
|
|
|
def read_selected_license(self, widget):
|
|
model, iterator = self.view.get_selection().get_selected()
|
|
if model != None and iterator != None:
|
|
license_identifier = model.get_value( iterator, 0 )
|
|
if not self.licenses.has_key(license_identifier): # for security reasons
|
|
return
|
|
packages = self.licenses[license_identifier]
|
|
license_text = ''
|
|
for package in packages:
|
|
repoid = package[1]
|
|
dbconn = self.Entropy.open_repository(repoid)
|
|
if dbconn.isLicensedataKeyAvailable(license_identifier):
|
|
license_text = dbconn.retrieveLicenseText(license_identifier)
|
|
break
|
|
# prepare textview
|
|
mybuffer = gtk.TextBuffer()
|
|
mybuffer.set_text(unicode(license_text,'raw_unicode_escape'))
|
|
self.licenseView.set_buffer(mybuffer)
|
|
self.read_dialog.set_title(license_identifier+" license text")
|
|
self.read_dialog.show_all()
|
|
|
|
def accept_selected_license(self, widget):
|
|
model, iterator = self.view.get_selection().get_selected()
|
|
if model != None and iterator != None:
|
|
license_identifier = model.get_value( iterator, 0 )
|
|
chief = model.get_value( iterator, 1 )
|
|
if chief:
|
|
self.accepted.add(license_identifier)
|
|
self.view.queue_draw()
|
|
if len(self.accepted) == len(self.licenses):
|
|
self.okButton.set_sensitive(True)
|
|
|
|
def show_data( self, licenses ):
|
|
self.model.clear()
|
|
for lic in licenses:
|
|
parent = self.model.append( None, [lic,True] )
|
|
packages = licenses[lic]
|
|
for match in packages:
|
|
dbconn = self.Entropy.open_repository(match[1])
|
|
atom = dbconn.retrieveAtom(match[0])
|
|
self.model.append( parent, [atom,None] )
|
|
|
|
class ExceptionDialog:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
def show(self):
|
|
import entropy.tools
|
|
from entropy.qa import ErrorReportInterface
|
|
errmsg = entropy.tools.get_traceback()
|
|
conntest = entropy.tools.get_remote_data(etpConst['conntestlink'])
|
|
rc, (name,mail,description) = errorMessage(
|
|
None,
|
|
_( "Exception caught" ),
|
|
_( "Spritz crashed! An unexpected error occured." ),
|
|
errmsg,
|
|
showreport = conntest
|
|
)
|
|
if rc == -1:
|
|
error = ErrorReportInterface()
|
|
error.prepare(errmsg, name, mail, description = description)
|
|
result = error.submit()
|
|
if result:
|
|
okDialog(None,_("Your report has been submitted successfully! Thanks a lot."))
|
|
else:
|
|
okDialog(None,_("Cannot submit your report. Not connected to Internet?"))
|
|
#gtkEventThread.doQuit()
|
|
raise SystemExit(1)
|
|
|
|
|
|
|