пятница, 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

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

Это ведет к усложнению проекта. Проект должен быть прост и красив, но сделать просто очень трудно.

Дальше технические детали.

понедельник, 26 октября 2009 г.

Ваяем форму ввода

Продолжаю ваять Форму ввода текста.

Пока остановился на том, что все компоненты, родные 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_;

и работать с ними как с одним типом.

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