Hi everybody..
I'm developing an application using Qt, but I need some about how to avoid code repeat without sharing the private members of my class.
I am working with some collections (QHash) of project-specific structs and I created a polymorphic class to manage those collections. A derived class also manage some UI components (shared through pointers or references) so it can automatically represent those structs in the UI.. It's something like this:
Main class
Base class for collection managing..
Derived class for UI management and so on
Code snippet
And I share some UI members in the constructor of the MainWindow class..
I call the functions from the StructEditor class when I need to add a new Category or something like that..
My project consists of three applications, those of which use almost the same methods for managing these structs, so I decided to use a class with the methods to add, update, remove and represent the structs in the UI sharing some member pointers with the MainWindow class. But now I'm thinking it is a bit dirty and I should not share these members because the MainWindow loses control over them. I was thinking I could create the collections of my structs in the Base class and make a method so I can read (securely) members of those collections in the MainWindow class, but my problem is with UI members. I could use signals and manage those members directly in the MainWindow class, but then I would have to duplicate a lot of code and it would complicate (a bit) the code changes, which is the main reason I decided to unify those methods in a class.
So, my question is: Is there any way to 'unify' those methods without having to share members or using ugly global variables? I would like to have those methods in a separated file.
Thanks and greetings!
I'm developing an application using Qt, but I need some about how to avoid code repeat without sharing the private members of my class.
I am working with some collections (QHash) of project-specific structs and I created a polymorphic class to manage those collections. A derived class also manage some UI components (shared through pointers or references) so it can automatically represent those structs in the UI.. It's something like this:
Main class
Code:
class ArmyEditor : public QMainWindow
{
//.... some specific functions ...
private:
Ui::ArmyEditor *ui;
// Specific structs
QHash<QString, GameCategory> categories;
QHash<QString, Column> columns;
QHash<QString, GameProperty> properties;
QHash<QString, UnitOption> commonOptions;
QHash<QString, UnitOption> inheritedOptions;
QHash<QString, GameItem> items;
QHash<QString, GameItem> inheritedItems;
QHash<QString, GlobalText> globalTexts;
QHash<QString, GlobalText> inheritedGlobalTexts;
QHash<QString, Unit> units;
};
Code:
class StructManager : public QObject { // Base class
Q_OBJECT
public:
explicit StructManager(QWidget* parent = 0);
virtual bool addCategory(const GameCategory &category, const QString &key);
// ..More virtual functions...
protected:
QWidget *parent;
QHash<QString, GameCategory> *categories; // Shared members
QHash<QString, Column> *columns;
QHash<QString, GameProperty> *properties;
QHash<QString, UnitOption> *commonOptions;
QHash<QString, GameItem> *commonItems;
QHash<QString, GlobalText> *globalTexts;
QHash<QString, Unit> *units;component
// There are more here
};
Code:
bool StructManager::addCategory(const GameCategory &category, const QString &key) {
if(categories && GameStructs::isValidKey(key, parent)) {
if(!categories->contains(key)) {
categories->insert(key, category);
emit categoryAdded(category, key);
return true;
} else {
if(showMessages)
QMessageBox::critical(parent, tr("Can not add the category"), tr("The category can not be added because its ID (%1) already exists").arg(key));
return false;
}
} else
return false;
}
Code:
class StructEditor : public StructManager
{
Q_OBJECT
public:
StructEditor(QWidget* parent = 0);
virtual bool addCategory(const GameCategory &category, const QString &key);
// ...More overriden functions...
protected:
QTreeWidget *catList; // More shared items (there are get/set methods in the class)
QListWidget *colList;
QTreeWidget *propList;
QTreeWidget *optList;
QListWidget *optActionList;
QTreeWidget *itemList;
QListWidget *itemActionList;
QTableWidget *globalTextsGrid;
QTreeWidget *unitTree;
QComboBox *optCategory;
QComboBox *itemCategory;
QComboBox *unitCategory;
QComboBox *optAmountColumn;
QComboBox *optSetColumn;
};
Code:
bool StructEditor::addCategory(const GameCategory &category, const QString &key) {
if(catList && StructManager::addCategory(category, key)) {
QStringList cells;
cells << QString(category.getName());
QTreeWidgetItem* item = new QTreeWidgetItem(cells);
item->setData(0, Qt::UserRole, key);
catList->topLevelItem(category.type)->addChild(item);
catList->expandItem(catList->topLevelItem(category.type));
if(category.type == GameCategory::CategoryOfOptions) {
if(optList && optCategory) {
item = new QTreeWidgetItem(cells);
item->setData(0, Qt::UserRole, key);
optList->addTopLevelItem(item);
optCategory->addItem(category.getName(), key);
}
} else if(category.type == GameCategory::CategoryOfItems) {
if(itemList && itemCategory) {
item = new QTreeWidgetItem(cells);
item->setData(0, Qt::UserRole, key);
itemList->addTopLevelItem(item);
itemCategory->addItem(category.getName(), key);
}
} else if(unitCategory && unitTree && category.type == GameCategory::CategoryOfUnits) {
item = new QTreeWidgetItem(cells);
item->setData(0, Qt::UserRole, QVariant(key));
unitTree->addTopLevelItem(item);
unitCategory->addItem(category.getName(), key);
}
return true;
} else
return false;
}
Code:
ArmyEditor::ArmyEditor(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ArmyEditor)
{
ui->setupUi(this);
// Setup Army Struct Manager
armyManager = new StructEditor(this);
armyManager->setCatList(ui->catList);
armyManager->setOptList(ui->optList);
armyManager->setOptActionList(ui->optActionList);
armyManager->setItemList(ui->itemList);
armyManager->setItemActionList(ui->itemActionList);
armyManager->setGlobalTextsGrid(ui->globalTextsGrid);
armyManager->setUnitTree(ui->unitTree);
armyManager->setOptCategory(ui->optCategory);
armyManager->setItemCategory(ui->itemCategory);
armyManager->setUnitCategory(ui->unitCategory);
armyManager->setOptAmountColumn(ui->optAmountColumn);
armyManager->setOptSetColumn(ui->optSetColumn);
armyManager->setCategories(&categories);
armyManager->setOptions(&commonOptions);
armyManager->setItems(&items);
armyManager->setGlobalTexts(&globalTexts);
//.. some other code ..
};
My project consists of three applications, those of which use almost the same methods for managing these structs, so I decided to use a class with the methods to add, update, remove and represent the structs in the UI sharing some member pointers with the MainWindow class. But now I'm thinking it is a bit dirty and I should not share these members because the MainWindow loses control over them. I was thinking I could create the collections of my structs in the Base class and make a method so I can read (securely) members of those collections in the MainWindow class, but my problem is with UI members. I could use signals and manage those members directly in the MainWindow class, but then I would have to duplicate a lot of code and it would complicate (a bit) the code changes, which is the main reason I decided to unify those methods in a class.
So, my question is: Is there any way to 'unify' those methods without having to share members or using ugly global variables? I would like to have those methods in a separated file.
Thanks and greetings!
Comment