Czy w Ubuntu Unity jest menu „Miejsca”?

11

Chciałbym wiedzieć, czy można umieścić zakładkę „Miejsca” w górnym menu Ubuntu, takim jak CentOS, Debian itp.

Dzięki

Ulises CT
źródło
Z łatwością, ale co dokładnie powinno to pokazać?
Jacob Vlijm,
główne foldery (domowe, pliki do pobrania, dokumenty itp.) oraz te z zakładkami, takie jak debian i centos
Ulises CT
Rozumiem, napiszę dziś lub jutro, jeśli nikt inny tego nie zrobił :), a może już istnieje (masz na myśli wskaźnik, prawda?)
Jacob Vlijm,
wyszukaj „Debian menu Miejsca” w Grafice Google, a zobaczysz, co mam na myśli.
Ulises CT
Nie, to było klasyczne menu. Wszystko, co znalazłem, to przestarzałe rzeczy z centymetrowym kurzem. Potrafię dość szybko napisać podstawowy (i zrobię). Chciałbym jednak połączyć go z tym: askubuntu.com/questions/803869/... , co uczyniłoby go interesującym projektem. Pierwszy strzał dzisiaj lub jutro nie będzie zatem ostatnim. Miłe pytanie.
Jacob Vlijm,

Odpowiedzi:

12

Wypróbowałem kilka istniejących, ale nie mogłem znaleźć działającego wskaźnika Miejsc . Te, które znalazłem, były przestarzałe, ppa nie były już utrzymywane.

Menu miejsc modułowych

A więc poniżej świeżo napisanego: Wskaźnik miejsc i plików dla Ubuntu .

wprowadź opis zdjęcia tutaj 2)

Wersja ppa jest modułowa ; możesz wybrać, co ma być wyświetlane w menu:

[ wprowadź opis zdjęcia tutaj]

W pełnej wersji:

wprowadź opis zdjęcia tutaj

... lub najmniejszy, pokazujący tylko ostatnio używane:

wprowadź opis zdjęcia tutaj

Instalowanie z ppa

sudo add-apt-repository ppa:vlijm/placesfiles
sudo apt-get update
sudo apt-get install placesfiles

Uproszczona wersja pokazująca menu miejsc, zakładki i ostatnio używane pliki

Opis i (początkowy) kod

Scenariusz

#!/usr/bin/env python3
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject
import time
from threading import Thread
import os
import subprocess

