Функция рекурсивного удаления папок не работает если в папке есть файлы только для чтения.
Функция QFile::remove() при попытке удалить такой файл возвращает false. Чтобы этого избежать нужно выставлять права для таких файлов. В Qt для этого есть функция
bool QFile::setPermissions ( const QString & fileName, Permissions permissions ) [static]
Таким образом окончательный вид функции удаления каталога имеет вид:
среда, 27 января 2010 г.
четверг, 21 января 2010 г.
Очистка каталога
void cleanFolder(const QString & folder)
{
QDir dir(folder);
//Получаем список файлов
QStringList lstFiles = dir.entryList(QDir::Files);
//Удаляем файлы
foreach (QString entry, lstFiles)
{
QString entryAbsPath = dir.absolutePath() + "/" + entry;
QFile::remove(entryAbsPath);
}
}
* This source code was highlighted with Source Code Highlighter.
вторник, 19 января 2010 г.
Подсветка кода для блога
Изначально я планировал в этом блоге писать о программировании на Qt. Однако сейчас на блоге больше всего постов о покере, Москве, пиве и прочем непотребстве.
Объясняю в чем секрет - отсутствие толковой подсветки кода. Те куски кода, что я помещал в блог имели столь ужасное форматирование и подсветку, что без содрогания читать программу просто невозможно. Я перепробовал множество подсветчиков, однако у всех были недостатки - кто-то по глупому делает подсветку, кто-то мутит с CSS, что вызывает трудности со вставкой кода.
Наконец я нашел приличный подсветчик: http://source.virtser.net
Он не использует CSS и делает подсветку аналогично Visual Studio.
Вот пример сгенеренного им кода.
На мой взгляд - лучшее решение для вставки кода в блог.
Объясняю в чем секрет - отсутствие толковой подсветки кода. Те куски кода, что я помещал в блог имели столь ужасное форматирование и подсветку, что без содрогания читать программу просто невозможно. Я перепробовал множество подсветчиков, однако у всех были недостатки - кто-то по глупому делает подсветку, кто-то мутит с CSS, что вызывает трудности со вставкой кода.
Наконец я нашел приличный подсветчик: http://source.virtser.net
Он не использует CSS и делает подсветку аналогично Visual Studio.
Вот пример сгенеренного им кода.
ApPhotoRobot::ApPhotoRobot(QWidget * parent )
: DirSelecter(tr("Applications - PhotoRobot"), parent)
{
lstlblPath.at(0)->setText(tr("Folder of Bars PhotoRobot"));
lstlblName.at(0)->setText(tr("Executable name of Bars PhotoRobot"));
leOut = new QLineEdit(this);
QLabel * lblOut = new QLabel(tr("Output folder for Bars Photorobot"), this);
QToolButton * btnBars = new QToolButton(this);
btnBars->setFixedSize(20, 20);
btnBars->setText("...");
connect(btnBars, SIGNAL(clicked()), this, SLOT(browseDir()));
mapBtnEdt[btnBars] = leOut;
grid->addItem(new QSpacerItem(1, 10, QSizePolicy::Fixed, QSizePolicy::Fixed), 5, 0);
grid->addWidget(lblOut, 6, 0, 1, 2);
grid->addWidget(leOut, 7, 0);
grid->addWidget(btnBars, 7, 1);
grid->setRowStretch(8, 1);
}
* This source code was highlighted with Source Code Highlighter.На мой взгляд - лучшее решение для вставки кода в блог.
понедельник, 7 декабря 2009 г.
Настоящий программист
Понравилась цитата:
Настоящий программист не использует буфер обмена. (с)
От себя добавлю - Настоящий программист использует наследование.
Настоящий программист не использует буфер обмена. (с)
От себя добавлю - Настоящий программист использует наследование.
среда, 2 декабря 2009 г.
Ваш код отстой
Ваш код – отстой, если он не работает
Ваш код – отстой, если он не поддаётся тестированию
Ваш код – отстой, если его трудно прочесть
Ваш код – отстой, если он непонятен
Ваш код – отстой, если он догматично следует ультрамодным framework ценою соблюдения хороших практик дизайна и имплементации
Ваш код – отстой, если в нём есть дублирование
Ваш код – отстой, если он не поддаётся тестированию
Ваш код – отстой, если его трудно прочесть
Ваш код – отстой, если он непонятен
Ваш код – отстой, если он догматично следует ультрамодным framework ценою соблюдения хороших практик дизайна и имплементации
Ваш код – отстой, если в нём есть дублирование
четверг, 26 ноября 2009 г.
Недалекий gcc
Сегодня случилось компилировать кусок с рекурсивным удалением каталогов под Linux.
Здесь про рекурсивное удаление
Компилятор gcc преподнес сюрприз. Не хотел компилировать безобидный кусок кода:
Пришлось за него самому создавать объект. В итоге код пришлось переписать в :
Здесь про рекурсивное удаление
Компилятор gcc преподнес сюрприз. Не хотел компилировать безобидный кусок кода:
int removeFolder(QDir & dir)То есть здесь идет рекурсивный вызов функции removeFolder(QDir &). В качестве параметра я передаю временный объект QDir, предполагая, что компилятор сможет получить ссылку на временный объект. Это не вызывает трудностей у MS Studio 2005, но повергает в шок gcc.
{
......
QString entryAbsPath = dir.absolutePath() + "/" + entry;
removeFolder(QDir(entryAbsPath));
......
}
Пришлось за него самому создавать объект. В итоге код пришлось переписать в :
int removeFolder(QDir & dir)
{
......
QString entryAbsPath = dir.absolutePath() + "/" + entry;
QDir dr(entryAbsPath);
removeFolder(dr);
......
}
пятница, 30 октября 2009 г.
Рекурсивное удаление каталогов в Qt
Удаляем рекурсивно папки.
//Функция удаления папки
int removeFolder(QDir & dir)
{
int res = 0;
//Получаем список каталогов
QStringList lstDirs = dir.entryList(QDir::Dirs |
QDir::AllDirs |
QDir::NoDotAndDotDot);
//Получаем список файлов
QStringList lstFiles = dir.entryList(QDir::Files);
//Удаляем файлы
foreach (QString entry, lstFiles)
{
QString entryAbsPath = dir.absolutePath() + "/" + entry;
QFile::remove(entryAbsPath);
}
//Для папок делаем рекурсивный вызов
foreach (QString entry, lstDirs)
{
QString entryAbsPath = dir.absolutePath() + "/" + entry;
removeFolder(QDir(entryAbsPath));
}
//Удаляем обрабатываемую папку
if (!QDir().rmdir(dir.absolutePath()))
{
res = 1;
}
return res;
}
четверг, 29 октября 2009 г.
Расширение типов зависимостей в форме ввода
Некоторые люди спрашивают, почему у тебя в форме ввода зависимости между компонентами обусловлены по RTTI? Ведь это налагает ограничения на разновидности зависимостей. То есть, ты четко прописываешь связку, например, FSexEdit (выбор пола) и FComboList (список фамилий) и в зависимости от пола меняешь окончания фамилий. А если тебе надо будет добавить некую другую зависимость, когда в FComboList будут не фамилии а нечто другое, как тогда?
Отвечаю, добавление новой зависимости не составит труда. В утилите Rule нужно добавить третий параметр - тип зависимости.
Вот код утилиты Rule::applyRule
Как видно из кода - я делаю динамическое преобразование с помощью dynamic_cast, а затем в зависимости от результата вызываю функцию apply, аргументами которой являются уже конкретные типы FSexEdit и FComboTextList.
Чтобы расширить набор зависимостей, мне нужно в функции apply добавить третий параметр - вид зависимости.
Тип зависимости будет узнавать функция applyRule из экземпляра master.
Так, что изменения минимальны, код легко расширяется. Все изменения не выходят за границы утилиты класса.
Отвечаю, добавление новой зависимости не составит труда. В утилите Rule нужно добавить третий параметр - тип зависимости.
Вот код утилиты Rule::applyRule
void Rule::applyRule(const AbstractFormComponent & master, AbstractFormComponent & slave) { //преобразование мастера const FSexEdit * masterSex = dynamic_cast<const FSexEdit *>(&master); //преобразование раба FComboTextList * slaveCombo = dynamic_cast<FComboTextList *>(&slave); //зависимости от секса if (masterSex) { if (slaveCombo) { apply(*masterSex, *slaveCombo); } } }
Как видно из кода - я делаю динамическое преобразование с помощью dynamic_cast, а затем в зависимости от результата вызываю функцию apply, аргументами которой являются уже конкретные типы FSexEdit и FComboTextList.
Чтобы расширить набор зависимостей, мне нужно в функции apply добавить третий параметр - вид зависимости.
void Rule::apply(const FSexEdit & sex, FComboTextList & combo, int depType)
Тип зависимости будет узнавать функция applyRule из экземпляра master.
Так, что изменения минимальны, код легко расширяется. Все изменения не выходят за границы утилиты класса.
вторник, 27 октября 2009 г.
Реализация зависимостей в форме ввода
Сегодня набросал механизм зависимостей. Вроде работает, но внутреннее чувство неправильности сделанного осталось.
Мне не нравится, что я использовал:
- множественное наследование
- RTTI
Это ведет к усложнению проекта. Проект должен быть прост и красив, но сделать просто очень трудно.
Дальше технические детали.
Мне не нравится, что я использовал:
- множественное наследование
- RTTI
Это ведет к усложнению проекта. Проект должен быть прост и красив, но сделать просто очень трудно.
Дальше технические детали.
понедельник, 26 октября 2009 г.
Ваяем форму ввода
Продолжаю ваять Форму ввода текста.
Пока остановился на том, что все компоненты, родные Qt и самописные должны наследовать от некого абстрактного класса, который я назвал AbstractFormComponent.
Класс содержит ряд чисто виртуальных функций, которые, следовательно, нужно переобпределять потомкам.
Интерфейс класса пока выглядит так.
Класс содержит пару функций для задания имени компонента, чтобы каждый компонент мог сказать как его зовут.
Дальше идут две основополагающие функции setValue и value. Они устанавливают и получают значение компонента.
Здесь пришлось использовать тип QVariant, хотя мне хотелось бы это сделать на чистом С. Тип QVariant удобен тем, что может хранить любой тип - int, QString, QDate и многие другие.
Каждый компонент сам понимает с каким типом он работает, преобразует QVariant в нужный тип и работает с ним.
Далее идет функция widget() - она возвращает виджет, который будет отражен на форме.
Такой подход, т.е. наследование всех компоненто от единой основы, позволяет отделить интерфейс компонента от реализации. Например, если захочу я переписать компонент QComboBox, то все что мне понадобится, чтобы пристыковать новый компонент - это соблюсти небольшой интерфейс абстрактного класса AbstractFormComponent.
А все компоненты я могу поместить в вектор
и работать с ними как с одним типом.
Следующим этапом нужно разработать класс для осуществления зависимостей между компонентами. Например, чтобы выбор в компоненте выбора пола влиял на окончания фамилий в справочнике фамилий. Причем таких зависимостей может быть сколько угодно и совершенно разнообразного поведения.
Пока остановился на том, что все компоненты, родные Qt и самописные должны наследовать от некого абстрактного класса, который я назвал AbstractFormComponent.
Класс содержит ряд чисто виртуальных функций, которые, следовательно, нужно переобпределять потомкам.
Интерфейс класса пока выглядит так.
class AbstractFormComponent
{
public:
void setName(const QString & name)
{
name_ = name;
}
QString name() const
{
return name_;
}
virtual void setValue(const QVariant &) = 0;
virtual QVariant value() const = 0;
protected:
virtual QWidget * widget() const = 0;
virtual void setCaps(Caps) = 0;
private:
QString name_;
};
Класс содержит пару функций для задания имени компонента, чтобы каждый компонент мог сказать как его зовут.
Дальше идут две основополагающие функции setValue и value. Они устанавливают и получают значение компонента.
Здесь пришлось использовать тип QVariant, хотя мне хотелось бы это сделать на чистом С. Тип QVariant удобен тем, что может хранить любой тип - int, QString, QDate и многие другие.
Каждый компонент сам понимает с каким типом он работает, преобразует QVariant в нужный тип и работает с ним.
Далее идет функция widget() - она возвращает виджет, который будет отражен на форме.
Такой подход, т.е. наследование всех компоненто от единой основы, позволяет отделить интерфейс компонента от реализации. Например, если захочу я переписать компонент QComboBox, то все что мне понадобится, чтобы пристыковать новый компонент - это соблюсти небольшой интерфейс абстрактного класса AbstractFormComponent.
А все компоненты я могу поместить в вектор
QVector<AbstractFormComponent *> components_;
и работать с ними как с одним типом.
Следующим этапом нужно разработать класс для осуществления зависимостей между компонентами. Например, чтобы выбор в компоненте выбора пола влиял на окончания фамилий в справочнике фамилий. Причем таких зависимостей может быть сколько угодно и совершенно разнообразного поведения.
Подписаться на:
Сообщения (Atom)