Russian Qt Forum

Qt => Вопросы новичков => Тема начата: koldun90 от Июль 12, 2014, 07:52



Название: отображение примонтированых устройств
Отправлено: koldun90 от Июль 12, 2014, 07:52
Здравствуйте скажите вот допустим когда я отображаю модель в линуксе

Код:
model1=new QFileSystemModel();
model1->setRootPath(QDir::currentPath());
model1->setFilter(QDir::AllDirs | QDir::Files |QDir::NoDotAndDotDot);
model1->setReadOnly(false);
 
ui->treeview->setModel(model1)


Проблема в том что когда я отображаю данную модель в windows там как бы изначально отображается полная файловая система (диск с допустим, вставленная флешка и тд).

А в линуксе отображается только каталог "/mnt".

Так что мне нужно сделать чтобы в линуксе файловая модель отображалась также как и в windows 7?
Мне вообще нужно сделать так чтоб в линуксе отображался каталог ("/"),а затем чуть ниже вставленная флешка( ее метка тома)
и допустим другие диски.
Подскажите что нужно переопределять и тд итп...

p.s вроде можно использовать dbus, но какие конкретно использовать(методы библиотеки) я не знаю


Название: Re: отображение примонтированых устройств
Отправлено: Командор от Июль 12, 2014, 13:14
Здравствуйте! Да, нужно использовать dbus (или hal, но в линуксе он практически везде выпилен).
Я делал так:

Код
C++ (Qt)
#include <QtDBus>
#define UD_DBUS_SERVICE                 "org.freedesktop.UDisks"
#define UD_DBUS_PATH                    "/org/freedesktop/UDisks"
#define UD_DBUS_INTERFACE_DISKS         "org.freedesktop.UDisks"
#define UD_DBUS_INTERFACE_DISKS_DEVICE  "org.freedesktop.UDisks.Device"
#define UD_DBUS_DEVICES_PREFIX          "/org/freedesktop/UDisks/devices/"
 
