Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Python: Разработка GUI > MIME-type & icons


Автор: DarkTroll 7.5.2010, 15:31
Здравствуйте. 
Я решил написать интереса ради файл-менеджер на PyQt. Для отображения содержимого каталогов выбрал QListWidget. Все бы хорошо, да не могу написать эффективный алгоритм ассоциации определенному типу файлов определенной иконки. 
Процесс я представляю так:
1. Получаю список файлов в директории средствами модуля os
2. Создаю цикл for и в нем:
    a) Для каждого элемента списка определяю его MIME-тип
    b) По MIME-типу определяю иконку и назначаю ее соответствующему файлу.

Но все это ОЧЕНЬ медленно работает при большом количестве файлов в каком-либо каталоге. Например, для отображения содержимого /usr/bin (около 2,5 тысяч файлов) уходит 16 секунд, а если без определения типа файла, то меньше секунды. Причем тормозит не отрисовка элементов компонента QListWidget, а именно определение MIME-типа.

Подскажите пожалуйста, где можно упростить, оптимизировать мой корявый код или подскажите, как можно иначе реализовать ассоциацию иконки файлу?

Вот листинги соответствующих функций:

list_print: функция, отображающая содержимое каталога:
Код

def list_print(self, path_): # функция, отображающая содержимое каталога
    items_ = pyfileman.sorted_list(path_) # список, содержащий упорядоченный перечень имен файлов в директории, указанной в переменной path_
    for j in items_: # создаю цикл для перебора списка
        mime_ = mime.get_mime(j) #определяю тип файла
        mime_icon_path = mime.get_mime_icon(mime_, os.getcwd(), j) # указываю путь к иконке, соответствующей этому типу
        icon = QtGui.QIcon(mime_icon_path) # создаю иконку
        i = QtGui.QListWidgetItem(icon, j, self.listwidget) # создаю элемент списка с иконкой и именем файла
        self.listwidget.addItem(i) # добавляю его в QListWidget.


get_mime: функция, определяющая MIME-тип:
Код

import mimetypes 
def get_mime(file): #Функция, определяющая MIME-тип файла, путь к которому указан в переменной file
    mimetypes.init()
    ext = u'.%s' % file.split('.')[-1]
    try:
        mime = mimetypes.types_map[ext]
    except:
        mime = False
    return mime

get_mime_icon: функция, назначающая иконку файлу
Код

def get_mime_icon(mime, path): # функция, назначающая иконку файлу. mime - MIME-тип, path - путь к файлу
    mimetype = str(mime)
    if mimetype == 'application/pdf': #если тип PDF 
        return '/.media/mime_icons/pdf.png' # то возвращаем путь к соответствующей иконке
    elif mimetype.startswith('image'):
        return '/.media/mime_icons/image.png'
    elif mimetype.startswith('audio'):
        return '/.media/mime_icons/audio-x-generic.png'
    elif mimetype.find('application/x-font-ttf') != -1:
        return '/.media/mime_icons/font_truetype.png'
        .......
        .......
    else:
        return '/.media/mime_icons/unknown.png'


Автор: Amp 7.5.2010, 17:23
Определять mime-type только для видимых айтемов у ListWidget + некоторый запас. mime-type-ы в процессе скроллинга запоминать и кэшировать. Вроде krusader так и делает.

Автор: DarkTroll 7.5.2010, 18:07
Amp, идея, кстати, интересная! Попробую так сделать позже, это должно еще ускорить отрисовку. Но решение моей проблемы (очень простое) в другом: я при каждом обращении к функции get_mime вызывал mimetypes.init(). Именно поэтому все и тормозило. Устранил - теперь все летает так же быстро как и без иконок! 

Автор: andreyVL 8.5.2010, 08:55
DarkTroll, поделись скриптом гюи

уже не надо.

Автор: DarkTroll 13.5.2010, 15:57
andreyVL, что ты имеешь ввиду?

Автор: andreyVL 13.5.2010, 17:14
отбой тревоги. уже сделал

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)