HQEd Types

Podzadania

  1. Zapoznać się z podstawową obsługą CVS-a i komentowaniem kodu http://home.agh.edu.pl/~kk/doku.php?id=others:bimloq:start
  2. Pobrać kod z CVS-a z gałęzi releases (dane do logowania zostaną wysłane mailem).
  3. Spróbować skompilować i uruchomić.
  4. Przyjść na konsultacje celem ustalenia dalszych szczegółów.

Uwagi 04.07.2011

Projekt

  • Dodać komentarz oddzielający metody w pliku: AttributeImport_ui.cpp
  • if(conWin→result()) sprawdzić przy pomocy wartości (mogą się zmienić w przszłości):
    • QDialog::Accepted
    • QDialog::Rejected
  • :!: Źle tworzony nowy identyfikator:
    selTypes[i].setAttribute("id", selTypes[i].attribute("id", "") + "_modified");
    selAttrs[i].setAttribute("id", selAttrs[i].attribute("id", "") + "_1");

    Dlaczego nie zostały wykorzystane metody przeznaczone do wyszukiwania unikatowych identyfikatorów?
    Dlaczego nie jest sprawdzane czy w ten sposób utworzony identyfikator jest rzeczywiście unikatowy?

  • :!: Zmiana ID typu nie propaguje się na atrybuty.
  • Program się zawiesza jeżeli w oknie AttributeImport klikniemy Cancel.
  • Program się zawiesza jeżeli w oknie AttributeImport klikniemy OK.
  • Dlaczego import trwa w momencie kliknięcia Cancel w oknie AttributeImport?
  • :!: Import atrybutów powinien być nieszkodliwy dla edytowanego projektu. Tym czasem usunięcie atrybutów/typów w zaproponowany przez Panów sposób jest niedopuszczalny:
    if(conWin->getSelChoice() == "overwrite")
    {
         for(int i = 0; i < selTypes.size(); ++i)
              typeList->remove(typeList->indexOfID(selTypes.at(i).attribute("id", "")));
         for(int i = 0; i < selAttrs.size(); ++i)
              AttributeGroups->removeAtt(selAttrs.at(i).attribute("id", ""));
    }
    if(conWin->getOthChoice() == "overwrite")
    {
         for(int i = 0; i < unselTypes.size(); ++i)
              typeList->remove(typeList->indexOfID(unselTypes.at(i).attribute("id", "")));
         for(int i = 0; i < unselAttrs.size(); ++i)
              AttributeGroups->removeAtt(unselAttrs.at(i).attribute("id", ""));
    }
  • Overwrite:
    • Typy:
      bool hTypeList::updateTypePointer(hType* __old, hType* __new)
    • Atrybuty:
      bool hqed::sendEventMessage(QString* __errmsgs, int __event, ...)
      • Tworzymy nowe zdarzenie: np.
        #define XTT_SIGNAL_ATTRIBUTE_REPLACED 3      // QString* __errmsgs, int __event, XTT_Attribute* __oldattptr, XTT_Attribute* __newattptr
      • Dodajemy zdarzenie do wszystkich obiektów i podobiektów:
        result = ardAttributeList->eventMessage(__errmsgs, __event, attr) && result;
        result = ardPropertyList->eventMessage(__errmsgs, __event, attr) && result;
        result = ardDependencyList->eventMessage(__errmsgs, __event, attr) && result;
        result = ardLevelList->eventMessage(__errmsgs, __event, attr) && result;
        result = AttributeGroups->eventMessage(__errmsgs, __event, attr) && result;
        result = ConnectionsList->eventMessage(__errmsgs, __event, attr) && result;
        result = TableList->eventMessage(__errmsgs, __event, attr) && result;
        result = States->eventMessage(__errmsgs, __event, attr) && result;
        result = OutputStates->eventMessage(__errmsgs, __event, attr) && result;

Raport

  • Brak opisu zaproponowanych sposobów rozwiązywania konfliktów.
  • Opis rzeczy zawartych w raporcie zbyt krótki:
    • Jak interpretować zwracane przez metody wartości.
    • Dokładniejszy opis okna AttributeImport
  • Pracujemy na Wiki :!:

Uwagi 06.07.2011

  • Skąd w pętli
    while(!type.isNull())
    {
        if(typeList->indexOfID(type.attribute("id", "")) != -1)
            if(type.attribute("id", "") != "tpe_1" && type.attribute("id", "") != "tpe_2" && type.attribute("id", "") != "numeric" && type.attribute("id", "") != "symbolic")
                conTypes.append(type);
        type = type.nextSiblingElement("type");
    }

    warunek:

    if(type.attribute("id", "") != "tpe_1" && type.attribute("id", "") != "tpe_2" && type.attribute("id", "") != "numeric" && type.attribute("id", "") != "symbolic")
  • Propagacja zmienionych ID typów:
    • Przy pomocy pętli:
      QStringList usedIds;
      for(int i = 0; i < selTypes.size(); ++i)
      {
          docElem.removeChild(types);
          types.removeChild(selTypes[i]);
          int id_index = 1;
          QString candidate = "";
          do
          {
              candidate = "tpe_" + QString::number(id_index++);
          }
          while(usedIds.indexOf(candidate) != -1 || typeList->indexOfID(candidate) != -1);
          usedIds << candidate;
          selTypes[i].setAttribute("id", candidate);
       
          types.appendChild(selTypes[i]);
          docElem.appendChild(types);
       
          QString oldTypeId = selTypes[i].attribute("id", "");
          QString newTypeId = candidate;
          for(int i = 0; i < selAttrs.size(); ++i)
              if(selAttrs[i].attribute("type", "") == oldTypeId)
                  selAttrs[i].setAttribute("type", newTypeId);
          for(int i = 0; i < unselAttrs.size(); ++i)
              if(unselAttrs[i].attribute("type", "") == oldTypeId)
                  unselAttrs[i].setAttribute("type", newTypeId);
      }

wyszukiwane są nowe ID typu/atrybutu, jeżeli stworzony kandydat ID spełnia warunek:

while(usedIds.indexOf(candidate) != -1 || typeList->indexOfID(candidate) != -1);

to jest przyjmowane że nie istnieje i jest modyfikowany element XML-owy i nowa wartość ID jest dodawana do usedIds. Jednak nigdzie nie jest sprawdzane czy utworzony w ten sposób nowy kandydat ID nie istnieje wśród innych typów importowanych, których ID się nie dublują.

  • Pętle:
    for(int i = 0; i < selAttrs.size(); ++i)
        if(selAttrs[i].attribute("type", "") == oldTypeId)
            selAttrs[i].setAttribute("type", newTypeId);
    for(int i = 0; i < unselAttrs.size(); ++i)
        if(unselAttrs[i].attribute("type", "") == oldTypeId)
            unselAttrs[i].setAttribute("type", newTypeId);

    nie uwzględniają wszystkich atrybutów a jedynie te których ID już istnieją. Zmianę ID typu należy przeprowadzić we wszystkich wczytywanych atrybutach.

  • Po dokonaniu importu nagłówek głównego okna zmienia się i wyświetla nazwę importowanego pliku. Nagłówek nie powinien się zmieniać.
  • FIXME overwrite

Uwagi 27.07.2011

  • Błąd podczas rozważanie przypadku:
    if(conWin->getSelChoice() == "load with changed id")

    w pętli

    for(int i = 0; i < selTypes.size(); ++i)

    kod jest wykonywany w następującej kolejności:

    selTypes[i].setAttribute("id", candidate);
    types.appendChild(selTypes[i]);
    docElem.appendChild(types);
    QString oldTypeId = selTypes[i].attribute("id", "");
    QString newTypeId = candidate;

    co powoduje że obie zmienne oldTypeId oraz newTypeId przyjmują wartość tego nowego ID.

  • Niepoprawnie wygenerowane zdarzenie nadpisania atrybutu:
    • Niepotrzebna funkcja copyPrperties, która kopiuje wskaźniki!!.
    • W przypadku uzupełnienia ciała destruktora w taki sposób że będzie kasował dynamicznie zaalokowane pola klasy, pojawi się problem.
    • Brak dodanego nowego zdarzenia.
    • Obsługiwane zdarzenie powinno zawierać kolejny parametr będący wskaźnikiem na nowy atrybut.
  • W przypadku nadpisywania atrybutów w nadpisywanym atrybucie jest ustawiane ID na wartość stałą
    _old->setId("eFeBeEjuBYHSLyQdkapm3SLqhfdcfv"); //random string

    następnie kopiowane są (w sposób niepoprawny) właściwości nowego atrybutu:

    _old->copyProperties(_new);

    i w efekcie końcowym usuwany jest atrybut nadpisujący:

    delete _new;

    czyli w dalszym ciągu istnieje nadpisywany atrybut ale ze zmienionym ID.
    Problem: Co jeżeli chcemy nadpisać dwa atrybuty?
    Pojawi się konflikt identyfikatorów!!! (wszystkie nadpisywane atrybuty będą miały to samo ID: eFeBeEjuBYHSLyQdkapm3SLqhfdcfv).

  • Nie w pełni zaktualizowany kod i raport:
    • Nie usunięte metody, które były nipotrzebnie lub niepoprawnie stworzone:
      bool XTT_AttributeGroups::removeAtt(QString __attId)
      QString hTypeList::createUniqeTypeIdentifier(void)
  • Brak komentarzy kluczowego fragmentu kodu odpowiadającego za rozwiązywanie konfliktów.
  • Brak modularyzacji kodu - cały kod rozwiązywania konfliktów jest zawarty w ciele jednej metody.
  • Powtarzające się (bardzo podobne) fragmenty kodu.