void DeviceManager::getData()
{
   QDBusInterface* UDisksInterface = new
           QDBusInterface(UD_DBUS_SERVICE, UD_DBUS_PATH,
                          UD_DBUS_INTERFACE_DISKS,
                          QDBusConnection::systemBus(), this);
 
   QDBusReply <QList <QDBusObjectPath> > objectPathList = UDisksInterface->call("EnumerateDevices");
   if (objectPathList.isValid()) {
       foreach (QDBusObjectPath pathDevice, objectPathList.value()) {
           QDBusInterface deviceInterface(UD_DBUS_SERVICE, pathDevice.path(),
                                          UD_DBUS_INTERFACE_DISKS_DEVICE,
                                          QDBusConnection::systemBus(), this);
           QVariant idUsage = deviceInterface.property("IdUsage");
           if (idUsage.isValid()) {
               if (idUsage.toString() == "filesystem") {
                   devicePathList << pathDevice.path().section('/', -1);
                   mountPathList << deviceInterface.property("DeviceMountPaths").toString();
                   QVariant idType = deviceInterface.property("IdType");
                   if (idType.isValid())
                       fileSystemList << idType.toString();
                   else
                       fileSystemList << "";
                   QVariant idLabel = deviceInterface.property("IdLabel");
                   if (idLabel.isValid()) {
                       if (!idLabel.toString().isEmpty()) {
                           labelDiskList << idLabel.toString();
                           diskNameList << idLabel.toString();
                       }
                       else {
                           labelDiskList << "";
                           diskNameList << devicePathList.last();
                       }
                   }
                   QVariant deviceIsHard = deviceInterface.property("DeviceIsSystemInternal");
                   if (deviceIsHard.isValid()) {
                       if (deviceIsHard.toBool()) {
                           typeDiskList << "drive-harddisk";
                       }
                       else {
                           QVariant deviceIsDrive = deviceInterface.property("DeviceIsDrive");
                           if (deviceIsDrive.isValid()) {
                               if (deviceIsDrive.toBool()) {
                                   QVariant driveMediaCompatibility = deviceInterface.property("DriveMediaCompatibility");
                                   if (driveMediaCompatibility.isValid()) {
                                       QStringList mediaTypes = driveMediaCompatibility.toStringList();
                                       if (!mediaTypes.filter("optical").isEmpty())
                                           typeDiskList << "media-optical";
                                       else if (!mediaTypes.filter("flash").isEmpty())
                                           typeDiskList << "drive-removable-media-usb-pendrive";
                                       else if (!mediaTypes.filter("floppy").isEmpty())
                                           typeDiskList << "media-floppy";
                                       else
                                           typeDiskList << "drive-harddisk";
                                   }
                               }
                               else {
                                   if (deviceInterface.property("DriveConnectionInterface").toString() == "usb")
                                       typeDiskList << "drive-removable-media-usb-pendrive";
                                   else
                                       typeDiskList << "drive-harddisk";
                               }
                           }
                       }
                   }
               }
           }
       }
 

После этого нужно как-то списки devicePathList, typeDiskList , labelDiskList прокинуть в модель.
У меня она самопальная, так что проще. А вот как быть с QFileSystemModel не знаю, наверное, нужно наследоваться и переопределять  QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ), допустим, если index указывает на корень, то отобразить корень и, например, labelDiskList (при этом отобразиться либо метка либо название устройства sda..).

А что за файл-менеждер, если не секрет? Каковы цели, возможности, открытый/закрытый или просто потренироваться? А то я тоже делаю файл-менеждер. Впрочем, я пошел иначе, отказался не только от QFileSystemModel, но и от Qt-х вьюверов, слабоваты они.


Название: Re: отображение примонтированых устройств
Отправлено: kambala от Июль 12, 2014, 13:15
model1->setRootPath("/");


Название: Re: отображение примонтированых устройств
Отправлено: Командор от Июль 12, 2014, 13:22
model1->setRootPath("/");

В этом случае просто отобразиться корень файловой системы. А человеку нужно как в Dolphin, например. Т.е. чтобы отдельно отобразились разделы, сидюки, флешки и т.д. При этом нужно, чтобы флешку можно было примонтировать/отмонтировать.


Название: Re: отображение примонтированых устройств
Отправлено: kambala от Июль 12, 2014, 14:16
к сожалению, в линуксе не силен :)


Название: Re: отображение примонтированых устройств
Отправлено: Bepec от Июль 12, 2014, 14:42
Файловая система винды - это структурированное разбиение на "диски/приводы и прочая".
Файловая система linux - хрен знает что с общим корнем и содержимым без особой структуры.

Так что чтобы отобразить разделы сидюки и флешки, вам нужно самому анализировать и отображать это. Приводя хаотический общий корень в упорядоченную структуру.


Название: Re: отображение примонтированых устройств
Отправлено: kuzulis от Июль 12, 2014, 15:28
ТС, попробуй этот класс: https://codereview.qt-project.org/#/c/73945/


Название: Re: отображение примонтированых устройств
Отправлено: vbv от Июль 12, 2014, 18:39
Во первых: структуры файловых систем разные.
    И таким образом "в лоб" так сделать не получится.

Как варианты:
1. Унаследовать модель и на основании монтирования вынести части fs в корень модели.
2. Поставить proxymodel в которой сделать преобразования как в п.1.
3. сделать окно из 2-х частей где дополнительно будут отображаться точки монтирования
при клике на которые будет производится монтирование/размонтирование и переход в этом место fs в модели и TreeView/TreeWidget соответственно.

По другому не вижу, как этом можно реализовать.
Хотя можно полностью реализовать свою модель.

Не по вопросу:
PS: Как по мне так, *nix структура гораздо эффективнее и понятнее чем форточная. И когда я вижу подобного рода реализации - вызывает аллергию.
Ну как может находится точка входа в VFS, ниже корня самой файловой системы.
Попадая под форточки - это немножко бесит.

