1# -*- coding: utf-8 -*- 2# 3# Copyright (C) 2011 Nick Lanham <nick@afternight.org> 4# 5# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with 6# the additional special exception to link portions of this program with the OpenSSL library. 7# See LICENSE for more details. 8# 9 10from __future__ import unicode_literals 11 12import logging 13 14from deluge.common import is_ip 15from deluge.decorators import overrides 16from deluge.i18n import get_languages 17from deluge.ui.client import client 18from deluge.ui.common import DISK_CACHE_KEYS 19from deluge.ui.console.widgets import BaseInputPane, BaseWindow 20from deluge.ui.console.widgets.fields import FloatSpinInput, TextInput 21from deluge.ui.console.widgets.popup import PopupsHandler 22 23log = logging.getLogger(__name__) 24 25 26class BasePreferencePane(BaseInputPane, BaseWindow, PopupsHandler): 27 def __init__(self, name, preferences): 28 PopupsHandler.__init__(self) 29 self.preferences = preferences 30 BaseWindow.__init__( 31 self, 32 '%s' % name, 33 self.pane_width, 34 preferences.height, 35 posy=1, 36 posx=self.pane_x_pos, 37 ) 38 BaseInputPane.__init__(self, preferences, border_off_east=1) 39 self.name = name 40 41 # have we scrolled down in the list 42 self.input_offset = 0 43 44 @overrides(BaseInputPane) 45 def handle_read(self, c): 46 if self.popup: 47 ret = self.popup.handle_read(c) 48 if self.popup and self.popup.closed(): 49 self.pop_popup() 50 self.refresh() 51 return ret 52 return BaseInputPane.handle_read(self, c) 53 54 @property 55 def visible_content_pane_height(self): 56 y, x = self.visible_content_pane_size 57 return y 58 59 @property 60 def pane_x_pos(self): 61 return self.preferences.sidebar_width 62 63 @property 64 def pane_width(self): 65 return self.preferences.width 66 67 @property 68 def cols(self): 69 return self.pane_width 70 71 @property 72 def rows(self): 73 return self.preferences.height 74 75 def is_active_pane(self): 76 return self.preferences.is_active_pane(self) 77 78 def create_pane(self, core_conf, console_config): 79 pass 80 81 def add_config_values(self, conf_dict): 82 for ipt in self.inputs: 83 if ipt.has_input(): 84 # Need special cases for in/out ports or proxy since they are tuples or dicts. 85 if ipt.name == 'listen_ports_to' or ipt.name == 'listen_ports_from': 86 conf_dict['listen_ports'] = ( 87 self.infrom.get_value(), 88 self.into.get_value(), 89 ) 90 elif ipt.name == 'out_ports_to' or ipt.name == 'out_ports_from': 91 conf_dict['outgoing_ports'] = ( 92 self.outfrom.get_value(), 93 self.outto.get_value(), 94 ) 95 elif ipt.name == 'listen_interface': 96 listen_interface = ipt.get_value().strip() 97 if is_ip(listen_interface) or not listen_interface: 98 conf_dict['listen_interface'] = listen_interface 99 elif ipt.name == 'outgoing_interface': 100 outgoing_interface = ipt.get_value().strip() 101 conf_dict['outgoing_interface'] = outgoing_interface 102 elif ipt.name.startswith('proxy_'): 103 if ipt.name == 'proxy_type': 104 conf_dict.setdefault('proxy', {})['type'] = ipt.get_value() 105 elif ipt.name == 'proxy_username': 106 conf_dict.setdefault('proxy', {})['username'] = ipt.get_value() 107 elif ipt.name == 'proxy_password': 108 conf_dict.setdefault('proxy', {})['password'] = ipt.get_value() 109 elif ipt.name == 'proxy_hostname': 110 conf_dict.setdefault('proxy', {})['hostname'] = ipt.get_value() 111 elif ipt.name == 'proxy_port': 112 conf_dict.setdefault('proxy', {})['port'] = ipt.get_value() 113 elif ipt.name == 'proxy_hostnames': 114 conf_dict.setdefault('proxy', {})[ 115 'proxy_hostnames' 116 ] = ipt.get_value() 117 elif ipt.name == 'proxy_peer_connections': 118 conf_dict.setdefault('proxy', {})[ 119 'proxy_peer_connections' 120 ] = ipt.get_value() 121 elif ipt.name == 'proxy_tracker_connections': 122 conf_dict.setdefault('proxy', {})[ 123 'proxy_tracker_connections' 124 ] = ipt.get_value() 125 elif ipt.name == 'force_proxy': 126 conf_dict.setdefault('proxy', {})['force_proxy'] = ipt.get_value() 127 elif ipt.name == 'anonymous_mode': 128 conf_dict.setdefault('proxy', {})[ 129 'anonymous_mode' 130 ] = ipt.get_value() 131 else: 132 conf_dict[ipt.name] = ipt.get_value() 133 134 if hasattr(ipt, 'get_child'): 135 c = ipt.get_child() 136 conf_dict[c.name] = c.get_value() 137 138 def update_values(self, conf_dict): 139 for ipt in self.inputs: 140 if ipt.has_input(): 141 try: 142 ipt.set_value(conf_dict[ipt.name]) 143 except KeyError: # just ignore if it's not in dict 144 pass 145 if hasattr(ipt, 'get_child'): 146 try: 147 c = ipt.get_child() 148 c.set_value(conf_dict[c.name]) 149 except KeyError: # just ignore if it's not in dict 150 pass 151 152 def render(self, mode, screen, width, focused): 153 height = self.get_content_height() 154 self.ensure_content_pane_height(height) 155 self.screen.erase() 156 157 if focused and self.active_input == -1: 158 self.move_active_down(1) 159 160 self.render_inputs(focused=focused) 161 162 @overrides(BaseWindow) 163 def refresh(self): 164 BaseWindow.refresh(self) 165 if self.popup: 166 self.popup.refresh() 167 168 def update(self, active): 169 pass 170 171 172class InterfacePane(BasePreferencePane): 173 def __init__(self, preferences): 174 BasePreferencePane.__init__(self, ' %s ' % _('Interface'), preferences) 175 176 @overrides(BasePreferencePane) 177 def create_pane(self, core_conf, console_config): 178 self.add_header(_('General options')) 179 180 self.add_checked_input( 181 'ring_bell', 182 _('Ring system bell when a download finishes'), 183 console_config['ring_bell'], 184 ) 185 self.add_header('Console UI', space_above=True) 186 self.add_checked_input( 187 'separate_complete', 188 _('List complete torrents after incomplete regardless of sorting order'), 189 console_config['torrentview']['separate_complete'], 190 ) 191 self.add_checked_input( 192 'move_selection', 193 _('Move selection when moving torrents in the queue'), 194 console_config['torrentview']['move_selection'], 195 ) 196 197 langs = get_languages() 198 langs.insert(0, ('', 'System Default')) 199 self.add_combo_input( 200 'language', _('Language'), langs, default=console_config['language'] 201 ) 202 self.add_header(_('Command Line Mode'), space_above=True) 203 self.add_checked_input( 204 'ignore_duplicate_lines', 205 _('Do not store duplicate input in history'), 206 console_config['cmdline']['ignore_duplicate_lines'], 207 ) 208 self.add_checked_input( 209 'save_command_history', 210 _('Store and load command line history in command line mode'), 211 console_config['cmdline']['save_command_history'], 212 ) 213 self.add_header('') 214 self.add_checked_input( 215 'third_tab_lists_all', 216 _('Third tab lists all remaining torrents in command line mode'), 217 console_config['cmdline']['third_tab_lists_all'], 218 ) 219 self.add_int_spin_input( 220 'torrents_per_tab_press', 221 _('Torrents per tab press'), 222 console_config['cmdline']['torrents_per_tab_press'], 223 min_val=5, 224 max_val=10000, 225 ) 226 227 228class DownloadsPane(BasePreferencePane): 229 def __init__(self, preferences): 230 BasePreferencePane.__init__(self, ' %s ' % _('Downloads'), preferences) 231 232 @overrides(BasePreferencePane) 233 def create_pane(self, core_conf, console_config): 234 self.add_header(_('Folders')) 235 self.add_text_input( 236 'download_location', 237 '%s:' % _('Download To'), 238 core_conf['download_location'], 239 complete=True, 240 activate_input=True, 241 col='+1', 242 ) 243 cmptxt = TextInput( 244 self.preferences, 245 'move_completed_path', 246 None, 247 self.move, 248 self.pane_width, 249 core_conf['move_completed_path'], 250 False, 251 ) 252 self.add_checkedplus_input( 253 'move_completed', 254 '%s:' % _('Move completed to'), 255 cmptxt, 256 core_conf['move_completed'], 257 ) 258 copytxt = TextInput( 259 self.preferences, 260 'torrentfiles_location', 261 None, 262 self.move, 263 self.pane_width, 264 core_conf['torrentfiles_location'], 265 False, 266 ) 267 self.add_checkedplus_input( 268 'copy_torrent_file', 269 '%s:' % _('Copy of .torrent files to'), 270 copytxt, 271 core_conf['copy_torrent_file'], 272 ) 273 self.add_checked_input( 274 'del_copy_torrent_file', 275 _('Delete copy of torrent file on remove'), 276 core_conf['del_copy_torrent_file'], 277 ) 278 279 self.add_header(_('Options'), space_above=True) 280 self.add_checked_input( 281 'prioritize_first_last_pieces', 282 ('Prioritize first and last pieces of torrent'), 283 core_conf['prioritize_first_last_pieces'], 284 ) 285 self.add_checked_input( 286 'sequential_download', 287 _('Sequential download'), 288 core_conf['sequential_download'], 289 ) 290 self.add_checked_input('add_paused', _('Add Paused'), core_conf['add_paused']) 291 self.add_checked_input( 292 'pre_allocate_storage', 293 _('Pre-Allocate disk space'), 294 core_conf['pre_allocate_storage'], 295 ) 296 297 298class NetworkPane(BasePreferencePane): 299 def __init__(self, preferences): 300 BasePreferencePane.__init__(self, ' %s ' % _('Network'), preferences) 301 302 @overrides(BasePreferencePane) 303 def create_pane(self, core_conf, console_config): 304 self.add_header(_('Incomming Ports')) 305 inrand = self.add_checked_input( 306 'random_port', 307 'Use Random Ports Active Port: %d' % self.preferences.active_port, 308 core_conf['random_port'], 309 ) 310 listen_ports = core_conf['listen_ports'] 311 self.infrom = self.add_int_spin_input( 312 'listen_ports_from', 313 ' %s:' % _('From'), 314 value=listen_ports[0], 315 min_val=0, 316 max_val=65535, 317 ) 318 self.infrom.set_depend(inrand, inverse=True) 319 self.into = self.add_int_spin_input( 320 'listen_ports_to', 321 ' %s:' % _('To'), 322 value=listen_ports[1], 323 min_val=0, 324 max_val=65535, 325 ) 326 self.into.set_depend(inrand, inverse=True) 327 328 self.add_header(_('Outgoing Ports'), space_above=True) 329 outrand = self.add_checked_input( 330 'random_outgoing_ports', 331 _('Use Random Ports'), 332 core_conf['random_outgoing_ports'], 333 ) 334 out_ports = core_conf['outgoing_ports'] 335 self.outfrom = self.add_int_spin_input( 336 'out_ports_from', 337 ' %s:' % _('From'), 338 value=out_ports[0], 339 min_val=0, 340 max_val=65535, 341 ) 342 self.outfrom.set_depend(outrand, inverse=True) 343 self.outto = self.add_int_spin_input( 344 'out_ports_to', 345 ' %s:' % _('To'), 346 value=out_ports[1], 347 min_val=0, 348 max_val=65535, 349 ) 350 self.outto.set_depend(outrand, inverse=True) 351 352 self.add_header(_('Incoming Interface'), space_above=True) 353 self.add_text_input( 354 'listen_interface', 355 _('IP address of the interface to listen on (leave empty for default):'), 356 core_conf['listen_interface'], 357 ) 358 359 self.add_header(_('Outgoing Interface'), space_above=True) 360 self.add_text_input( 361 'outgoing_interface', 362 _( 363 'The network interface name or IP address for outgoing ' 364 'BitTorrent connections. (Leave empty for default.):' 365 ), 366 core_conf['outgoing_interface'], 367 ) 368 369 self.add_header('TOS', space_above=True) 370 self.add_text_input('peer_tos', 'Peer TOS Byte:', core_conf['peer_tos']) 371 372 self.add_header(_('Network Extras'), space_above=True) 373 self.add_checked_input('upnp', 'UPnP', core_conf['upnp']) 374 self.add_checked_input('natpmp', 'NAT-PMP', core_conf['natpmp']) 375 self.add_checked_input('utpex', 'Peer Exchange', core_conf['utpex']) 376 self.add_checked_input('lsd', 'LSD', core_conf['lsd']) 377 self.add_checked_input('dht', 'DHT', core_conf['dht']) 378 379 self.add_header(_('Encryption'), space_above=True) 380 self.add_select_input( 381 'enc_in_policy', 382 '%s:' % _('Inbound'), 383 [_('Forced'), _('Enabled'), _('Disabled')], 384 [0, 1, 2], 385 core_conf['enc_in_policy'], 386 active_default=True, 387 col='+1', 388 ) 389 self.add_select_input( 390 'enc_out_policy', 391 '%s:' % _('Outbound'), 392 [_('Forced'), _('Enabled'), _('Disabled')], 393 [0, 1, 2], 394 core_conf['enc_out_policy'], 395 active_default=True, 396 ) 397 self.add_select_input( 398 'enc_level', 399 '%s:' % _('Level'), 400 [_('Handshake'), _('Full Stream'), _('Either')], 401 [0, 1, 2], 402 core_conf['enc_level'], 403 active_default=True, 404 ) 405 406 407class BandwidthPane(BasePreferencePane): 408 def __init__(self, preferences): 409 BasePreferencePane.__init__(self, ' %s ' % _('Bandwidth'), preferences) 410 411 @overrides(BasePreferencePane) 412 def create_pane(self, core_conf, console_config): 413 self.add_header(_('Global Bandwidth Usage')) 414 self.add_int_spin_input( 415 'max_connections_global', 416 '%s:' % _('Maximum Connections'), 417 core_conf['max_connections_global'], 418 min_val=-1, 419 max_val=9000, 420 ) 421 self.add_int_spin_input( 422 'max_upload_slots_global', 423 '%s:' % _('Maximum Upload Slots'), 424 core_conf['max_upload_slots_global'], 425 min_val=-1, 426 max_val=9000, 427 ) 428 self.add_float_spin_input( 429 'max_download_speed', 430 '%s:' % _('Maximum Download Speed (KiB/s)'), 431 core_conf['max_download_speed'], 432 min_val=-1.0, 433 max_val=60000.0, 434 ) 435 self.add_float_spin_input( 436 'max_upload_speed', 437 '%s:' % _('Maximum Upload Speed (KiB/s)'), 438 core_conf['max_upload_speed'], 439 min_val=-1.0, 440 max_val=60000.0, 441 ) 442 self.add_int_spin_input( 443 'max_half_open_connections', 444 '%s:' % _('Maximum Half-Open Connections'), 445 core_conf['max_half_open_connections'], 446 min_val=-1, 447 max_val=9999, 448 ) 449 self.add_int_spin_input( 450 'max_connections_per_second', 451 '%s:' % _('Maximum Connection Attempts per Second'), 452 core_conf['max_connections_per_second'], 453 min_val=-1, 454 max_val=9999, 455 ) 456 self.add_checked_input( 457 'ignore_limits_on_local_network', 458 _('Ignore limits on local network'), 459 core_conf['ignore_limits_on_local_network'], 460 ) 461 self.add_checked_input( 462 'rate_limit_ip_overhead', 463 _('Rate Limit IP Overhead'), 464 core_conf['rate_limit_ip_overhead'], 465 ) 466 self.add_header(_('Per Torrent Bandwidth Usage'), space_above=True) 467 self.add_int_spin_input( 468 'max_connections_per_torrent', 469 '%s:' % _('Maximum Connections'), 470 core_conf['max_connections_per_torrent'], 471 min_val=-1, 472 max_val=9000, 473 ) 474 self.add_int_spin_input( 475 'max_upload_slots_per_torrent', 476 '%s:' % _('Maximum Upload Slots'), 477 core_conf['max_upload_slots_per_torrent'], 478 min_val=-1, 479 max_val=9000, 480 ) 481 self.add_float_spin_input( 482 'max_download_speed_per_torrent', 483 '%s:' % _('Maximum Download Speed (KiB/s)'), 484 core_conf['max_download_speed_per_torrent'], 485 min_val=-1.0, 486 max_val=60000.0, 487 ) 488 self.add_float_spin_input( 489 'max_upload_speed_per_torrent', 490 '%s:' % _('Maximum Upload Speed (KiB/s)'), 491 core_conf['max_upload_speed_per_torrent'], 492 min_val=-1.0, 493 max_val=60000.0, 494 ) 495 496 497class OtherPane(BasePreferencePane): 498 def __init__(self, preferences): 499 BasePreferencePane.__init__(self, ' %s ' % _('Other'), preferences) 500 501 @overrides(BasePreferencePane) 502 def create_pane(self, core_conf, console_config): 503 self.add_header(_('System Information')) 504 self.add_info_field('info1', ' Help us improve Deluge by sending us your', '') 505 self.add_info_field( 506 'info2', ' Python version, PyGTK version, OS and processor', '' 507 ) 508 self.add_info_field( 509 'info3', ' types. Absolutely no other information is sent.', '' 510 ) 511 self.add_checked_input( 512 'send_info', 513 _('Yes, please send anonymous statistics.'), 514 core_conf['send_info'], 515 ) 516 self.add_header(_('GeoIP Database'), space_above=True) 517 self.add_text_input( 518 'geoip_db_location', 'Location:', core_conf['geoip_db_location'] 519 ) 520 521 522class DaemonPane(BasePreferencePane): 523 def __init__(self, preferences): 524 BasePreferencePane.__init__(self, ' %s ' % _('Daemon'), preferences) 525 526 @overrides(BasePreferencePane) 527 def create_pane(self, core_conf, console_config): 528 self.add_header('Port') 529 self.add_int_spin_input( 530 'daemon_port', 531 '%s:' % _('Daemon Port'), 532 core_conf['daemon_port'], 533 min_val=0, 534 max_val=65535, 535 ) 536 self.add_header('Connections', space_above=True) 537 self.add_checked_input( 538 'allow_remote', _('Allow remote connections'), core_conf['allow_remote'] 539 ) 540 self.add_header('Other', space_above=True) 541 self.add_checked_input( 542 'new_release_check', 543 _('Periodically check the website for new releases'), 544 core_conf['new_release_check'], 545 ) 546 547 548class QueuePane(BasePreferencePane): 549 def __init__(self, preferences): 550 BasePreferencePane.__init__(self, ' %s ' % _('Queue'), preferences) 551 552 @overrides(BasePreferencePane) 553 def create_pane(self, core_conf, console_config): 554 self.add_header(_('New Torrents')) 555 self.add_checked_input( 556 'queue_new_to_top', _('Queue to top'), core_conf['queue_new_to_top'] 557 ) 558 self.add_header(_('Active Torrents'), True) 559 self.add_int_spin_input( 560 'max_active_limit', 561 '%s:' % _('Total'), 562 core_conf['max_active_limit'], 563 min_val=-1, 564 max_val=9999, 565 ) 566 self.add_int_spin_input( 567 'max_active_downloading', 568 '%s:' % _('Downloading'), 569 core_conf['max_active_downloading'], 570 min_val=-1, 571 max_val=9999, 572 ) 573 self.add_int_spin_input( 574 'max_active_seeding', 575 '%s:' % _('Seeding'), 576 core_conf['max_active_seeding'], 577 min_val=-1, 578 max_val=9999, 579 ) 580 self.add_checked_input( 581 'dont_count_slow_torrents', 582 'Ignore slow torrents', 583 core_conf['dont_count_slow_torrents'], 584 ) 585 self.add_checked_input( 586 'auto_manage_prefer_seeds', 587 'Prefer seeding torrents', 588 core_conf['auto_manage_prefer_seeds'], 589 ) 590 self.add_header(_('Seeding Rotation'), space_above=True) 591 self.add_float_spin_input( 592 'share_ratio_limit', 593 '%s:' % _('Share Ratio'), 594 core_conf['share_ratio_limit'], 595 precision=2, 596 min_val=-1.0, 597 max_val=100.0, 598 ) 599 self.add_float_spin_input( 600 'seed_time_ratio_limit', 601 '%s:' % _('Time Ratio'), 602 core_conf['seed_time_ratio_limit'], 603 precision=2, 604 min_val=-1.0, 605 max_val=100.0, 606 ) 607 self.add_int_spin_input( 608 'seed_time_limit', 609 '%s:' % _('Time (m)'), 610 core_conf['seed_time_limit'], 611 min_val=1, 612 max_val=10000, 613 ) 614 seedratio = FloatSpinInput( 615 self.mode, 616 'stop_seed_ratio', 617 '', 618 self.move, 619 core_conf['stop_seed_ratio'], 620 precision=2, 621 inc_amt=0.1, 622 min_val=0.5, 623 max_val=100.0, 624 ) 625 self.add_checkedplus_input( 626 'stop_seed_at_ratio', 627 '%s:' % _('Share Ratio Reached'), 628 seedratio, 629 core_conf['stop_seed_at_ratio'], 630 ) 631 self.add_checked_input( 632 'remove_seed_at_ratio', 633 _('Remove torrent (Unchecked pauses torrent)'), 634 core_conf['remove_seed_at_ratio'], 635 ) 636 637 638class ProxyPane(BasePreferencePane): 639 def __init__(self, preferences): 640 BasePreferencePane.__init__(self, ' %s ' % _('Proxy'), preferences) 641 642 @overrides(BasePreferencePane) 643 def create_pane(self, core_conf, console_config): 644 proxy = core_conf['proxy'] 645 646 self.add_header(_('Proxy Settings')) 647 self.add_header(_('Proxy'), space_above=True) 648 self.add_int_spin_input( 649 'proxy_type', '%s:' % _('Type'), proxy['type'], min_val=0, max_val=5 650 ) 651 self.add_text_input('proxy_username', '%s:' % _('Username'), proxy['username']) 652 self.add_text_input('proxy_password', '%s:' % _('Password'), proxy['password']) 653 self.add_text_input('proxy_hostname', '%s:' % _('Hostname'), proxy['hostname']) 654 self.add_int_spin_input( 655 'proxy_port', '%s:' % _('Port'), proxy['port'], min_val=0, max_val=65535 656 ) 657 self.add_checked_input( 658 'proxy_hostnames', _('Proxy Hostnames'), proxy['proxy_hostnames'] 659 ) 660 self.add_checked_input( 661 'proxy_peer_connections', _('Proxy Peers'), proxy['proxy_peer_connections'] 662 ) 663 self.add_checked_input( 664 'proxy_tracker_connections', 665 _('Proxy Trackers'), 666 proxy['proxy_tracker_connections'], 667 ) 668 self.add_header('%s' % _('Force Proxy'), space_above=True) 669 self.add_checked_input('force_proxy', _('Force Proxy'), proxy['force_proxy']) 670 self.add_checked_input( 671 'anonymous_mode', _('Hide Client Identity'), proxy['anonymous_mode'] 672 ) 673 self.add_header('%s' % _('Proxy Type Help'), space_above=True) 674 self.add_text_area( 675 'proxy_text_area', 676 ' 0: None 1: Socks4\n' 677 ' 2: Socks5 3: Socks5 Auth\n' 678 ' 4: HTTP 5: HTTP Auth\n' 679 ' 6: I2P', 680 ) 681 682 683class CachePane(BasePreferencePane): 684 def __init__(self, preferences): 685 BasePreferencePane.__init__(self, ' %s ' % _('Cache'), preferences) 686 self.created = False 687 688 @overrides(BasePreferencePane) 689 def create_pane(self, core_conf, console_config): 690 self.core_conf = core_conf 691 692 def build_pane(self, core_conf, status): 693 self.created = True 694 self.add_header(_('Settings'), space_below=True) 695 self.add_int_spin_input( 696 'cache_size', 697 '%s:' % _('Cache Size (16 KiB blocks)'), 698 core_conf['cache_size'], 699 min_val=0, 700 max_val=99999, 701 ) 702 self.add_int_spin_input( 703 'cache_expiry', 704 '%s:' % _('Cache Expiry (seconds)'), 705 core_conf['cache_expiry'], 706 min_val=1, 707 max_val=32000, 708 ) 709 self.add_header(' %s' % _('Write'), space_above=True) 710 self.add_info_field( 711 'blocks_written', 712 ' %s:' % _('Blocks Written'), 713 status['disk.num_blocks_written'], 714 ) 715 self.add_info_field( 716 'writes', ' %s:' % _('Writes'), status['disk.num_write_ops'] 717 ) 718 self.add_info_field( 719 'write_hit_ratio', 720 ' %s:' % _('Write Cache Hit Ratio'), 721 '%.2f' % status['write_hit_ratio'], 722 ) 723 self.add_header(' %s' % _('Read')) 724 self.add_info_field( 725 'blocks_read', ' %s:' % _('Blocks Read'), status['disk.num_blocks_read'] 726 ) 727 self.add_info_field( 728 'blocks_read_hit', 729 ' %s:' % _('Blocks Read hit'), 730 status['disk.num_blocks_cache_hits'], 731 ) 732 self.add_info_field('reads', ' %s:' % _('Reads'), status['disk.num_read_ops']) 733 self.add_info_field( 734 'read_hit_ratio', 735 ' %s:' % _('Read Cache Hit Ratio'), 736 '%.2f' % status['read_hit_ratio'], 737 ) 738 self.add_header(' %s' % _('Size')) 739 self.add_info_field( 740 'cache_size_info', 741 ' %s:' % _('Cache Size'), 742 status['disk.disk_blocks_in_use'], 743 ) 744 self.add_info_field( 745 'read_cache_size', 746 ' %s:' % _('Read Cache Size'), 747 status['disk.read_cache_blocks'], 748 ) 749 750 @overrides(BasePreferencePane) 751 def update(self, active): 752 if active: 753 client.core.get_session_status(DISK_CACHE_KEYS).addCallback( 754 self.update_cache_status_fields 755 ) 756 757 def update_cache_status_fields(self, status): 758 if not self.created: 759 self.build_pane(self.core_conf, status) 760 else: 761 for ipt in self.inputs: 762 if not ipt.has_input() and ipt.name in status: 763 ipt.set_value(status[ipt.name]) 764 self.preferences.refresh() 765