В Qt3 была чудная возможность в диалоге открытия интегрировать виджет в котором осуществлять предпросмотра содержимого файла, в частность делать предпросмотр изображений. В Qt4 такую возможность убрали. Да, можно приделать при помощи ItemDelegate кастомное отображение для иконок, и тем самым осуществлять предпросмотр, но не всегда это бывает удобным. Следующий вариант: писать свою реализацию класса для диалога открытия/сохранения. Я же решил попробовать хитрый способ…
Я никоим образом не претендую на правду в последней инстанции и не рекомендую относить данный метод к рекомендуемым практикам программирования, но как вариант решения с минимальными затратами он очень хорошо себя показывает.
Итак смыл: наследовать свой класс от QFileDialog, в конструкторе при помощи findChild()
по имени искать контейнер в котором располагается виджеты для отображения иконок и быстрых ссылок, приводить его к нужному типу, создавать виджет для предпросмотра, добавлять его в контейнер, при смене файла обновлять содержимое.
Для того, что бы узнать какой контейнер используется (что бы произвести приведение типа) и его имя, нам потребуются исходники Qt, которые скачиваем с сайта Nokia:
http://qt.nokia.com, распаковываем, находим файл *qfiledialog.ui// и загружаем его в Qt Designer. После пары минут изучения находим, что контейнер это компонент типа QSplitter и имя у него - splitter
. Всё просто и лаконично.
Теперь создаём свой класс, наследуем его от QFileDialog
class MFileDialog : public QFileDialog
В теле класса обязательно ставим
Q_OBJECT
в секции private:
создаем прототип функции init()
- её будем вызвать из конструктора (если вы решитесь объявить их несколько), и указатель на экземпляр класса QLabel - его будем использовать для вывода миниатюры изображения:
private:
void init();
QLabel *_preview;
Да, я обычно использую для методов класса одну секцию private/public/etc
, а для переменных - другую. Так получается нагляднее.
Далее, сразу вспоминаем, что нам нужно обновлять предпросмотр при смене файла, для этого создадим слот - обработчик сигнала currentChanged(**QString**)
:
public slots:
void fileChanged(const QString &file);
Реализации методов init()
и fileChanged(**QString** &file)
в листинге ниже:
void MFileDialog::init()
{
_preview = 0;
// HACK: original file dialog in Qt4 does not have preview functinality
// Work well on 4.7.1
QSplitter *splitter = findChild<QSplitter*>("splitter");
if (splitter == 0)
{
return;
}
_preview = new QLabel();
QRect geomerty = _preview->geometry();
geomerty.setWidth(160); // Настройки геометрии, можно так же сделать что бы рамочка отображалась или что-то вроде
_preview->setGeometry(geomerty);
splitter->addWidget(_preview); // Собсвенно, добавляем наш виджет в контейнер
// подключаем обработчик сигнала currentChanged
connect(this, SIGNAL(currentChanged(QString)),
this, SLOT(fileChanged(QString)));
}
void MFileDialog::fileChanged(const QString &file)
{
if (_preview == 0)
{
return;
}
QPixmap pix(file);
if (pix.isNull())
{
_preview->setPixmap(QPixmap());
}
else
{
// Не зыбываем масштабировать изображение к размеру нашей области просмотра
QSize size = _preview->size();
pix = pix.scaled(size, Qt::KeepAspectRatio);
_preview->setPixmap(pix);
}
}
Не забываем в конструкторе вызвать init()
, а в деструктор поместить delete _preview
. И всё, примерно так это выглядит:

