QFileSystemModel — Обнаружение пустой папки (с фильтром ‘AllDirs’)?

#qt #user-interface #qt4 #qtruby

#qt #пользовательский интерфейс #qt4 #qtruby

Вопрос:

Я использую Qt 4.6 в Ruby (через QtRuby) и пытаюсь создать диалоговое окно выбора общего каталога, в котором отображается небольшой символ «загрузка», пока запрашивается файловая система и обновляется дерево каталогов (QTreeView).

ОБНОВЛЕНИЕ: я должен сказать, что анимация работает не так, как ожидалось, есть ли другой способ обнаружения этих событий (загрузка, loaded)? Смотрите «На другом примечании» ниже.

Мне удалось подключить событие «загружены новые каталоги» через rowsInserted сигнал используемой QFileSystemModel, работает довольно нормально. Я также могу перехватить событие «загрузка новых каталогов» с помощью rowsAboutToBeInserted сигнала. Тем не менее, анимация, которую я пытаюсь воспроизвести (простой анимированный GIF для обозначения прогресса, загруженный в QMovie), воспроизводится, даже если каталог, который был «расширен», пуст. Вот код, который я использую :

 # FileSystemModel extension which shows a 'busy' animation
# in a given Qt::Label
class FileSystemModelEx < Qt::FileSystemModel

  # Slot declarations
  slots "handle_ready(QModelIndex, int, int)"
      slots "handle_busy(QModelIndex, int, int)"

  # Parametrised constructor, initializes fields
  def initialize(p_parent, p_label, p_busy_icon, p_ready_icon)

      # Call superclass constructor
      super(p_parent)

      # Set instance vars
      @label = p_label
      @busy_icon = p_busy_icon
      @ready_icon = p_ready_icon

      # Connect 'finished loaded' event
      Qt::Object.connect(self,
                        SIGNAL('rowsAboutToBeInserted(QModelIndex, int, int)'),
                        self,
                        SLOT('handle_busy(QModelIndex, int, int)'))

      # Connect 'loading' event
      Qt::Object.connect(self, 
                        SIGNAL('rowsInserted(QModelIndex, int, int)'),
                        self,
                        SLOT('handle_ready(QModelIndex, int, int)'))
  end

  # Loading finished event, changes icon state to ready
  def handle_ready(p_index, p_start, p_end)
      set_icon(false)   

      puts "    done - loaded #{rowCount(p_index)} folders"
  end

  # Loading started event, changes icon state to busy
  def handle_busy(p_index, p_start, p_end)
      set_icon(true)

      path = fileInfo(p_index).canonicalFilePath
    puts "Loading . . . path = '#{path}'"
  end

  # Overriden start loading event
  def fetchMore(p_index)
      handle_busy(p_index, nil, nil)
      super(p_index)
  end

  # Utility method, switches icons, depending on a given state
  def set_icon(p_busy) 
      movie = (p_busy ? @busy_icon : @ready_icon)
      @label.setMovie(movie)
      movie.start
  end   

end # class FileSystemModelEx
  

Мой вопрос был бы таким: как я могу запретить воспроизведение анимации, если загруженная папка пуста? Нельзя предварительно отфильтровать пустые каталоги, не так ли?

С другой стороны, существует ли другой способ реализации таких обработчиков событий ‘loading’ / ‘loaded’, кроме описанного выше? Я просмотрел сигналы, виртуалы ( fetchMore и canFetchMore , безрезультатно), просканировал источник, но я не могу связаться с вызовом, который отправляет поток в поисках получения большего количества файлов. Переопределение event или timerEvent не помогает.

Для завершения, вот QFileSystemModel, который я также использую:

 # Creates a FileSystemModel which display folders only
def create_model
    @model = FileSystemModelEx.new(self, 
                @form.iconPlaceholderDir, 
                @loading_icon, @folder_icon)

    @model.setReadOnly(true)
    @model.setFilter(Qt::Dir::NoDotAndDotDot | Qt::Dir::AllDirs)
    @model.setRootPath(Qt::Dir.rootPath)


    @form.shellTreeView.setModel(@model)
end
  

Буду признателен за любую помощь, заранее спасибо!
Я могу предоставить дополнительную информацию, если возникнет необходимость, без проблем.

Ответ №1:

Вам следует попробовать подключить directoryLoaded(const QStringamp;) слот модели. Это сигнализирует, когда каталог был полностью обработан.

Пример приложения с qt4-ruby (2.1.0), построенного на Ruby 1.8.7 и Qt 4.7.3

 #!/usr/bin/ruby -w
require 'Qt4'

class MyObject < Qt::Object
    slots "mySlot(QString)"
    def mySlot(path)
        print "Done loading ", path, "n"
    end
end

a = Qt::Application.new(ARGV)
m = Qt::FileSystemModel.new
v = Qt::TreeView.new
m.setRootPath("/")
v.setModel(m)
o = MyObject::new
Qt::Object.connect(m, SIGNAL('directoryLoaded(QString)'), o, SLOT('mySlot(QString)'))
v.show
a.exec
  

(Будьте добры, это моя самая первая ruby «программа» …)

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

1. Я был вне себя от радости, а затем я просто увидел: «Эта функция была введена в Qt 4.7», я могу использовать только Qt 4.6 (после некоторых усилий по ее запуску!), Поскольку «последние» привязки QtRuby (2.1.0, обновленный 2010) обеспечивают совместимость только с 4.6. Спасибо за ваш вклад, высоко ценится!

2. Я только что попробовал с примером кода, который я опубликовал, и никаких проблем не видно (кроме того факта, что я не знаю Ruby 🙂 ). qt4-ruby отлично собран на основе Qt 4.7.3 (единственная версия, которую я установил).

3. Это действительно выглядит довольно хорошо, я полагаю, вы не в Windows, верно? У меня возникли проблемы с получением QtRuby для использования . библиотеки DLL из Qt 4.7.3 есть мысли по этому поводу? Вот сообщение в блоге, которое я написал, в котором описывается (болезненный) способ установки QtRuby в Windows и привязки его к поставляемым 4.6.1 .dll: dr1ku.posterous.com/qt-461-ruby-187-on-win32 . Мне было бы очень интересно узнать, как вы заставили QtRuby 2.1.0 хорошо работать с Qt 4.7.3. Еще раз спасибо!

4. Нет, я на Linux. Использование Qt4 Ruby . библиотеки DLL, созданные в Qt 4.6, не будут работать с Qt 4.7. Не уверен, насколько легко было бы собрать qt4-ruby в Windows — может сработать, поскольку он основан на cmake, но у меня нет никакого опыта в этом.

5. Да, существует установщик, который довольно давно не обновлялся ( vision.eng.shu.ac.uk/mmvlwiki/index.php / … ), в нем использовался Qt 4.3. Думаю, я мог бы попытаться связаться с автором, чтобы помочь бедным разработчикам, которым (все еще) нравится их Win32 🙂 Спасибо за ответ, он должен быть принят. Я мог бы задать новый вопрос относительно другого события (‘loading’), не уверен, что переопределение fetchMore в порядке.