1 #!/usr/bin/env python 2 3 CDDL = ''' 4 CDDL HEADER START 5 6 The contents of this file are subject to the terms of the 7 Common Development and Distribution License (the "License"). 8 You may not use this file except in compliance with the License. 9 10 You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 or http://www.opensolaris.org/os/licensing. 12 See the License for the specific language governing permissions 13 and limitations under the License. 14 15 When distributing Covered Code, include this CDDL HEADER in each 16 file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 If applicable, add the following below this CDDL HEADER, with the 18 fields enclosed by brackets "[]" replaced with your own identifying 19 information: Portions Copyright [yyyy] [name of copyright owner] 20 21 CDDL HEADER END 22 ''' 23 24 # 25 # Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26 # Use is subject to license terms. 27 # 28 # ident "%Z%%M% %I% %E% SMI" 29 # 30 31 # -*- coding: utf-8 -*- 32 33 ### Import section START 34 #-------------------------------------------------------------------------- 35 36 #Imports standard libraries 37 import getopt 38 import os 39 import sys 40 import time 41 import pango 42 import locale 43 import gettext 44 from threading import Thread 45 46 #Imports modules from PyGTK 47 try: 48 import pygtk 49 pygtk.require("2.0") 50 except: 51 pass 52 try: 53 import gobject 54 gobject.threads_init() 55 import gtk 56 import gtk.glade 57 except: 58 sys.exit(1) 59 60 #Imports modules from IPS 61 import pkg.catalog as catalog 62 import pkg.client.image as image 63 import pkg.client.progress as progress 64 65 import pkg.client.filelist as filelist 66 67 #Imports local modules 68 import pkg.gui.imageinfo as imageinfo 69 import pkg.gui.installupdate as installupdate 70 import pkg.gui.remove as remove 71 #import pkg.gui.packagemanagerconfig as packagemanagerconfig 72 import pkg.gui.enumerations as enumerations 73 import pkg.gui.userrights as userrights 74 75 #-------------------------------------------------------------------------- 76 ### Import section END 77 78 #-------------------------------------------------------------------------- 79 ### Init threads section END 80 81 class PackageManager: 82 #-------------------------------------------------------------------------- 83 def __init__(self): 84 pass 85 86 #-------------------------------------------------------------------------- 87 def N_(self, message): return message 88 89 #-------------------------------------------------------------------------- 90 def run_gui(self): 91 '''This method prepares all widgets and runs empty GUI''' 92 try: 93 self.application_dir = os.environ["PACKAGE_MANAGER_ROOT"] 94 except KeyError: 95 self.application_dir = "/" 96 locale.setlocale(locale.LC_ALL, '') 97 for module in (gettext, gtk.glade): 98 module.bindtextdomain("packagemanager",self.application_dir+"/usr/share/locale") 99 module.textdomain("packagemanager") 100 self._ = gettext.gettext 101 # self.pkgconfig = packagemanagerconfig.PackageManagerConfig() #Config 102 # self.pkgconfig.set_config_file_path(os.path.expanduser("~")+"/.packagemanager/config") #Config path 103 main_window_title = self._('Package Manager - revision 0.1') 104 rights = userrights.UserRights() 105 self.user_rights = rights.check_administrative_rights() 106 self.canceled = False # For background processes 107 self.preparing_list = True # 108 self.description_thread_running = False # For background processes 109 # self.pkginfo_canceled = False # For background processes 110 # self.pkginfo_thread_running = False # For background processes 111 self.pkginfo_thread = None # For background processes 112 gtk.rc_parse('~/.gtkrc-1.2-gnome2') # Load gtk theme 113 self.gladefile = self.application_dir + \ 114 "/usr/share/package-manager/packagemanager.glade" 115 self.wTree = gtk.glade.XML(self.gladefile, "mainwindow") 116 self.application_list = None #List for applications/main view 117 self.category_list = None #List for categories 118 self.section_list = None #List for sections 119 self.clipboard_text = None 120 self.create_models_lists() #Creates gtk.ListStore for models 121 self.pr = progress.NullProgressTracker() 122 try: 123 dic = self.declare_signals() 124 self.wTree.signal_autoconnect(dic) 125 except AttributeError, error: 126 print self._('GUI will not respond to any event! %s.Check declare_signals()')\ 127 % error 128 self.create_available_widgets() #Get widgets from glade file 129 self.update_reload_button() 130 131 self.clipboard.request_text(self.clipboard_text_received) 132 self.mainwindow.set_title(main_window_title) 133 self.init_tree_views() #Connects treeviews with models 134 self.init_sections() #Initiates sections 135 self.init_show_filter() #Initiates filter sections 136 self.mainwindow.show_all() 137 #TODO: Uncomment for testing dialog: 138 #self.installupdate.run() 139 #self.downloadpreferences.run() 140 #Switch to active in new thread. 141 #Thread(target=self.switch_to_active_valid_image, args=()).start() 142 143 #-------------------------------------------------------------------------- 144 def create_available_widgets(self): 145 '''Create available widgets''' 146 #Widnows 147 self.mainwindow = self.wTree.get_widget("mainwindow") 148 self.downloadingfiles = self.wTree.get_widget("downloadingfiles") 149 self.applyingchanges = self.wTree.get_widget("applyingchanges") 150 self.downloadpreferences1 = self.wTree.get_widget("downloadpreferences1") 151 self.downloadingpackageinformation = \ 152 self.wTree.get_widget("downloadingpackageinformation") 153 self.managerepositories = self.wTree.get_widget("managerepositories") 154 155 #Treeviews 156 self.applicationtreeview = self.wTree.get_widget("applicationtreeview") 157 self.categoriestreeview = self.wTree.get_widget("categoriestreeview") 158 159 #Textviews 160 self.generalinfotextview = self.wTree.get_widget("generalinfotextview") 161 self.installedfilestextview = self.wTree.get_widget("installedfilestextview") 162 self.dependenciestextview = self.wTree.get_widget("dependenciestextview") 163 164 #Labels 165 self.packagenamelabel = self.wTree.get_widget("packagenamelabel") 166 self.shortdescriptionlabel = \ 167 self.wTree.get_widget("shortdescriptionlabel") 168 #Search dialog 169 self.searchentrydialog = self.wTree.get_widget("searchentry") 170 171 #Buttons 172 self.install_update_button = self.wTree.get_widget("install_update_button") 173 self.remove_button = self.wTree.get_widget("remove_button") 174 self.update_all_button = self.wTree.get_widget("update_all_button") 175 self.reload_button = self.wTree.get_widget("reloadbutton") 176 177 #Other 178 self.repositorycombobox = self.wTree.get_widget("repositorycombobox") 179 self.sectionscombobox = self.wTree.get_widget("sectionscombobox") 180 self.filtercombobox = self.wTree.get_widget("filtercombobox") 181 self.packageimage = self.wTree.get_widget("packageimage") 182 self.statusbar = self.wTree.get_widget("statusbar") 183 184 #Menu 185 self.install_update_menu = self.wTree.get_widget("package_install_update") 186 self.remove_menu = self.wTree.get_widget("package_remove") 187 self.update_all_menu = self.wTree.get_widget("package_update_all") 188 self.cut_menu = self.wTree.get_widget("edit_cut") 189 self.copy_menu = self.wTree.get_widget("edit_copy") 190 self.paste_menu = self.wTree.get_widget("edit_paste") 191 self.clear_menu = self.wTree.get_widget("edit_clear") 192 self.select_all_menu = self.wTree.get_widget("edit_select_all") 193 self.select_updates_menu = self.wTree.get_widget("edit_select_updates") 194 self.deselect_menu = self.wTree.get_widget("edit_deselect") 195 196 #Clipboard 197 self.clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD) 198 199 #-------------------------------------------------------------------------- 200 def clipboard_text_received(self, clipboard, text, data): 201 self.clipboard_text = text 202 return 203 #-------------------------------------------------------------------------- 204 def init_tree_views(self): 205 '''This function connects treeviews with their models and also applies 206 filters''' 207 #TODO:1 Do we need to clear treeviews before appending columns? 208 #TODO:2 Do we need to have hidden columns with not shown information 209 #TODO:2 like objects, other lists or we can get those information from 210 #TODO:2 lists rather than models??? 211 #TODO:3 Make sure that not only name is sortable, other columns should be 212 #TODO:3 as well. Please refer to wireframes 213 #TODO:4 check if there should be some padding between columns or the names 214 #TODO:4 should have " name " instead of "name" 215 #TODO:5 compare with ipsgui what should be added, like row activated?? 216 ##APPLICATION MAIN TREEVIEW 217 self.application_list_filter = self.application_list.filter_new() 218 self.application_list_filter.set_visible_func(self.application_filter) 219 self.application_list_sort = \ 220 gtk.TreeModelSort(self.application_list_filter) 221 self.applicationtreeview.set_model(self.application_list_sort) 222 #enumerations.MARK_COLUMN 223 model = self.applicationtreeview.get_model() 224 toggle_renderer = gtk.CellRendererToggle() 225 toggle_renderer.connect('toggled', self.active_pane_toggle, model) 226 column = gtk.TreeViewColumn("", toggle_renderer, active=enumerations.MARK_COLUMN) 227 column.set_sort_column_id(enumerations.MARK_COLUMN) 228 column.set_sort_indicator(True) 229 column.set_cell_data_func(toggle_renderer, self.cell_data_function, None) 230 self.applicationtreeview.append_column(column) 231 #enumerations.STATUS_ICON_COLUMN 232 column = gtk.TreeViewColumn() 233 column.set_title("") 234 #Commented, since there was funny jumping of the icons 235 #column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) 236 render_pixbuf = gtk.CellRendererPixbuf() 237 column.pack_start(render_pixbuf, expand=False) 238 column.add_attribute(render_pixbuf, "pixbuf", enumerations.STATUS_ICON_COLUMN) 239 column.set_fixed_width(32) 240 column.set_cell_data_func(render_pixbuf, self.cell_data_function, None) 241 self.applicationtreeview.append_column(column) 242 #enumerations.ICON_COLUMN 243 column = gtk.TreeViewColumn() 244 column.set_title("") 245 #Commented, since there was funny jumping of the icons 246 #column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) 247 render_pixbuf = gtk.CellRendererPixbuf() 248 column.pack_start(render_pixbuf, expand=False) 249 column.add_attribute(render_pixbuf, "pixbuf", enumerations.ICON_COLUMN) 250 column.set_fixed_width(32) 251 column.set_cell_data_func(render_pixbuf, self.cell_data_function, None) 252 self.applicationtreeview.append_column(column) 253 #enumerations.NAME_COLUMN 254 name_renderer = gtk.CellRendererText() 255 column = gtk.TreeViewColumn(self._("Name"), name_renderer, \ 256 text=enumerations.NAME_COLUMN) 257 column.set_sort_column_id(enumerations.NAME_COLUMN) 258 column.set_sort_indicator(True) 259 column.set_cell_data_func(name_renderer, self.cell_data_function, None) 260 self.applicationtreeview.append_column(column) 261 #enumerations.INSTALLED_VERSION_COLUMN 262 installed_version_renderer = gtk.CellRendererText() 263 column = gtk.TreeViewColumn(self._('Installed Version'), \ 264 installed_version_renderer, text=enumerations.INSTALLED_VERSION_COLUMN) 265 column.set_cell_data_func(installed_version_renderer, self.cell_data_function, None) 266 self.applicationtreeview.append_column(column) 267 #enumerations.LATEST_AVAILABLE_COLUMN 268 latest_available_renderer = gtk.CellRendererText() 269 column = gtk.TreeViewColumn(self._('Latest Version'), \ 270 latest_available_renderer, text=enumerations.LATEST_AVAILABLE_COLUMN) 271 column.set_cell_data_func(latest_available_renderer, self.cell_data_function, None) 272 self.applicationtreeview.append_column(column) 273 #enumerations.RATING_COLUMN 274 rating_renderer = gtk.CellRendererText() 275 column = gtk.TreeViewColumn(self._('Rating'), rating_renderer, text=enumerations.RATING_COLUMN) 276 column.set_cell_data_func(rating_renderer, self.cell_data_function, None) 277 #TODO: Rating column hidden 278 #self.applicationtreeview.append_column(column) 279 #enumerations.DESCRIPTION_COLUMN 280 description_renderer = gtk.CellRendererText() 281 column = gtk.TreeViewColumn(self._('Description'), description_renderer, \ 282 text=enumerations.DESCRIPTION_COLUMN) 283 column.set_cell_data_func(description_renderer, self.cell_data_function, None) 284 self.applicationtreeview.append_column(column) 285 286 #Added selection listener 287 self.package_selection = self.applicationtreeview.get_selection() 288 self.package_selection.set_mode(gtk.SELECTION_SINGLE) 289 self.package_selection.connect("changed", self.on_package_selection_changed, 290 None) 291 292 ##CATEGORIES TREEVIEW 293 #enumerations.CATEGORY_NAME 294 295 self.category_list_filter = self.category_list.filter_new() 296 self.category_list_filter.set_visible_func(self.category_filter)#, 297 #self.category_list) 298 self.categoriestreeview.set_model(self.category_list_filter) 299 enumerations.CATEGORY_NAME_renderer = gtk.CellRendererText() 300 column = gtk.TreeViewColumn(self._('Name'), enumerations.CATEGORY_NAME_renderer, \ 301 text=enumerations.CATEGORY_NAME) 302 self.categoriestreeview.append_column(column) 303 304 #Added selection listener 305 self.category_selection = self.categoriestreeview.get_selection() 306 self.category_selection.set_mode(gtk.SELECTION_SINGLE) 307 self.category_selection.connect("changed", self.on_category_selection_changed, 308 None) 309 310 ##SECTION COMBOBOX 311 #enumerations.SECTION_NAME 312 self.sectionscombobox.set_model(self.section_list) 313 cell = gtk.CellRendererText() 314 self.sectionscombobox.pack_start(cell, True) 315 self.sectionscombobox.add_attribute(cell, 'text', enumerations.SECTION_NAME) 316 self.sectionscombobox.set_row_separator_func(self.combobox_separator) 317 318 ##FILTER COMBOBOX 319 #enumerations.FILTER_NAME 320 self.filtercombobox.set_model(self.filter_list) 321 cell = gtk.CellRendererText() 322 self.filtercombobox.pack_start(cell, True) 323 self.filtercombobox.add_attribute(cell, 'text', enumerations.FILTER_NAME) 324 self.filtercombobox.set_row_separator_func(self.combobox_separator) 325 326 ##FILTER COMBOBOX 327 #enumerations.FILTER_NAME 328 self.repositorycombobox.set_model(self.repositories_list) 329 cell = gtk.CellRendererText() 330 self.repositorycombobox.pack_start(cell, True) 331 self.repositorycombobox.add_attribute(cell, 'text', enumerations.REPOSITORY_NAME) 332 self.repositorycombobox.set_row_separator_func(self.combobox_separator) 333 334 335 #-------------------------------------------------------------------------- 336 def on_mainwindow_delete_event(self,widget, event): 337 ''' handler for delete event of the main window ''' 338 if self.check_if_something_was_changed() == True: 339 #TODO: Change this to not quit and show dialog 340 #TODO: if some changes were applied: 341 self.main_application_quit() 342 return True 343 else: 344 self.main_application_quit() 345 #-------------------------------------------------------------------------- 346 def download_pref_close_clicked(self,widget): 347 self.downloadpreferences.destroy() 348 #-------------------------------------------------------------------------- 349 def on_file_quit_activate(self,widget): 350 ''' handler for quit menu event ''' 351 self.on_mainwindow_delete_event(None,None) 352 353 def downloadpreferences_delete_event(self,widget,event): 354 self.downloadpreferences.destroy() 355 356 #-------------------------------------------------------------------------- 357 def on_settings_download_preferences_activate(self,widget): 358 ''' handler for quit menu event ''' 359 wTree = gtk.glade.XML(self.gladefile, "downloadpreferences") 360 self.downloadpreferences = wTree.get_widget("downloadpreferences") 361 self.arch = wTree.get_widget("arch_1") 362 self.debug = wTree.get_widget("debug_1") 363 self.arch_2 = wTree.get_widget("arch_2") 364 self.debug_2 = wTree.get_widget("debug_2") 365 self.download_pref_reset_clicked(None) 366 367 dic = { 368 #downloadpreferences signals 369 "download_pref_close_clicked":\ 370 self.download_pref_close_clicked, 371 "downloadpreferences_delete_event":\ 372 self.downloadpreferences_delete_event, 373 "download_pref_reset_clicked":\ 374 self.download_pref_reset_clicked, 375 } 376 wTree.signal_autoconnect(dic) 377 self.downloadpreferences.run() 378 379 #-------------------------------------------------------------------------- 380 def download_pref_reset_clicked(self,widget): 381 #TODO: Not for rev 1 382 return 383 #config_attribute = self.pkgconfig.get_list_of_config_attributes() 384 #arch = config_attribute.get('arch') 385 #debug = config_attribute.get('debug') 386 #if cmp(arch,"sparc") == 0: 387 # self.arch.set_active(True) 388 389 #if cmp(debug,"True") == 0: 390 # self.debug.set_active(True) 391 392 #if not arch: 393 # self.arch.set_active(True) 394 395 #if not debug: 396 # self.debug.set_active(True) 397 398 #-------------------------------------------------------------------------- 399 def main_application_quit(self): 400 '''quits the main gtk loop''' 401 self.canceled = True 402 gtk.main_quit() 403 sys.exit(0) 404 return True 405 #-------------------------------------------------------------------------- 406 def check_if_something_was_changed(self): 407 ''' Returns True if any of the check boxes for package was changed, false 408 if not''' 409 for pkg in self.application_list: 410 if pkg[enumerations.MARK_COLUMN] == True: 411 return True 412 return False 413 #-------------------------------------------------------------------------- 414 def cell_data_function(self, column, renderer, model, iter, data): 415 '''Function which sets the background colour to black if package is 416 selected''' 417 if iter: 418 if model.get_value(iter, enumerations.MARK_COLUMN): 419 renderer.set_property("cell-background", "#ffe5cc") 420 renderer.set_property("cell-background-set", True) 421 else: 422 renderer.set_property("cell-background-set", False) 423 424 #-------------------------------------------------------------------------- 425 def combobox_separator(self,model,iter): 426 return model.get_value(iter,enumerations.FILTER_NAME) == "" 427 #-------------------------------------------------------------------------- 428 def set_visible_packages_from_category(self,category): 429 '''Sets all packages as visible from category''' 430 if not category: 431 return 432 pkglist = category[PACKAGE_LIST_OBJECT]; 433 if pkglist: 434 for pkg in pkglist: 435 pkg[enumerations.IS_VISIBLE_COLUMN] = True 436 #-------------------------------------------------------------------------- 437 def init_sections(self): 438 '''This function is for initializing sections combo box, also adds "All" 439 Category. It sets active section combobox entry "All"''' 440 self.section_list.append([self._('All'),]) 441 self.section_list.append(["",]) 442 self.section_list.append([self._('Meta Packages'),]) 443 self.section_list.append([self._('Applications Desktop'),]) 444 self.section_list.append([self._('Applications Web-Based'),]) 445 self.section_list.append([self._('Operating System'),]) 446 self.section_list.append([self._('User Environment'),]) 447 self.section_list.append([self._('Web Infrastructure'),]) 448 self.category_list.append([self._('All'),None,None,True,None]) 449 self.sectionscombobox.set_active(0) 450 #-------------------------------------------------------------------------- 451 def init_show_filter(self): 452 self.filter_list.append([self._('All Packages'),]) 453 self.filter_list.append(["",]) 454 self.filter_list.append([self._('Installed Packages'),]) 455 self.filter_list.append([self._('Updates'),]) 456 self.filter_list.append(["",]) 457 # self.filter_list.append([self._('Locked Packages'),]) 458 # self.filter_list.append(["",]) 459 self.filter_list.append([self._('Selected Packages'),]) 460 self.filtercombobox.set_active(0) 461 #-------------------------------------------------------------------------- 462 def setup_repositories_combobox(self,image): 463 repositories = image.catalogs 464 default_authority = image.get_default_authority() 465 self.repositories_list.clear() 466 i = 0 467 active = 0 468 for repo in repositories: 469 if cmp(repo,default_authority) == 0: 470 active = i 471 i = i+1 472 self.repositories_list.append([repo,]) 473 if default_authority: 474 self.repositorycombobox.set_active(active) 475 else: 476 self.repositorycombobox.set_active(0) 477 #-------------------------------------------------------------------------- 478 def active_pane_toggle(self, cell, path, model_sort): 479 '''Toggle function for column enumerations.MARK_COLUMN''' 480 applicationModel = model_sort.get_model() 481 applicationPath = model_sort.convert_path_to_child_path(path) 482 filterModel = applicationModel.get_model() 483 child_path = applicationModel.convert_path_to_child_path(applicationPath) 484 iter = filterModel.get_iter(child_path) 485 if iter: 486 modified = filterModel.get_value(iter, enumerations.MARK_COLUMN) 487 filterModel.set_value(iter,enumerations.MARK_COLUMN,not modified) 488 latest_available = filterModel.get_value(iter, enumerations.LATEST_AVAILABLE_COLUMN) 489 installed_available = filterModel.get_value(iter, enumerations.INSTALLED_VERSION_COLUMN) 490 self.update_statusbar() 491 self.update_install_update_button(latest_available,modified) 492 self.update_remove_button(installed_available,modified) 493 self.enable_disable_selection_menus() 494 #-------------------------------------------------------------------------- 495 def update_install_update_button(self, latest_available, toggle_true): 496 if not toggle_true and self.user_rights: 497 if latest_available: 498 self.install_update_button.set_sensitive(True) 499 self.install_update_menu.set_sensitive(True) 500 else: 501 available = None 502 for row in self.application_list: 503 if row[enumerations.MARK_COLUMN]: 504 available = row[enumerations.LATEST_AVAILABLE_COLUMN] 505 if available: 506 return 507 if not available: 508 self.install_update_button.set_sensitive(False) 509 self.install_update_menu.set_sensitive(False) 510 511 #-------------------------------------------------------------------------- 512 def update_reload_button(self): 513 if self.user_rights: 514 self.reload_button.set_sensitive(True) 515 else: 516 self.reload_button.set_sensitive(False) 517 518 #-------------------------------------------------------------------------- 519 def update_remove_button(self, installed_available, toggle_true): 520 if not toggle_true and self.user_rights: 521 if installed_available: 522 self.remove_button.set_sensitive(True) 523 self.remove_menu.set_sensitive(True) 524 else: 525 available = None 526 for row in self.application_list: 527 if row[enumerations.MARK_COLUMN]: 528 installed = row[enumerations.INSTALLED_VERSION_COLUMN] 529 if installed: 530 return 531 if not available: 532 self.remove_button.set_sensitive(False) 533 self.remove_menu.set_sensitive(False) 534 535 #-------------------------------------------------------------------------- 536 def update_statusbar(self): 537 '''Function which updates statusbar''' 538 539 installed = 0 540 selected = 0 541 broken = 0 542 for pkg in self.application_list: 543 if pkg[enumerations.INSTALLED_VERSION_COLUMN]: 544 installed = installed + 1 545 if pkg[enumerations.MARK_COLUMN]: 546 selected = selected + 1 547 548 listed_str = self._('%d packages listed') % len(self.application_list) 549 inst_str = self._('%d installed') % installed 550 sel_str = self._('%d selected') % selected 551 broken_str = self._('%d broken') % broken 552 553 self.statusbar.push(0,listed_str + ', ' + inst_str + ', ' + sel_str +\ 554 ', ' + broken_str + '.') 555 556 #-------------------------------------------------------------------------- 557 def update_package_list(self): 558 for row in self.application_list: 559 if row[enumerations.MARK_COLUMN]: 560 image = row[enumerations.IMAGE_OBJECT_COLUMN] 561 pkg = max(row[enumerations.PACKAGE_OBJECT_COLUMN]) 562 package_installed = self.get_installed_version(image,pkg) 563 version_installed = None 564 if package_installed: 565 version_installed = package_installed.version.get_short_version() 566 567 row[enumerations.MARK_COLUMN] = False 568 row[enumerations.STATUS_ICON_COLUMN] = None 569 row[enumerations.INSTALLED_VERSION_COLUMN] = version_installed 570 row[enumerations.INSTALLED_OBJECT_COLUMN] = package_installed 571 if not package_installed: 572 dt = self.get_datetime(pkg.version) 573 dt_str = (":%02d%02d") % (dt.month,dt.day) 574 available_version = pkg.version.get_short_version()+dt_str 575 row[enumerations.LATEST_AVAILABLE_COLUMN] = available_version 576 else: 577 row[enumerations.LATEST_AVAILABLE_COLUMN] = None 578 579 self.install_update_button.set_sensitive(False) 580 self.install_update_menu.set_sensitive(False) 581 self.remove_button.set_sensitive(False) 582 self.remove_menu.set_sensitive(False) 583 self.enable_disable_selection_menus() 584 self.update_statusbar() 585 #-------------------------------------------------------------------------- 586 def get_datetime(self,version): 587 dt = None 588 try: 589 dt = version.get_datetime() 590 except AttributeError: 591 dt = version.get_timestamp() 592 return dt 593 #-------------------------------------------------------------------------- 594 def on_searchentry_changed(self,widget): 595 '''On text search field changed we should refilter the main view''' 596 Thread(target=self.on_searchentry_threaded, args=()).start() 597 #self.application_list_filter.refilter() 598 599 def on_searchentry_threaded(self): 600 gobject.idle_add(self.application_list_filter.refilter) 601 gobject.idle_add(self.enable_disable_selection_menus) 602 603 #-------------------------------------------------------------------------- 604 def on_edit_paste(self,widget): 605 self.searchentrydialog.insert_text(self.clipboard_text,self.searchentrydialog.get_position()) 606 607 #-------------------------------------------------------------------------- 608 def on_clear_paste(self,widget): 609 bounds = self.searchentrydialog.get_selection_bounds() 610 text = self.searchentrydialog.get_chars(bounds[0],bounds[1]) 611 self.searchentrydialog.delete_text(bounds[0],bounds[1]) 612 return 613 #-------------------------------------------------------------------------- 614 def on_copy(self,widget): 615 bounds = self.searchentrydialog.get_selection_bounds() 616 text = self.searchentrydialog.get_chars(bounds[0],bounds[1]) 617 self.clipboard.set_text(text) 618 return 619 #-------------------------------------------------------------------------- 620 def on_cut(self,widget): 621 bounds = self.searchentrydialog.get_selection_bounds() 622 text = self.searchentrydialog.get_chars(bounds[0],bounds[1]) 623 self.searchentrydialog.delete_text(bounds[0],bounds[1]) 624 self.clipboard.set_text(text) 625 return 626 #-------------------------------------------------------------------------- 627 def on_select_all(self,widget): 628 sort_filt_model = self.applicationtreeview.get_model() #gtk.TreeModelSort 629 filt_model = sort_filt_model.get_model() #gtk.TreeModelFilter