При этом, если даже не будет найдет разделитель с таким именем, диалог не поломается - просто не будет отображаться окошко предпросмотра.
Какие улучшения тут можно сделать? Я думаю как минимум такие:
- Установление ограничение на размер файла для которого будет автоматически делаться предпросмотр, ибо загрузка занимает время, а файлы могут быть оооочень большими (у меня, к примеру, есть такие которые не отрываются по причине нехватки памяти).
- Вместо QLabel использовать QToolButton и если файл слишком большой отрабатывать нажатие и делать принудительный предпросмотр, либо какие-то другие действия.
PS Кому нужны исходники, пишите на мыло.
Известно, что, без преувеличения, основа Qt это moc и их система метатипов. В базе метатипов зарегистрированы все простые C/C++ типы и все сложные Qt типы, часто этого бывает с головой достаточно для написания программ: при использовании QVariant и QSettings или при организации вызовов типа сигнал-слот…
Но бывает, что в качестве параметра сигнала нужно передавать свою структуру или класс, или преобразовывать свой тип в QVariant. Для этого нужно зарегистрировать свой тип перед первым использованием (можно в функции main()), примерно так:
qRegisterMetaType<PhotoFormat>("PhotoFormat");
После этого его можно использовать в качестве параметра в механизме сигнал-слот.
Следующим полезным шагом - приведение нашего типа к QVariant, для этого, в дополнение к предыдущему, в заголовочном файла где располагается объявление нашего типа (на самом деле - в любом месте, но так будет логичнее) нужно разместить такую конструкцию:
Q_DECLARE_METATYPE(PhotoFormat);
Всё, после этого можно использовать подобные конструкции:
QVariant var = qVariantFromValue(PhotoFotmat("Name", 23, 22));
PhotoFormat format = qVariantValue<PhotoFormat>(var);
Ну и последнее, сохранение и восстановление нашего класса при помощи QSettings. Для этого нужно, для начала, зарегистрировать потоковые операторы:
qRegisterMetaTypeStreamOperators<PhotoFormat>("PhotoFormat");
Далее, обычно в заголовочном файле, где объявлен класс, объявляются операторы <<
и >>
:
QDataStream &operator<<(QDataStream &out, const PhotoFormat &obj);
QDataStream &operator>>(QDataStream &in, PhotoFormat &obj);
Обращаю внимание - за пределами class {};
А реализация примерно такая:
QDataStream & operator <<(QDataStream &out, const PhotoFormat &obj)
{
QString name = obj.getFormatName();
QSizeF size = obj.getSize();
qreal dst1 = obj.getTopPateDistance();
qreal dst2 = obj.getNoseChinDistance();
out << name << size << dst1 << dst2;
return out;
}
QDataStream & operator >>(QDataStream &in, PhotoFormat &obj)
{
QString name;
QSizeF size;
qreal dst1;
qreal dst2;
in >> name >> size >> dst1 >> dst2;
obj.setFormanName(name);
obj.setSize(size);
obj.setTopPateDistance(dst1);
obj.setNoseChinDistance(dst2);
return in;
}
По сути, сериализация класса. Более подробная информация - на странице справки по классу QMetaType, и можно глянуть тут:
http://www.crossplatform.ru/?q=node/281
Делал тут небольшую работку, писал программку, которая позволяла таскать линии по холсту и формировать по его данным потом xml файл в заданном формате, который потом превращался в уровень для игры. Заказчик просил ObjectivC и целевая платформа Mac OS X, на мой вопрос о критичности ObjectvC ответил - не суть, предложил написать на Qt4, тем самым покроем, одним махом, три платформы: Linux/Windows/Mac, но будет нуанс - я только примерно знаю как собирать под Mac, в общем, подумав - согласились.
Работу, естественно, я делал под Linux, проверил сборку для Windows (опять таки - кросскомпиляция). Показал результаты (сборку под Win32 и скапченый видеоролик работы в Linux), заказчику понравилось, дальше пошла очередь запуска на Mac OS X…
Первым делом был скачан Qt SDK 2010.05 - бронебойно, но зато всё сразу есть. Собрать получилось без проблем (были ворнинги у линковщика на лишние пути, указанные через атрибут -L, которые реально не существуют, но тут камень в огород создателям SDK). А вот дальше встал вопрос - а как запускать приложение на машинах где нет Qt4? Под windows/linux, в случае распространения бинарников, можно просто положить необходимые dll/so рядом и исполняемым файлов, но в Mac OS X они распространяются в виде бандла (директория с определённой структурой и суффиксом .app). Так вот, что бы собрать всё нужные библиотеки в бандл, разработчики Qt сделали утилиту macdeployqt, которую, после сборки, достаточно натравить на полученное приложение так:
macdeployqt helloworld.app
Тут человек с ником Ayoy, тоже озадачивался подобными вопросами, и рассмотрел более подробно. Так же, он столкнулся с тем, что если используются библиотеки/фреймворки которые используют Qt, после обработки macdeployqt они будут продолжать ссылаться на системные, а не те, что в бандле. Что бы это исправить он написал скрипт на перл, которые позволяет это исправлять:
http://gist.github.com/109674
Чуть позже поставлю в виртуалку Mac OS X, посмотрю, может на будущее буду сам делать бандлы, а ещё заинтересовала кросс-компиляция для макоси :)
Замечание 1: Qt Creator (одна из последних git сборок)
При включенном отображении Outline в левой панели, при работе появляются значительные тормоза даже на небольших проектах (при моих 1024Мб RAM и Atom 1.6Гц). Решение: выбрать другой режим, тем более что в значительный промежуток времени эта панель вообще не нужна (убирается и вновь показывается при помощи Alt-0), да и есть мощный инструмент Locate (Ctrl-K)
Замечание 2: sshfs и не уходим в sleep
Я активно пользуюсь sshfs для подключения удалённых ресурсов, удобно, быстро, не нужно дополнительных плясок. Недавно стал наблюдать, что система при каких-то условиях перестала засыпать на нетбуке. Опытным путем выяснилось условие: ресурс, примонтированный при помощи sshfs, был отлючен с использованием опции lazy у fusermount (иначе ругался на Resource busy). При этом продолжал висеть процесс sshfs, его убийство после, опять позволяло уводить систему в sleep.
Вышла версия 0.5.0 программы Crowns для построения проекций крон деревьев. Скачать можно
тут
В этой версии, основные изменения, касающиеся функционала в целом:
- Добавлена возможность удалять подложку из проекта.
- Добавлена возможность экспорта параметров крон деревьев в формат, пригодный для обработки в математических программах типа Octave (100% проверено), Scilab (проверено частично), Mathlab (теоретически должно работать). Т.к. проекции теперь строятся при помощи кривых Безье, то при экспорта с точностью 0.1 выдаются и промежуточные точки для построения полной проекции, теоретически, после обработки данные будут пригодны для загрузки в GIS.
- Исправлена ошибка, при которой подложка не удалялась при открытии проекта без оной или создании нового проекта.
- Исправлена ошибка, при которой случайное нажатие клавиши Esc приводило к закрытию окна программы.
Другие изменения, касающиеся технических аспектов разработки:
- Исправлены вспомогательный скрипты для отстройки и паковки win32 версии из среды Linux.
- Был осуществлен переход на систему сборки CMake.
- Исправлено не критическое поведение с float типами при сохранении проекта: значения сохранялись как @Variant(..).
Полный список изменений:
ChageLog
На правах мемориза.
Тут лежит полная и последняя:
http://gcc.gnu.org/onlinedocs/ в различных форматах, берём то, что нужно, а в системе пользуемся
инфо
А здесь полезная информация от гентоводов:
http://en.gentoo-wiki.com/wiki/Safe_Cflags - безопасные флаги оптимизация для различных процессоров (далее по тексту - ссылки)
Многим знакомо цветовое пространство RGB (Red/Green/Blue), мне потребовалось же работать с входными данными пространства YUV, которое широко используется в семействе кодеков MPEG.
Потребовалось тут собрать для C++Builder DLL, наткнулся походу на такой мануал:
http://bcbjournal.org/articles/vol4/0012/Using_Visual_C_DLLs_with_CBuilder.htm
В мемориз, хотя, надеюсь, оно мне никогда не пригодится, собирать под винду, это ужас…
Полезная ссылка:
http://my.opera.com/Lex1/blog/flashblock-for-opera-9/
даны различные рецепты, в том числе очень удобный для Opera 10.5+: просто включить опцию EnableOnDemandPlugin, для чего нужно открыть настройки: opera:config#UserPrefs|EnableOnDemandPlugin, опция автоматически добавится, и можно её включить. Да, это будет работать для любых плагинов.
Сама новость на OpenNet:
http://www.opennet.ru/opennews/art.shtml?num=27979
Рабочий эксплоит:
http://sota.gen.nz/compat2/robert_you_suck.c
PS рабочий, в смысле, что у меня сработал отлично :)