Как добавить элемент в список файлов GTK «недавно использованных» из Python?

#python #gtk #pygtk #gtk3

#python #gtk #pygtk #gtk3

Вопрос:

Я пытаюсь добавить в список «недавно использованных» файлов из Python 3 в Ubuntu.

Я могу успешно прочитать список недавно использованных файлов следующим образом:

 from gi.repository import Gtk
recent_mgr = Gtk.RecentManager.get_default()
for item in recent_mgr.get_items():
    print(item.get_uri())
  

При этом выводится тот же список файлов, который я вижу, когда смотрю на «Недавние» в Nautilus или просматриваю «Недавно использованное» место в диалоговом окне «Файл» таких приложений, как GIMP.

Однако, когда я попытался добавить подобный элемент (где /home/laurence/foo/bar.txt находится существующий текстовый файл)…

 recent_mgr.add_item('file:///home/laurence/foo/bar.txt')
  

… файл не отображается в разделе «Последние» Nautilus или в диалоговых окнах файлов. Он даже не отображается в результатах, возвращаемых get_items() .

Как я могу добавить файл в список недавно использованных файлов GTK из Python?

Комментарии:

1. @oldtechaa Список последних файлов, которые видит Nautilus, и диалоговое окно файла в других приложениях (включая GIMP, Inkscape и даже Chrome) кажутся идентичными. Многие приложения по умолчанию фильтруют список по своему типу файлов, но если вы измените фильтр на «Все файлы», вы увидите точно такой же список, который показывает Nautilus, и который отображается кодом в вопросе.

2. Что add_item() возвращает?

3. Возвращает вызов @andlabs add_item() True . (На самом деле, is, кажется, всегда возвращается True , даже если URI, который я передаю ему, не существует или полная бессмыслица. Единственное исключение — если я передаю его не- str . Затем он возникает TypeError .)

4. Возможно, нет, хотя, увидев, что add_item() возвращает true, можно предположить, что это что-то другое. Может ли это каким-то образом получить неправильный файл истории? Если он возвращает true, это говорит о том, что ему удалось его где-то записать.

5. @andlabs Это связано с использованием асинхронного кода, чтобы избежать g_content_type_guess блокирования потока программы, я думаю, см. Мой ответ ниже.

Ответ №1:

A Gtk.RecentManager должен выдать changed сигнал для записи обновления в закрытый атрибут класса C . Чтобы использовать RecentManager объект в приложении, вам нужно запустить цикл событий, вызвав Gtk.main :

 from gi.repository import Gtk

recent_mgr = Gtk.RecentManager.get_default()
uri = r'file:/path/to/my/file'
recent_mgr.add_item(uri)
Gtk.main()
  

Если вы не вызываете Gtk.main() , changed сигнал не передается, и ничего не происходит.

Чтобы ответить на запрос @andlabs, причина RecentManager.add_item , по которой возвращается логическое значение, заключается в том, что g_file_query_info_async вызывается функция. Затем функция обратного gtk_recent_manager_add_item_query_info вызова собирает mimetype, имя приложения и команду в GtkRecentData структуру и, наконец, вызывает gtk_recent_manager_add_full . Источник находится здесь.

Если что-то пойдет не так, это произойдет уже после add_item завершения, поэтому метод просто возвращает True , если объект, из которого он вызывается, является a RecentManager , и если uri не NULL является; и False в противном случае.

В документации неточно указано:

Возвращает TRUE , если новый элемент был успешно добавлен в список недавно использованных ресурсов

поскольку возврат TRUE означает только то, что была вызвана асинхронная функция для обработки добавления нового элемента.

Как было предложено Лоуренсом Гонсалвесом, следующее выполняется псевдосинхронно:

 from gi.repository import Gtk, GObject

recent_mgr = Gtk.RecentManager.get_default()
uri = r'file:/path/to/my/file'
recent_mgr.add_item(uri)
GObject.idle_add(Gtk.main_quit)
Gtk.main()
  

Ответ №2:

Это мое решение (сценарий завершения) с таймером для завершения GTK.main() цикла

 #!/usr/bin/env python3

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib
import sys
import os
import subprocess

recent_mgr = Gtk.RecentManager.get_default()

if len(sys.argv) <= 1:
    paths = (os.getcwd(),)
else:
    paths = sys.argv[1:]

for path in paths:
    if os.path.exists(path):
        if path[0] != "/":
            path = os.getcwd()   "/"   path
        subprocess.call(["touch", "-a", path])
        uri = r"file:"   path
        recent_mgr.add_item(uri)

GLib.timeout_add(22, Gtk.main_quit, None)
Gtk.main()