Пример:
Монтирован /home  и у меня в домашнем подкаталоге есть каталог ~/home - глядя на подобное представление - вопрос так в каком же месте фс я в данный момент нахожусь?
И в результате приходиться спускаться от root (/) например что-бы попасть в /home/tmp а не в ~/tmp (есть у меня и такие подкаталоги.) или на оборот. А если я уже в tmp где мне потом искать сохраненный файл, т.е. нужно подняться на уровень вверх и посмотреть, куда же я таки сохраняю данные.
А в модели можно вынести в корень только, точки монтирования, как ссылки к реальной mountpoint - хотя это и есть /mnt.
Или реализовать механизм Bookmark где выставлять желаемые, быстрые точки входа в фс.
Как вариант, даже можно перемонтировать mnt в ~/mnt.

И еще, эта мулечка, которя монтирует в /media - совсем страшная штука. Черти куда цепляет диск, и где его искать.....
Пример: под кедами монтируется диск и подключается в авто-подключении /media/чего-то/там. Надо открыть dolphin'ом посмотреть куда же его таки прицепило сие несчастье и после этого в консоле cd /media/чего-то/там.... Ну в самом деле это не вариант. Причем методов авто-монтирования - тьма. А точки входа можно увидеть только как результат выполнения mount из консоли. Ну или путем "прямо спросить у ядра" через API.


Название: Re: отображение примонтированых устройств
Отправлено: Bepec от Июль 12, 2014, 19:52
to vdv: вы определитесь.
Вас воротит от Win реализации, а доводы о безумности вы приводите с Unix реализацией :D


Название: Re: отображение примонтированых устройств
Отправлено: vbv от Июль 13, 2014, 06:20
to vdv: вы определитесь.
Вас воротит от Win реализации, а доводы о безумности вы приводите с Unix реализацией :D

to:Bepec
Не подворачивайте пожалуйста.
Против *nix реализации я ничего не имею, я имею "против" втягивания в *nix системы видновой реализации.
Второе: система автомонтирования - это отдельная песня. т.к. Монтируем автоматом, отмонтируем руками...
Плюс я написал как получать точки монтирования, а не о самом механизме монтажа.
К тому-же к самому вопросу, это уже не относится - "Хочешь делай".
А доводы о по Вашему "безумности Unix" я не привожу, а утверждаю о не корректности под *nix ориентироваться на какой-то один принцип автомонтирования. Который опирается на дополнения. Или придется требовать зависимости от сторонних библиотек и опираться на их функции. Причем нет гарантии, что эти библиотеки окажутся на клиентской машине предустановленны. Тем более не ориентироваться на автомонтирование через DE (KDE и пр.).
А в общем случае, систем автомонтирования много и для разных целей используются разные. (пример: монтаж ресурса на сервере и отключении его по завершению работы с ним, против пользовательской сессии когда сам пользователь решает когда нужен ему этот ресурс когда уже нет)

PS:
монтирую по прежнему:
mount /dev/sda1 /mnt
а размонтирую по прежнему:
umount /mnt
и смотрю, чего намонтировано:
mount
И проблем нет, и все нравится.


Название: Re: отображение примонтированых устройств
Отправлено: koldun90 от Июль 13, 2014, 11:49
Здравствуйте! Да, нужно использовать dbus (или hal, но в линуксе он практически везде выпилен).
Я делал так:

Код
C++ (Qt)
#include <QtDBus>
#define UD_DBUS_SERVICE                 "org.freedesktop.UDisks"
#define UD_DBUS_PATH                    "/org/freedesktop/UDisks"
#define UD_DBUS_INTERFACE_DISKS         "org.freedesktop.UDisks"
#define UD_DBUS_INTERFACE_DISKS_DEVICE  "org.freedesktop.UDisks.Device"
#define UD_DBUS_DEVICES_PREFIX          "/org/freedesktop/UDisks/devices/"
 