Raport - v1.0

1. Opis problemu:

Naszym zadaniem było dodanie do programu hqed możliwości importu atrybutów oraz typów z plików o rozszerzeniu hml. W tym celu należało dodać stosowną opcję w menu programu oraz zaimplementować funkcjonalności odpowiadające za wczytanie rzeczonych elementów oraz zaproponować rozwiązanie w przypadku powtarzających się id.

2. Propozycja rozwiązania:

Użytkownik otrzyma listę wczytywanych typów i atrybutów, których id istnieje już w programie. Będzie mógł podzielić konfliktowe pozycje na dwie grupy:

  • zaznaczone
  • odznaczone


Dla obu utworzonych w ten sposób grup udostępnione zostaną 3 opcje działania:

  • nadpisanie typów/atrybutów istniejących w programie wczytywanymi
  • pozostawienie oryginalnych typów/atrybutów
  • zapisanie konfliktowych typów/atrybutów ze zmienionym id

3. Modyfikacje istniejących plików:

MainWin.ui

Dodano do menu File akcję Attribute import z opcją HML file.

MainWin_ui.(h|cpp)

Dodano funkcję odpowiadającą za wczytanie atrybutów oraz typów z pliku.

 void importAttributesFromHML20file(void) 


Kolejność operacji:

  1. wyświetlenie okna QFileDialog w celu wybrania pliku
  2. odczytanie zawartości pliku i przypisanie jej do obiektu klasy QDomDocument
  3. wyznaczenie zdublowanych id wczytywanych typów i atrybutów
  4. wyświetlenie okna dialogowego z wyborem dalszego postępowania
  5. przygotowanie danych do wczytania w zależności od wybranej opcji
  6. wczytanie danych do programu


Funkcję połączono z sygnałem kliknięcia opcji HML file w menu:

 connect(att_import_from_hml_file, SIGNAL(triggered()), this, SLOT(importAttributesFromHML20file())); 


hTypeList.(h|cpp)

Dodano funkcję zwracającą unikalny id typu.

 QString hTypeList::createUniqeTypeIdentifier(void) 

return – wygenerowany unikalny identyfikator

XTT_AttributeGroups.(h|cpp)

Dodano funkcję odpowiadającą za usunięcie atrybutu o zadanym id:

 bool removeAtt(QString __attId) 

__attId – id wybranego atrybutu
return – wynik operacji (true/false)

XTT_Attribute.(h|cpp)

Dodano funkcję odpowiadającą za przekopiowanie zawartości atrybutu:

 void copyProperties(XTT_Attribute* _new) 

_new – atrybut źródłowy

4. Utworzone pliki:

AttributeImport_ui.(h|cpp)

W ramach klasy AttributeImport zdefiniowano następujące metody:

 QList<QDomElement> getSTypes(void) 

Funkcja zwraca listę typów zaznaczonych w oknie dialogowym.

 QList<QDomElement> getUTypes(void) 

Funkcja zwraca listę typów, które nie zostały zaznaczone w oknie dialogowym.

 QList<QDomElement> getSAttrs(void) 

Funkcja zwraca listę atrybutów zaznaczonych w oknie dialogowym.

 QList<QDomElement> getUAttrs(void) 

Funkcja zwraca listę atrybutów, które nie zostały zaznaczone w oknie dialogowym.

 QString getSelChoice(void) 

Funkcja zwraca opcję wybraną dla oznaczonych elementów.

 QString getOthChoice(void) 

Funkcja zwraca opcję wybraną dla nieoznaczonych elementów.

 void confirm(void) 

Funkcja wykonywana po kliknięciu przycisku OK. Następuje w niej przypisanie opcji wybranych w oknie dialogowym do odpowiednich zmiennych klasy AttributeImport.

AttributeImport.ui

Utworzono okno typu QDialog zawierające obiekt typu QListWidget, pozwalający na wyświetlenie zduplikowanych typów i atrybutów. Okno zawiera ponadto dwa obiekty typu QComboBox, umożliwiające wybór akcji, zarówno dla oznaczonych jak i nieoznaczonych elementów listy oraz dwa przyciski – OK i Cancel. Po kliknięciu przycisku OK wykonane zostaną akcje wybrane przez użytkownika za pomocą kontrolek typu combobox. Po naciśnięciu przycisku Cancel operacja wczytywania zostanie anulowana, a okno dialogowe zostanie zamknięte.

pl/dydaktyka/miw/2011/hqedtypes.txt · ostatnio zmienione: 2017/07/17 08:08 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0