class Indicator():
    def __init__(self):

        currpath = os.path.dirname(os.path.realpath(__file__))
        self.home = os.environ["HOME"]
        self.bmark_file = os.path.join(self.home, ".config/gtk-3.0/bookmarks")
        self.def_file = os.path.join(self.home, ".config/user-dirs.dirs")
        self.recdata = os.path.join(self.home, ".local/share/recently-used.xbel")
        self.n = 10
        self.app = 'places'
        iconpath = os.path.join(currpath, "dir_icon.png")
        self.indicator = AppIndicator3.Indicator.new(
            self.app, iconpath,
            AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
        self.indicator.set_label("Places", self.app)
        self.indicator.set_menu(self.create_menu())
        # the thread:
        self.update = Thread(target=self.check_recent)
        self.update.setDaemon(True)
        self.update.start()

    def create_menu(self):
        # creates the (initial) menu
        self.menu = Gtk.Menu()
        # separator
        initial = Gtk.MenuItem("Fetching list...")
        menu_sep = Gtk.SeparatorMenuItem()
        self.menu.append(initial)
        self.menu.append(menu_sep)
        # item_quit.show() 
        self.menu.show_all()
        return self.menu

    def open_directory(self, *args):
        index = self.menu.get_children().index(self.menu.get_active())
        selection = self.menu_items2[index-2]
        self.execute(["xdg-open", selection])

    def open_file(self, *args):
        index = self.submenu.get_children().index(self.submenu.get_active())
        selection = self.submenu2[index] 
        self.execute(["xdg-open", selection])

    def go_special(self, button, target):
        self.execute(["xdg-open", target])

    def connect(self, button):
        self.execute("nautilus-connect-server")

    def set_new(self):
        # update the list, appearing in the menu
        for i in self.menu.get_children():
            self.menu.remove(i)
        home_mention = Gtk.MenuItem("⌂ Home")
        home_mention.connect("activate", self.go_special, self.home)
        self.menu.append(home_mention)
        # separator
        menu_sep1 = Gtk.SeparatorMenuItem()
        self.menu.append(menu_sep1)
        for app in self.menu_items2:
            sub = Gtk.MenuItem("⏍ "+app.split("/")[-1])
            self.menu.append(sub)
            sub.connect('activate', self.open_directory)
        # separator
        menu_sep2 = Gtk.SeparatorMenuItem()
        self.menu.append(menu_sep2)
        # network
        network = "network:///"
        network_mention = Gtk.MenuItem("⇄ Network")
        network_mention.connect("activate", self.go_special, network)
        self.menu.append(network_mention)
        connect_mention = Gtk.MenuItem("⮁ Connect to server")
        connect_mention.connect("activate", self.connect)
        self.menu.append(connect_mention)
        # separator
        menu_sep3 = Gtk.SeparatorMenuItem()
        self.menu.append(menu_sep3)
        # computer
        computer = "computer:///"
        computer_mention = Gtk.MenuItem("⛁ Computer")
        computer_mention.connect("activate", self.go_special, computer)
        self.menu.append(computer_mention)
        recent_mention = Gtk.MenuItem("⁕ Recent files")
        self.menu.append(recent_mention)

        self.submenu = Gtk.Menu()
        for f in self.submenu2:
            recent = Gtk.MenuItem(f)
            recent.connect("activate", self.open_file)
            self.submenu.append(recent)
        recent_mention.set_submenu(self.submenu)
        # separator
        menu_sep6 = Gtk.SeparatorMenuItem()
        self.menu.append(menu_sep6)
        # quit
        item_quit = Gtk.MenuItem('Quit')
        item_quit.connect('activate', self.stop)
        self.menu.append(item_quit)
        self.menu.show_all()

    def run_about(self, *args):
        self.execute("/opt/upfront/code/runabout")

    def check_recent(self):
        self.menu_items1 = []; self.submenu1 = []
        while True:
            time.sleep(4)
            self.menu_items2 = self.get_bookmarks()
            self.submenu2 = self.get_files()

            if any([self.menu_items2 != self.menu_items1,
                self.submenu2 != self.submenu1]):
                GObject.idle_add(
                    self.set_new, 
                    priority=GObject.PRIORITY_DEFAULT
                    )
            self.menu_items1 = self.menu_items2
            self.submenu1 = self.submenu2

    def stop(self, source):
        Gtk.main_quit()

    def get_bookmarks(self):
        loc_bookmarks = [
            l.replace("file://", "") for l in open(self.bmark_file).read().splitlines()\
            if l.startswith("file://")
            ]
        netw_bookmarks = [
            l for l in open(self.bmark_file).read().splitlines()\
            if l.startswith("smb://")
            ]
        defaults = [
            os.path.join(self.home, l.replace('"', "").split("$HOME/")[-1]) for l in \
            open(self.def_file).read().splitlines() if all\
            (["$HOME/" in l, l.startswith("XDG")])
            ]
        return [self.replace_sc(m.split(" ")[0]).rstrip("/") for m in list(
            set(loc_bookmarks+defaults+netw_bookmarks))]

    def replace_sc(self, path):
        for c in [("%23", "#"), ("%5D", "]"), ("%5E", "^"),
                  ("file://", ""), ("%20", " ")]:
            path = path.replace(c[0], c[1])
        return path

    def execute(self, command):
        subprocess.Popen(command)

    def get_files(self):
        # create the list of recently used files
        used = [l for l in open(self.recdata) if all([
                    '<bookmark href="file://' in l, not "/tmp" in l, "." in l])]
        relevant = [l.split('="') for l in set(used)]
        relevant = [[it[1][7:-7], it[-2][:-10]] for it in relevant]
        relevant.sort(key=lambda x: x[1])
        return [item[0].replace("%20", " ") for item in relevant[::-1][:self.n]]


Indicator()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()

Jak korzystać (jeśli nie jest zainstalowany z ppa)

  1. Skopiuj skrypt do pustego pliku i zapisz go jako places_indicator.py
  2. Zapisz ikonę (kliknij prawym przyciskiem myszy> zapisz jako) dokładnie o nazwie:

    dir_icon.png
    

    wprowadź opis zdjęcia tutaj

    .. w jednym i tym samym katalogu co skrypt.

  3. Testuj - uruchom skrypt za pomocą polecenia:

    python3 /path/to/places_indicator.py
    
  4. Jeśli wszystko działa poprawnie, dodaj go do aplikacji startowych: Dash> Aplikacje startowe> Dodaj. Dodaj polecenie:

    /bin/bash -c "sleep 10 && python3 /path/to/places_indicator.py
    

O wskaźniku

Wskaźnik pokazuje:

  1. Katalog domowy
  2. Wszystkie katalogi (lokalne zakładki i smb) w
    • ~/.config/gtk-3.0/bookmarks
    • ~/.config/user-dirs.dirs
  3. Sieć
  4. Połącz z siecią
  5. Komputer
  6. Ostatnio używane pliki (łats 10, jak to jest, można łatwo zmienić)

Zmiana / dodane / usunięte zakładki są aktualizowane dynamicznie

Jacob Vlijm
źródło
całkiem dobrze, próbowałem tego na Unity i działa dzięki! Ale zdecydowałem się użyć Gnome'a, ponieważ wygląda piękniej, ale użyję go również do niedawnej funkcji plików! dzięki
Ulises CT
@UlisesCT Ach, dziękuję za wypróbowanie Unity, mimo że się zmieniłeś!
Jacob Vlijm,
Tak! problem polega na tym, że pochodzę z systemu Windows na komputer stacjonarny i nigdy nie korzystałem z grafik w Linuksie, tylko terminal na CentOS dla serwerów i tym podobne, a kiedy zainstalowałem ubuntu z ubuntu.es, myślałem, że jego GUI jest właśnie taki i nie wiedziałem jest Gnome i Unity, które możesz wybrać (brakowało mi zakładki Miejsca, ponieważ to było w CentOS, które próbowałem wypróbować jako pulpit, ale to trochę do bani). Dobrze jest kontynuować naukę
Ulises CT
Wow, to zobowiązanie - napisanie nowego programu, aby zaspokoić tę potrzebę! Bardzo pod wrażeniem, dobra robota @JacobVlijm! Dlaczego jest to wersja 0.5.1-1, jeśli dopiero ją napisałeś?
Ads20000,
@ Ads20000 Dzięki! Kilka ulepszeń; Pliki (ponownie) przeniesione lub o zmienionej nazwie są teraz zaznaczone, powiadomienie jest wyświetlane, jeśli (spróbujesz) je otworzyć, inna ikona ostatniej chwili, teraz działa również 14.04, drobna optymalizacja kodu (odfiltrowanie znaków specjalnych w nazwach plików) itp.
Jacob Vlijm,
8

Aktualizacja 24 lutego 2017 r . : wskaźnik ma teraz opcję przypinania łączy internetowych

Wprowadzenie

UWAGA: Poprzednia wersja tej odpowiedzi znajduje się w historii edycji, chociaż nie jest już istotna.

Przedstawiony poniżej wskaźnik ma na celu inne pytanie, ale ponieważ pojawiła się okazja, postanowiłem ją tutaj opublikować. Wskaźnik plików to prosty wskaźnik dostępu do plików i folderów użytkownika. Umożliwia sprawdzenie ostatnio używanych plików, zakładek i katalogów. W szczególności menu Miejsca ma szczególne znaczenie dla tego pytania.

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Jak widać na zrzucie ekranu, wskaźnik obsługuje również ustawienia narodowe inne niż angielski, więc jeśli twój system używa czegoś innego niż angielski, będzie działać.

Aktualizacja : wskaźnik obsługuje teraz także uruchamianie plików .desktop, które zostały przypięte. Na przykład, jeśli masz przypięty firefox.desktop, uruchomi się firefox. Tak więc wskaźnik może być używany jako szybki program uruchamiający programy. Funkcja jest w drodze do PPA w momencie pisania (19 listopada, 19:53 GMT, przetworzenie powinno zająć około 24 godzin), ale jest już dostępna na github, podobnie jak tutaj, w zaktualizowanym kodzie źródłowym.

wprowadź opis zdjęcia tutaj

Uzyskanie wskaźnika

Wskaźnik jest dostępny z mojego osobistego PPA, a także z GitHub . Aby to uzyskać, wykonaj następujące kroki:

sudo add-apt-repository ppa:1047481448-2/sergkolo
sudo apt-get update
sudo apt-get install files-indicator

Kod źródłowy

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#
# Author: Serg Kolo , contact: [email protected]
# Date: November 19 , 2016
# Purpose: appindicator for accessing files and folders
# 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')
gi.require_version('Notify', '0.7')
from gi.repository import GLib as glib
from gi.repository import AppIndicator3 as appindicator
from gi.repository import Gtk as gtk
from gi.repository import Gio
from gi.repository import Notify
from collections import OrderedDict
# from collections import OrderedDict
import urllib.parse
import subprocess
import copy
import shutil
import dbus
import math
import json
import os

class FilesIndicator(object):

    def __init__(self):
        self.app = appindicator.Indicator.new(
            'files-indicator', "document-open-recent",
            appindicator.IndicatorCategory.HARDWARE
        )
        self.user_home = os.path.expanduser('~')
        filename = '.pinned_files.json'
        self.pinned_list = os.path.join(self.user_home,filename)

        self.config = os.path.join(self.user_home,'.files_indicator.json')
        self.max_items = 15
        self.name_length = 20
        self.read_config()

        self.app.set_status(appindicator.IndicatorStatus.ACTIVE)

        self.cached_files = self.get_recent_files()
        self.make_menu()
        self.update()

    def read_config(self,*args):
        config = {}
        try:
            with open(self.config) as f:
                 config = json.load(f)

        except FileNotFoundError:
            print('>>> ',self.config,' not found.Creating one')
            f = open(self.config,'w')
            config = {'max_items':self.max_items,
                      'name_length':self.name_length
            }
            json.dump(config,f,indent=4)
            f.close()
        except json.JSONDecodeError:
            print(">>> Can't read ",self.pinned_list,',may be corrupt')
            return None
        else:
            self.max_items = config['max_items']
            self.name_length = config['name_length']

    def add_menu_item(self, menu_obj, item_type, image, label, action, args):
        """ dynamic function that can add menu items depending on
            the item type and other arguments"""
        menu_item, icon = None, None
        if item_type is gtk.ImageMenuItem and label:
            menu_item = gtk.ImageMenuItem.new_with_label(label)
            menu_item.set_always_show_image(True)
            if '/' in image:
                icon = gtk.Image.new_from_file(image)
            else:
                icon = gtk.Image.new_from_icon_name(image, 48)
            menu_item.set_image(icon)
        elif item_type is gtk.ImageMenuItem and not label:
            menu_item = gtk.ImageMenuItem()
            menu_item.set_always_show_image(True)
            if '/' in image:
                icon = gtk.Image.new_from_file(image)
            else:
                icon = gtk.Image.new_from_icon_name(image, 16)
            menu_item.set_image(icon)
        elif item_type is gtk.MenuItem:
            menu_item = gtk.MenuItem(label)
        elif item_type is gtk.SeparatorMenuItem:
            menu_item = gtk.SeparatorMenuItem()
        if action:
            menu_item.connect('activate', action, *args)

        menu_obj.append(menu_item)
        menu_item.show()

    def get_user_dirs(self,*args):
        user_dirs = []
        for index,val in glib.UserDirectory.__enum_values__.items():
            if index == 8: continue
            dir = glib.get_user_special_dir(index)
            if dir: user_dirs.append(dir)
        return user_dirs

    def get_file_icon(self,*args):
        if args[-1].endswith('.desktop'):
            desk_file = Gio.DesktopAppInfo.new_from_filename(args[-1])
            icon = desk_file.get_icon()
            if type(icon) == Gio.ThemedIcon:
                themed_name = icon.get_names()[0]
                theme = gtk.IconTheme.get_default()
                name = theme.lookup_icon(themed_name, 48, 0).get_filename()
            if type(icon) == Gio.FileIcon:
                name = icon.get_file().get_uri()

            icon_url= urllib.parse.unquote(name).replace('file://','') 
            return icon_url

        file = Gio.File.new_for_path(args[-1])
        file_info = file.query_info("standard::*",0)
        icon_string = file_info.get_icon().to_string()
        if 'folder-' in icon_string:
            return icon_string.split()[-2]
        return icon_string.split()[-1]

    def get_recent_files(self,*args):
        manager = gtk.RecentManager.get_default()
        try:
            files = OrderedDict()
            for index,item in enumerate(manager.get_items(),1):
                    uri = item.get_uri()
                    uri_decoded = urllib.parse.unquote(uri)
                    filepath = uri_decoded.replace('file://','')
                    if not os.path.exists(filepath): continue
                    basename = os.path.basename(uri_decoded)
                    files[basename] = filepath
                    if index == self.max_items:
                        break
        except Exception as e:
            print(e)
            return None
        finally:  return files

    def callback(self,*args):
        self.update()

    def update(self,*args):
        current_files = self.get_recent_files()
        if current_files != self.cached_files:
             self.make_menu()
             self.cached_files = current_files
        glib.timeout_add_seconds(3,self.callback)

    def add_submenu(self,top_menu,label):
        menuitem = gtk.MenuItem(label)
        submenu = gtk.Menu()
        menuitem.set_submenu(submenu)
        top_menu.append(menuitem)
        menuitem.show()
        return submenu

    def make_menu(self):
        if hasattr(self, 'app_menu'):
            for item in self.app_menu.get_children():
                    self.app_menu.remove(item)
        else:
            self.app_menu = gtk.Menu()
        recent = self.add_submenu(self.app_menu,'Recent Files')
        recent_dict = self.get_recent_files()

        content = [recent,gtk.ImageMenuItem,'gtk-add',
                   'Add to Recent Files',self.add_recent,[None]
        ]      
        self.add_menu_item(*content) 

        content = [recent,gtk.ImageMenuItem,'user-trash',
                   'Clear recent files list',self.clear_recent,[None]
        ]      
        self.add_menu_item(*content)

        content = [recent,gtk.SeparatorMenuItem,
                   None,None,
                   None,[None]
        ]
        self.add_menu_item(*content)
        self.add_menu_item(*content) 
        if not recent_dict:
            content = [recent,gtk.MenuItem,None,
                       'No items',None,None
            ]
            self.add_menu_item(*content)
            last = None
            for i in recent.get_children():
                last = i
            last.set_sensitive(False)
        else:
            for name,data in recent_dict.items():
                icon = self.get_file_icon(data)
                content = [recent, gtk.ImageMenuItem,
                           icon, name[:self.name_length],
                           self.open_item, [data]
                ]
                self.add_menu_item(*content)

        # Pinned files
        bookmarks = self.add_submenu(self.app_menu,'Pinned Files')
        content = [bookmarks,gtk.ImageMenuItem,
                   'bookmark_add','Pin a file',
                   self.pin_file,[bookmarks,None]
        ]
        self.add_menu_item(*content)

        content = [bookmarks,gtk.ImageMenuItem,
                   'remove','Remove item',
                   self.remove_pinned,['files']
        ]
        self.add_menu_item(*content)

        content = [bookmarks,gtk.ImageMenuItem,
                   'user-trash','Remove All',
                   self.remove_all_pinned,[None]
        ]
        self.add_menu_item(*content)
        content = [bookmarks,gtk.SeparatorMenuItem,
                   None,None,
                   None,[None]
        ]
        self.add_menu_item(*content)
        self.add_menu_item(*content) 

        pinned_files = self.get_pinned()

        if (pinned_files and 
            'files' in pinned_files.keys() and
            pinned_files['files']):
            for filepath in pinned_files['files']:
                icon = self.get_file_icon(filepath) 
                content = [bookmarks,gtk.ImageMenuItem,
                           icon,os.path.basename(filepath),
                           self.open_item,[filepath]
                ]
                self.add_menu_item(*content)
        else:
            content = [bookmarks,gtk.MenuItem,None,
                       'No items',None,None
            ]
            self.add_menu_item(*content)
            last = None
            for i in bookmarks.get_children():
                last = i
            last.set_sensitive(False)

        places = self.add_submenu(self.app_menu,'Places')
        content = [places,gtk.ImageMenuItem,'add',
                   'Pin Directory',self.pin_dir,[None]
        ]

        self.add_menu_item(*content)

        content = [places,gtk.ImageMenuItem,
                   'remove','Remove Pinned',
                   self.remove_pinned,['dirs']
        ]
        self.add_menu_item(*content)

        content = [places,gtk.SeparatorMenuItem,
                   None,None,
                   None,[None]
        ]
        self.add_menu_item(*content)

        content = [places,gtk.MenuItem,None,
                   'Standard Dirs',None,None
        ]
        self.add_menu_item(*content)
        last = None
        for i in places.get_children():
            last = i
        last.set_sensitive(False)
        for dir in self.get_user_dirs():
            icon = self.get_file_icon(dir)
            content = [places,gtk.ImageMenuItem,icon,
                       os.path.basename(dir),self.open_item,[dir]

            ]
            self.add_menu_item(*content)

        content = [places,gtk.SeparatorMenuItem,
                   None,None,
                   None,[None]
        ]
        self.add_menu_item(*content)

        content = [places,gtk.MenuItem,None,
                   'Pinned Dirs',None,None
        ]
        self.add_menu_item(*content)
        last = None
        for i in places.get_children():
            last = i
        last.set_sensitive(False)

        if (pinned_files and 
           'dirs' in pinned_files.keys() and
           pinned_files['dirs']):
            for dir in pinned_files['dirs']:
                icon = self.get_file_icon(dir)
                print(icon)
                content = [places,gtk.ImageMenuItem,icon,
                           os.path.basename(dir),self.open_item,[dir]

                ]
                self.add_menu_item(*content)
        else:
            content = [places,gtk.MenuItem,None,
                       'No items',None,None
            ]
            self.add_menu_item(*content)
            last = None
            for i in places.get_children():
                last = i
            last.set_sensitive(False)

        content = [self.app_menu,gtk.SeparatorMenuItem,
                   None,None,
                   None,[None]
        ]
        self.add_menu_item(*content)
        content = [self.app_menu,gtk.ImageMenuItem,'exit',
                   'quit',self.quit,[None]
        ]
        self.add_menu_item(*content)
        self.app.set_menu(self.app_menu)

    def check_directory(self,*args):
        current_set = set(os.listdir(args[-1]))
        return current_set - self.cached_set


    def get_pinned(self,*args):
        try:
            with open(self.pinned_list) as f:
                 return json.load(f,object_pairs_hook=OrderedDict)

        except FileNotFoundError:
            print('>>> ',self.pinned_list,' not found')
            return None
        except json.JSONDecodeError:
            print(">>> Can't read ",self.pinned_list,',may be corrupt')
            return None

    def pin_dir(self,*args):
        # TODO
        current_list = self.get_pinned()
        if not current_list:
                current_list = OrderedDict()
                current_list['dirs'] = []
                f = open(self.pinned_list,'w')
                f.write("")
                f.close()

        if not args[-1]:
                cmd = "zenity --file-selection --directory --separator || --multiple"
                dirs = self.run_cmd(cmd.split())
        else:
                dirs = args[-1]

        dir_list = []
        if not dirs: return None
        dir_list = dirs.decode().strip().split("||")
        if not 'dirs' in current_list.keys():
             current_list['dirs'] = []
        for f in dir_list:
                #icon = self.get_file_icon(f)
                current_list['dirs'].append(f)

        with open(self.pinned_list,'w') as f:
                json.dump(current_list,f,indent=4)
        self.make_menu()

    def pin_file(self,*args):
        current_list = self.get_pinned()
        if not current_list:
                current_list = OrderedDict()
                current_list['files'] = []
                f = open(self.pinned_list,'w')
                f.write("")
                f.close()
        if not args[-1]:
                cmd = "zenity --file-selection --separator || --multiple "
                files = self.run_cmd(cmd.split())
        else:
                files = args[-1]

        file_list = []
        if not files: return None
        file_list = files.decode().strip().split("||")
        if not 'files' in current_list.keys():
            current_list['files'] = []
        for f in file_list:
                #icon = self.get_file_icon(f)
                current_list['files'].append(f)

        with open(self.pinned_list,'w') as f:
                json.dump(current_list,f,indent=4)
        self.make_menu()

    def remove_all_pinned(self,*args):
        try:
            #os.unlink(self.pinned_list)

            with open(self.pinned_list) as f:
                pinned = json.load(f)
            pinned.pop('files')       
            with open(self.pinned_list,'w') as f:
                    json.dump(pinned,f,indent=4)
        except:
            pass
        finally:
            self.make_menu()

    def remove_pinned(self,*args):
        key = args[-1]
        pinned = self.get_pinned() 
        if not pinned: return
        cmd_str = "zenity --forms --add-combo Remove --combo-values"
        vals = "|".join(pinned[key])
        cmd = cmd_str.split() + [vals]
        item = self.run_cmd(cmd)
        if item: 
            path = item.decode().strip()
            index = pinned[key].index(path)
            pinned[key].pop(index)
            with open(self.pinned_list,'w') as f:
                json.dump(pinned,f,indent=4)
            self.make_menu()

    def add_recent(self,*args):
        cmd = "zenity --file-selection --separator || --multiple "
        files = self.run_cmd(cmd.split())
        file_list = []
        if not files: return
        file_list = files.decode().strip().split("||")
        items = ['file://' + f for f in file_list]
        for f in items: gtk.RecentManager().get_default().add_item(f)

    def clear_recent(self,*args):
        try:
            gtk.RecentManager.get_default().purge_items()
            self.make_menu()
        except:
            pass

    def open_item(self,*args):
        #self.run_cmd(['xdg-open',args[-1]]) 
        if args[-1].endswith('.desktop'):
            desk_file = Gio.DesktopAppInfo.new_from_filename(args[-1])
            return desk_file.launch_uris()
        return subprocess.Popen(['xdg-open',args[-1]])

    def quit(self,*args):
        gtk.main_quit()

    def run_cmd(self, cmdlist):
        """ utility: 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, *args):
        """ closes indicator """
        gtk.main_quit()


def main():
    """ defines program entry point """
    indicator = FilesIndicator()
    indicator.run()

if __name__ == '__main__':
  try:
    main()
  except  KeyboardInterrupt:
    gtk.main_quit()

Konfiguracje

Wskaźnik jest konfigurowany za pomocą dwóch plików Json przechowywanych w katalogu osobistym użytkownika.

~/.files_indicator.json kontroluje interfejs użytkownika, długość pozycji menu i maksymalną liczbę w menu ostatnich plików.

{
    "name_length": 30,
    "max_items": 10
}

~/.pinned_files.jsonKontroluje listy przypiętych plików i folderów. Każdy element jest listą / tablicą.

{
    "dirs": [
        "/home/xieerqi/\u56fe\u7247/Wallpapers"
    ],
    "files": [
        "/home/xieerqi/work_in_progress/videonauth_code.py",
        "/home/xieerqi/work_in_progress/spin_button.py"
    ]
}
Sergiy Kolodyazhnyy
źródło
Wow, pod wrażeniem, że stworzyłeś również rozwiązanie tego problemu! : D
Ads20000,
@ Ads20000 Dzięki :) Ten wskaźnik pierwotnie miał być przeznaczony tylko dla najnowszych plików. Kiedy zobaczyłem pytanie, pomyślałem, że fajnie byłoby dodać tę funkcję do wskaźnika, a ponadto było bardzo proste do wdrożenia - zabrało mi prawie jeden poranek i 2 filiżanki kawy :)
Sergiy Kolodyazhnyy
Twoja praca również przekształciła się w OMG! Ubuntu! artykuł ! : D
Ads20000,
Tak, widziałem to :)
Sergiy Kolodyazhnyy
0

Okej, chłopaki, właśnie zrobiłem instalując Ubuntu-Gnome i włączając rozszerzenie „Miejsca” w narzędziu Tweak i otrzymałem je. Muszę powiedzieć, że Ubuntu Gnome wygląda znacznie lepiej niż Unity

Zobacz zakładkę „Lugares”

Ulises CT
źródło
Mądry wybór. Od początku było oczywiste, że skłaniasz się ku korzystaniu z GNOME, ponieważ jest on bardziej znany z CentOS. Nawiasem mówiąc, w CentOS używają GNOME Flashback. Ma być wizualnie podobny do poprzedniej wersji, ale używać nowszej technologii. Co do Unity, może nie być dla wszystkich, chociaż osobiście bardzo nie lubię GNOME za ciągłe usuwanie funkcji i komplikowanie rozwoju.
Sergiy Kolodyazhnyy
Tak, dokładnie jestem „noob” w Linuksie lub „przestarzały”, jak wolisz to powiedzieć. Mam na myśli, że zawsze korzystałem z terminala dla serwerów w CentOS i niewiele graficznych rzeczy, nie wiedziałem, że istnieją różne opcje graficzne, takie jak Unity i Gnome, po prostu myślałem, że Ubuntu może wyglądać tylko tak, jak robi to z pakiet do pobrania ubuntu.com, CentOS tak, jak robi to z oficjalnej strony internetowej itp. Nie wiedziałem, że możesz mieć różne opcje graficzne. Dobrze się uczyć. @Serg
Ulises CT
Pozwól, że zadam ci to pytanie: Jeśli absolutnie musiałeś korzystać z pulpitu Unity, jakie inne rzeczy chciałbyś mieć? (Oczywiście staram się badać pomysły na przyszłe zastosowania :)
Sergiy Kolodyazhnyy
jedyną rzeczą, o której mogę myśleć, jest karta „Miejsca” lub „Aplikacje” (których tak naprawdę nie używam), reszta jest dostępna również w Unity. Chyba nie lubię z gnome tego, że w menu aplikacji muszę kliknąć przycisk w większości programów (typowy plik, edycja itp. menu)
Ulises CT