void DeviceManager::getData()
{
   QDBusInterface* UDisksInterface = new
           QDBusInterface(UD_DBUS_SERVICE, UD_DBUS_PATH,
                          UD_DBUS_INTERFACE_DISKS,
                          QDBusConnection::systemBus(), this);
 
   QDBusReply <QList <QDBusObjectPath> > objectPathList = UDisksInterface->call("EnumerateDevices");
   if (objectPathList.isValid()) {
       foreach (QDBusObjectPath pathDevice, objectPathList.value()) {
           QDBusInterface deviceInterface(UD_DBUS_SERVICE, pathDevice.path(),
                                          UD_DBUS_INTERFACE_DISKS_DEVICE,
                                          QDBusConnection::systemBus(), this);
           QVariant idUsage = deviceInterface.property("IdUsage");
           if (idUsage.isValid()) {
               if (idUsage.toString() == "filesystem") {
                   devicePathList << pathDevice.path().section('/', -1);
                   mountPathList << deviceInterface.property("DeviceMountPaths").toString();
                   QVariant idType = deviceInterface.property("IdType");
                   if (idType.isValid())
                       fileSystemList << idType.toString();
                   else
                       fileSystemList << "";
                   QVariant idLabel = deviceInterface.property("IdLabel");
                   if (idLabel.isValid()) {
                       if (!idLabel.toString().isEmpty()) {
                           labelDiskList << idLabel.toString();
                           diskNameList << idLabel.toString();
                       }
                       else {
                           labelDiskList << "";
                           diskNameList << devicePathList.last();
                       }
                   }
                   QVariant deviceIsHard = deviceInterface.property("DeviceIsSystemInternal");
                   if (deviceIsHard.isValid()) {
                       if (deviceIsHard.toBool()) {
                           typeDiskList << "drive-harddisk";
                       }
                       else {
                           QVariant deviceIsDrive = deviceInterface.property("DeviceIsDrive");
                           if (deviceIsDrive.isValid()) {
                               if (deviceIsDrive.toBool()) {
                                   QVariant driveMediaCompatibility = deviceInterface.property("DriveMediaCompatibility");
                                   if (driveMediaCompatibility.isValid()) {
                                       QStringList mediaTypes = driveMediaCompatibility.toStringList();
                                       if (!mediaTypes.filter("optical").isEmpty())
                                           typeDiskList << "media-optical";
                                       else if (!mediaTypes.filter("flash").isEmpty())
                                           typeDiskList << "drive-removable-media-usb-pendrive";
                                       else if (!mediaTypes.filter("floppy").isEmpty())
                                           typeDiskList << "media-floppy";
                                       else
                                           typeDiskList << "drive-harddisk";
                                   }
                               }
                               else {
                                   if (deviceInterface.property("DriveConnectionInterface").toString() == "usb")
                                       typeDiskList << "drive-removable-media-usb-pendrive";
                                   else
                                       typeDiskList << "drive-harddisk";
                               }
                           }
                       }
                   }
               }
           }
       }
 

После этого нужно как-то списки devicePathList, typeDiskList , labelDiskList прокинуть в модель.
У меня она самопальная, так что проще. А вот как быть с QFileSystemModel не знаю, наверное, нужно наследоваться и переопределять  QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ), допустим, если index указывает на корень, то отобразить корень и, например, labelDiskList (при этом отобразиться либо метка либо название устройства sda..).

А что за файл-менеждер, если не секрет? Каковы цели, возможности, открытый/закрытый или просто потренироваться? А то я тоже делаю файл-менеждер. Впрочем, я пошел иначе, отказался не только от QFileSystemModel, но и от Qt-х вьюверов, слабоваты они.
здравствуйте я монтирую командой mount /mnt
Работаю в мсвс
файл менеджер почти доделал (осталось вот реализовать показ примонтированых устройств )
если можно отправьте вашу почту или скайп для связи с вами в личку