відмова від відповідальності: Я є автором цього показника, і він написаний для цього конкретного питання
Оновлення 23 жовтня 2018 року
Індикатор тепер підтримує лістинг акції мережі . Завдяки mihaigalos
Оновлення 29 жовтня 2016 року
Тепер індикатор має відключену функціональність і псевдоніми стали унікальними, посилаючись на UUID кожного розділу замість імені блокового пристрою, такого як sda1
. Дивіться відповідний звіт про помилку
Оновлення, 8 жовтня 2016 р
Індикатор зараз у версії 2.0, додав декілька функцій та має власний PPA.
Щоб встановити з PPA, виконайте такі дії в терміналі:
sudo apt-add-repository ppa:udisks-indicator-team/ppa
sudo bash -c 'apt-get update && apt-get install udisks-indicator'
Як згадується у примітках до випуску, до таких функцій належать:
- Піктограми для записів у меню: до кожного розділу / пристрою додається відповідна піктограма. Якщо на пристрої є USB-диск, використовується значок знімного носія, якщо це ізо-зображення - використовується значок оптичного диска, і, очевидно, на розділах жорсткого диска / SSD є піктограми накопичувача.
- Тепер використання показано у відсотковому та читаному для людини значеннях (потужність 1024).
- Графічне зображення використання за допомогою панелі використання (велике спасибі Матео Сальті за ідею)
- Діалогове вікно налаштувань: користувачі можуть вимкнути певні поля, які вони не хочуть бачити для кожної записи меню. Це дозволяє підтримувати меню індикатора в чистоті, якщо додається велика кількість розділів. (Завдяки проханню Захарі)
- Текстовий інтервал: з шрифтом Ubuntu за замовчуванням та шрифтами Monospace, текстові записи добре розташовані, щоб мати більш чистий вигляд та підвищити читабельність інформації.
- Пухирці повідомлень у випадку, якщо перегородку неможливо встановити
Нижче наведено скріншот із темою значка Ubuntu за замовчуванням:
Тема значка Ubuntu Kylin
Якщо всі необов’язкові поля вимкнено
Вибір дизайну та додаткові думки:
Створюючи цей показник, я сподівався досягти утиліти, яка б підходила як для досвідчених, так і для випадкових користувачів. Я спробував вирішити деякі проблеми, які я помітив у нових користувачів, можливо, в роботі з інструментами командного рядка. Крім того, утиліта прагне бути багатоцільовою.
Діалогове вікно "Налаштування" дозволяє зробити індикатор таким же складним та / або таким же простим, як бажає користувач. Це також було конкретним дизайнерським рішенням, щоб уникнути наявності етикетки на верхній панелі, щоб вона не займала занадто багато місця на верхній панелі користувача. Крім того, цей індикатор прагне бути багатоцільовою утилітою, яка дозволяє монтувати розділи, а також відкривати відповідні каталоги. Це може використовуватися не тільки як утиліта використання диска, але і як утиліта навігації для швидкого відкриття каталогів.
Користувачам також зручно знати, який розділ мешкає на якому диску, тим самим уникаючи частого плутанини з монтажем через утиліти командного рядка, такі як mount
. Натомість він використовує udisksctl
для цієї мети (а також отримання інформації від UDisks2
демона, звідси і названня). Єдине завдання, яке воно не виконує, - це відключення, або через Open Disks Utility
це включена запис у меню.
Хоча спочатку я прагнув зробити це схожим на меню iStat, проект відхилився від цієї мети - індикатор унікальний за своїм дизайном та призначенням. Я сподіваюся, що він стане корисним для багатьох користувачів та зробить їхній досвід Ubuntu набагато приємнішим.
удиски-індикатор (оригінальна відповідь)
Індикатор для Ubuntu з робочим столом Unity для показу використання диска
Огляд
Цей показник для Ubuntu з Unity дозволяє легко переглядати інформацію про встановлені розділи. Він прагне бути візуально схожим на меню iStat Menu 3 меню OS X.
Записи організовані в порядку:
- Перегородка
- Псевдонім (якщо встановлено користувачем)
- Дисковий диск, до якого розділу належить
- Точка кріплення розділу (каталог)
- % Використання
Натиснувши на кожен запис розділу, ви відкриєте точку кріплення розділу в файловому менеджері за замовчуванням
У меню "Відключені розділи" перелічені всі розділи, які наразі не змонтовані системою. Натиснувши на будь-який запис у цьому підменю, автоматично підключите цей розділ, як правило, у /media/username/drive-id
папку
Індикатор використовує піктограми за замовчуванням, що надаються в системі, тому піктограму слід змінювати, змінюючи тему піктограми за допомогою інструменту "Інструмент настроювання"
ПРИМІТКА . Якщо ви хочете додати одночасно кілька псевдонімів, замість одного за одним за допомогою опції "Зробити псевдонім", це можна зробити за допомогою редагування ~/.partition_aliases.json
файла конфігурації. Формат такий:
{
"sda1": "Alias 1",
"sda2": "Alias 2",
"sdb1": "Alias 3"
}
Установка
PPA для простої установки незабаром. . .
Тим часом, ось альтернативні кроки:
cd /tmp
wget https://github.com/SergKolo/udisks-indicator/archive/master.zip
unzip master.zip
sudo install udisks-indicator-master/udisks-indicator /usr/bin/udisks-indicator
sudo install udisks-indicator-master/udisks-indicator.desktop /usr/share/applications/udisks-indicator.desktop
Всі ці кроки можна помістити в маленький хороший сценарій встановлення:
#!/bin/bash
cd /tmp
rm master.zip*
wget https://github.com/SergKolo/udisks-indicator/archive/master.zip
unzip master.zip
install udisks-indicator-master/udisks-indicator /usr/bin/udisks-indicator
install udisks-indicator-master/udisks-indicator.desktop /usr/share/applications/udisks-indicator.desktop
Вихідний код
Оригінальний вихідний код (версія v1.0) з базовою функціональністю цього індикатора можна знайти нижче. Щоб отримати новітні функції, перегляньте сховище GitHub для цього проекту . Повідомте про будь-які запити щодо функцій, а також про помилки на GitHub.
The /usr/bin/udisks-indicator
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Author: Serg Kolo , contact: 1047481448@qq.com
# Date: September 27 , 2016
# Purpose: appindicator for displaying mounted filesystem usage
# Tested on: Ubuntu 16.04 LTS
#
#
# Licensed under The MIT License (MIT).
# See included LICENSE file or the notice below.
#
# Copyright © 2016 Sergiy Kolodyazhnyy
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import gi
gi.require_version('AppIndicator3', '0.1')
from gi.repository import GLib as glib
from gi.repository import AppIndicator3 as appindicator
from gi.repository import Gtk as gtk
from os import statvfs
#from collections import OrderedDict
import subprocess
import shutil
import dbus
import json
import os
class UdisksIndicator(object):
def __init__(self):
self.app = appindicator.Indicator.new(
'udisks-indicator', "drive-harddisk-symbolic.svg",
appindicator.IndicatorCategory.HARDWARE
)
if not self.app.get_icon():
self.app.set_icon("drive-harddisk-symbolic")
self.app.set_status(appindicator.IndicatorStatus.ACTIVE)
filename = '.partition_aliases.json'
user_home = os.path.expanduser('~')
self.config_file = os.path.join(user_home,filename)
self.cache = self.get_partitions()
self.make_menu()
self.update()
def update(self):
timeout = 5
glib.timeout_add_seconds(timeout,self.callback)
def callback(self):
if self.cache != self.get_partitions():
self.make_menu()
self.update()
def make_menu(self,*args):
""" generates entries in the indicator"""
if hasattr(self, 'app_menu'):
for item in self.app_menu.get_children():
self.app_menu.remove(item)
self.app_menu = gtk.Menu()
partitions = self.get_partitions()
for i in partitions:
part = "Partition: " + i[0]
alias = self.find_alias(i[0])
drive = "\nDrive: " + i[1]
mount = "\nMountPoint: " + i[2]
usage = "\n%Usage: " + i[3]
item = part + drive + mount + usage
if alias:
alias = "\nAlias: " + alias
item = part + alias + drive + mount + usage
self.menu_item = gtk.MenuItem(item)
self.menu_item.connect('activate',self.open_mountpoint,i[2])
self.app_menu.append(self.menu_item)
self.menu_item.show()
self.separator = gtk.SeparatorMenuItem()
self.app_menu.append(self.separator)
self.separator.show()
self.unmounted = gtk.MenuItem('Unmounted Partitions')
self.unmounted_submenu = gtk.Menu()
self.unmounted.set_submenu(self.unmounted_submenu)
for i in self.get_unmounted_partitions():
# TODO: add type checking, prevent swap
part = "Partition: " + i[0]
alias = self.find_alias(i[0])
drive = "\nDrive: " + i[1]
label = part + drive
if alias:
alias = "\nAlias: " + alias
label = part + alias + drive
self.menu_item = gtk.MenuItem(label)
self.menu_item.connect('activate',self.mount_partition,i[0])
self.unmounted_submenu.append(self.menu_item)
self.menu_item.show()
self.separator = gtk.SeparatorMenuItem()
self.unmounted_submenu.append(self.separator)
self.separator.show()
self.app_menu.append(self.unmounted)
self.unmounted.show()
self.separator = gtk.SeparatorMenuItem()
self.app_menu.append(self.separator)
self.separator.show()
self.make_part_alias = gtk.MenuItem('Make Alias')
self.make_part_alias.connect('activate',self.make_alias)
self.app_menu.append(self.make_part_alias)
self.make_part_alias.show()
user_home = os.path.expanduser('~')
desktop_file = '.config/autostart/udisks-indicator.desktop'
full_path = os.path.join(user_home,desktop_file)
label = 'Start Automatically'
if os.path.exists(full_path):
label = label + ' \u2714'
self.autostart = gtk.MenuItem(label)
self.autostart.connect('activate',self.toggle_auto_startup)
self.app_menu.append(self.autostart)
self.autostart.show()
self.open_gnome_disks = gtk.MenuItem('Open Disks Utility')
self.open_gnome_disks.connect('activate',self.open_disks_utility)
self.app_menu.append(self.open_gnome_disks)
self.open_gnome_disks.show()
self.quit_app = gtk.MenuItem('Quit')
self.quit_app.connect('activate', self.quit)
self.app_menu.append(self.quit_app)
self.quit_app.show()
self.app.set_menu(self.app_menu)
def mount_partition(self,*args):
# TODO: implement error checking for mounting
return self.run_cmd(['udisksctl','mount','-b','/dev/' + args[-1]])
def get_mountpoint_usage(self,mountpoint):
fs = statvfs(mountpoint)
usage = 100*(float(fs.f_blocks)-float(fs.f_bfree))/float(fs.f_blocks)
return str("{0:.2f}".format(usage))
def get_partitions(self):
objects = self.get_dbus('system',
'org.freedesktop.UDisks2',
'/org/freedesktop/UDisks2',
'org.freedesktop.DBus.ObjectManager',
'GetManagedObjects',
None)
partitions = []
for item in objects:
try:
if 'block_devices' in str(item):
drive = self.get_dbus_property('system',
'org.freedesktop.UDisks2',
item,
'org.freedesktop.UDisks2.Block',
'Drive')
if drive == '/': continue
mountpoint = self.get_mountpoint(item)
if not mountpoint: continue
mountpoint = mountpoint.replace('\x00','')
drive = str(drive).split('/')[-1]
usage = self.get_mountpoint_usage(mountpoint)
part = str(item.split('/')[-1])
partitions.append((part,drive,mountpoint,usage))
except Exception as e:
#print(e)
pass
# returning list of tuples
partitions.sort()
return partitions
def get_mountpoint(self,dev_path):
try:
data = self.get_dbus_property(
'system',
'org.freedesktop.UDisks2',
dev_path,
'org.freedesktop.UDisks2.Filesystem',
'MountPoints')[0]
except Exception as e:
#print(e)
return None
else:
if len(data) > 0:
return ''.join([ chr(byte) for byte in data])
def get_unmounted_partitions(self):
objects = self.get_dbus('system',
'org.freedesktop.UDisks2',
'/org/freedesktop/UDisks2',
'org.freedesktop.DBus.ObjectManager',
'GetManagedObjects',
None)
partitions = []
for item in objects:
try:
if 'block_devices' in str(item):
drive = self.get_dbus_property('system',
'org.freedesktop.UDisks2',
item,
'org.freedesktop.UDisks2.Block',
'Drive')
if drive == '/': continue
mountpoint = self.get_mountpoint(item)
if mountpoint: continue
drive = str(drive).split('/')[-1]
part = str(item.split('/')[-1])
if not part[-1].isdigit(): continue
partitions.append((part,drive))
#print(partitions)
except Exception as e:
#print(e)
pass
partitions.sort()
return partitions
def get_dbus(self,bus_type,obj,path,interface,method,arg):
if bus_type == "session":
bus = dbus.SessionBus()
if bus_type == "system":
bus = dbus.SystemBus()
proxy = bus.get_object(obj,path)
method = proxy.get_dbus_method(method,interface)
if arg:
return method(arg)
else:
return method()
def get_dbus_property(self,bus_type,obj,path,iface,prop):
if bus_type == "session":
bus = dbus.SessionBus()
if bus_type == "system":
bus = dbus.SystemBus()
proxy = bus.get_object(obj,path)
aux = 'org.freedesktop.DBus.Properties'
props_iface = dbus.Interface(proxy,aux)
props = props_iface.Get(iface,prop)
return props
def make_alias(self,*args):
partitions = [ i[0] for i in self.get_partitions() ]
combo_values = '|'.join(partitions)
#print(combo_values)
command=[ 'zenity','--forms','--title','Make Alias',
'--add-combo','Partition','--combo-values',
combo_values,'--add-entry','Alias' ]
user_input = self.run_cmd(command)
if not user_input: return
alias = user_input.decode().strip().split('|')
existing_values = None
if os.path.isfile(self.config_file):
with open(self.config_file) as conf_file:
try:
existing_values = json.load(conf_file)
except ValueError:
pass
with open(self.config_file,'w') as conf_file:
if existing_values:
existing_values[alias[0]] = alias[1]
else:
existing_values = {alias[0]:alias[1]}
#print(existing_values)
json.dump(existing_values,conf_file,indent=4,sort_keys=True)
def find_alias(self,part):
if os.path.isfile(self.config_file):
with open(self.config_file) as conf_file:
try:
aliases = json.load(conf_file)
except ValueError:
pass
else:
if part in aliases:
return aliases[part]
else:
return None
def toggle_auto_startup(self,*args):
user_home = os.path.expanduser('~')
desktop_file = '.config/autostart/udisks-indicator.desktop'
full_path = os.path.join(user_home,desktop_file)
if os.path.exists(full_path):
os.unlink(full_path)
else:
original = '/usr/share/applications/udisks-indicator.desktop'
if os.path.exists(original):
shutil.copyfile(original,full_path)
self.make_menu()
def open_mountpoint(self,*args):
pid = subprocess.Popen(['xdg-open',args[-1]]).pid
def open_disks_utility(self,*args):
pid = subprocess.Popen(['gnome-disks']).pid
def run_cmd(self, cmdlist):
""" Reusable function for running external commands """
new_env = dict(os.environ)
new_env['LC_ALL'] = 'C'
try:
stdout = subprocess.check_output(cmdlist, env=new_env)
except subprocess.CalledProcessError:
pass
else:
if stdout:
return stdout
def run(self):
""" Launches the indicator """
try:
gtk.main()
except KeyboardInterrupt:
pass
def quit(self, data=None):
""" closes indicator """
gtk.main_quit()
def main():
""" defines program entry point """
indicator = UdisksIndicator()
indicator.run()
if __name__ == '__main__':
main()
The /usr/share/applications/udisks-indicator.desktop
[Desktop Entry]
Version=1.0
Name=Udisks Indicator
Comment=Indicator for reporting partition information
Exec=udisks-indicator
Type=Application
Icon=drive-harddisk-symbolic.svg
Terminal=false
Додаткова інформація:
Тест Ubuntu Mate 16.04:
Користувачам Gnome потрібне розширення (KStatusNotifierItem / AppIndicator Support), щоб індикатор поводився належним чином:
/dev/sdb1
та його використання прямо поруч із ним? У відсотках чи фактичних гігабайти?