The Meta-Object System Signals & Slots 信号槽机制

 

 

应用:

timhul/ClassicSim: An event-driven simulation tool written in C++ for World of Warcraft Classic. https://github.com/timhul/ClassicSim

ClassicSim/ClassicSimControl.cpp at master · timhul/ClassicSim https://github.com/timhul/ClassicSim/blob/master/GUI/ClassicSimControl.cpp

 

#pragma once

#include <QMap>
#include <QObject>
#include <QSet>
#include <QVariant>
#include <QVector>

#include "EnchantName.h"

class ActiveItemStatFilterModel;
class AvailableItemStatFilterModel;
class BuffBreakdownModel;
class BuffModel;
class Character;
class CharacterDecoder;
class CharacterEncoder;
class CharacterTalents;
class CombatRoll;
class DamageMetersModel;
class DebuffBreakdownModel;
class DebuffModel;
class EnchantModel;
class Engine;
class EngineBreakdownModel;
class EquipmentDb;
class Item;
class ItemModel;
class ItemTypeFilterModel;
class MeleeDamageAvoidanceBreakdownModel;
class MeleeDamageBreakdownModel;
class NumberCruncher;
class ProcBreakdownModel;
class Race;
class RaidControl;
class RandomAffixes;
class RandomAffixModel;
class ResourceBreakdownModel;
class RotationExecutorBreakdownModel;
class RotationExecutorListModel;
class RotationModel;
class ScaleResult;
class ScaleResultModel;
class SimControl;
class SimScaleModel;
class SimSettings;
class SimulationThreadPool;
class Target;
class TemplateCharacterModel;
class ThreatBreakdownModel;
class WeaponModel;

class ClassicSimControl : public QObject {
    Q_OBJECT
public:
    ClassicSimControl(QObject* parent = nullptr);
    ~ClassicSimControl();

    void save_settings();

    /* Character */
    Q_PROPERTY(QString classColor READ get_class_color NOTIFY classChanged)
    Q_PROPERTY(QString className READ get_class_name NOTIFY classChanged)
    Q_PROPERTY(QString raceName READ get_race_name NOTIFY raceChanged)
    Q_PROPERTY(bool isAlliance READ get_is_alliance NOTIFY factionChanged)
    Q_PROPERTY(bool isHorde READ get_is_horde NOTIFY factionChanged)

    Q_INVOKABLE void selectRace(const QString& race_name);
    Q_INVOKABLE void selectFaction(const int faction);

    Q_INVOKABLE bool raceAvailable(const QString& race_name);
    /* End of Character */

    /* Talents */
    Q_PROPERTY(int talentPointsRemaining READ get_talent_points_remaining NOTIFY talentsUpdated)
    Q_PROPERTY(QString leftTalentTreeBackground READ getLeftBackgroundImage NOTIFY classChanged)
    Q_PROPERTY(QString midTalentTreeBackground READ getMidBackgroundImage NOTIFY classChanged)
    Q_PROPERTY(QString rightTalentTreeBackground READ getRightBackgroundImage NOTIFY classChanged)
    Q_PROPERTY(int leftTreePoints READ get_left_talent_tree_points NOTIFY talentsUpdated)
    Q_PROPERTY(int midTreePoints READ get_mid_talent_tree_points NOTIFY talentsUpdated)
    Q_PROPERTY(int rightTreePoints READ get_right_talent_tree_points NOTIFY talentsUpdated)
    Q_PROPERTY(QString talentAllocation READ get_formatted_talent_allocation NOTIFY talentsUpdated)

    Q_INVOKABLE QString getIcon(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool showPosition(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool showBottomArrow(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool showRightArrow(const QString& tree_position, const QString& talent_position) const;

    Q_INVOKABLE QString getBottomArrow(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE QString getRightArrow(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool bottomChildAvailable(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool bottomChildActive(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool rightChildAvailable(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool rightChildActive(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool isActive(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool isAvailable(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool isMaxed(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE bool hasTalentPointsRemaining() const;
    Q_INVOKABLE QString getRank(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE QString getMaxRank(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE void incrementRank(const QString& tree_position, const QString& talent_position);
    Q_INVOKABLE void decrementRank(const QString& tree_position, const QString& talent_position);
    Q_INVOKABLE QString getRequirements(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE QString getCurrentRankDescription(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE QString getNextRankDescription(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE QString getTreeName(const QString& tree_position) const;
    Q_INVOKABLE QString getTalentName(const QString& tree_position, const QString& talent_position) const;
    Q_INVOKABLE void maxRank(const QString& tree_position, const QString& talent_position);
    Q_INVOKABLE void minRank(const QString& tree_position, const QString& talent_position);

    Q_INVOKABLE void clearTree(const QString& tree_position);

    Q_INVOKABLE void setTalentSetup(const int talent_index);
    int get_left_talent_tree_points() const;
    int get_mid_talent_tree_points() const;
    int get_right_talent_tree_points() const;
    int get_tree_points(const QString& tree_position) const;
    QString get_formatted_talent_allocation() const;
    /* End of Talents */

    Q_INVOKABLE void toggleTank();
    Q_PROPERTY(bool isTanking READ get_is_tanking NOTIFY tankingChanged)
    bool get_is_tanking() const;

    /* Stats */
    Q_PROPERTY(unsigned strength READ get_strength NOTIFY statsChanged)
    Q_PROPERTY(unsigned agility READ get_agility NOTIFY statsChanged)
    Q_PROPERTY(unsigned stamina READ get_stamina NOTIFY statsChanged)
    Q_PROPERTY(unsigned intellect READ get_intellect NOTIFY statsChanged)
    Q_PROPERTY(unsigned spirit READ get_spirit NOTIFY statsChanged)

    Q_PROPERTY(QString meleeCritChance READ get_melee_crit_chance NOTIFY statsChanged)
    Q_PROPERTY(QString meleeHitChance READ get_melee_hit_chance NOTIFY statsChanged)
    Q_PROPERTY(int meleeAttackPower READ get_melee_attack_power NOTIFY statsChanged)
    Q_PROPERTY(int wpnSkillMh READ get_mainhand_wpn_skill NOTIFY statsChanged)
    Q_PROPERTY(int wpnSkillOh READ get_offhand_wpn_skill NOTIFY statsChanged)
    Q_PROPERTY(QString rangedCritChance READ get_ranged_crit_chance NOTIFY statsChanged)
    Q_PROPERTY(QString rangedHitChance READ get_ranged_hit_chance NOTIFY statsChanged)
    Q_PROPERTY(int rangedAttackPower READ get_ranged_attack_power NOTIFY statsChanged)
    Q_PROPERTY(int wpnSkillRanged READ get_ranged_wpn_skill NOTIFY statsChanged)
    Q_PROPERTY(int spellPower READ get_spell_power NOTIFY statsChanged)
    Q_PROPERTY(QString spellHitChance READ get_spell_hit_chance NOTIFY statsChanged)
    Q_PROPERTY(QString spellCritChance READ get_spell_crit_chance NOTIFY statsChanged)
    Q_PROPERTY(QString displayStatsType READ get_stats_type_to_display NOTIFY displayStatsTypeChanged)
    Q_SIGNAL void displayStatsTypeChanged();
    QString get_stats_type_to_display() const;
    QString get_attack_mode_as_string() const;
    unsigned get_ranged_wpn_skill() const;
    unsigned get_spell_power() const;
    QString get_spell_hit_chance() const;
    QString get_spell_crit_chance() const;
    Q_INVOKABLE void selectDisplayStat(const QString& attack_mode);
    /* End of Stats */

    /* Equipment */
    Q_PROPERTY(QString mainhandIcon READ get_mainhand_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString offhandIcon READ get_offhand_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString rangedIcon READ get_ranged_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString headIcon READ get_head_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString neckIcon READ get_neck_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString shouldersIcon READ get_shoulders_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString backIcon READ get_back_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString chestIcon READ get_chest_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString wristIcon READ get_wrist_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString glovesIcon READ get_gloves_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString beltIcon READ get_belt_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString legsIcon READ get_legs_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString bootsIcon READ get_boots_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString ring1Icon READ get_ring1_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString ring2Icon READ get_ring2_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString trinket1Icon READ get_trinket1_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString trinket2Icon READ get_trinket2_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString projectileIcon READ get_projectile_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString relicIcon READ get_relic_icon NOTIFY equipmentChanged)
    Q_PROPERTY(QString quiverIcon READ get_quiver_icon NOTIFY equipmentChanged)

    Q_INVOKABLE void setEquipmentSetup(const int equipment_index);

    Q_SIGNAL void enchantChanged();
    Q_INVOKABLE bool hasItemEquipped(const QString& slot_string) const;
    Q_INVOKABLE bool hasEnchant(const QString& slot_string) const;
    Q_INVOKABLE bool hasTemporaryEnchant(const QString& slot_string) const;
    Q_INVOKABLE QString getEnchantEffect(const QString& slot_string) const;
    Q_INVOKABLE QString getTemporaryEnchantEffect(const QString& slot_string) const;
    Q_INVOKABLE void applyEnchant(const QString& slot_string, const int enchant_name);
    Q_INVOKABLE void applyTemporaryEnchant(const QString& slot_string, const int enchant_name);
    Q_INVOKABLE void clearEnchant(const QString& slot_string);
    Q_INVOKABLE void clearTemporaryEnchant(const QString& slot_string);
    EnchantModel* get_mh_enchant_model() const;
    EnchantModel* get_mh_temporary_enchant_model() const;
    EnchantModel* get_oh_enchant_model() const;
    EnchantModel* get_oh_temporary_enchant_model() const;
    EnchantModel* get_ranged_enchant_model() const;
    EnchantModel* get_head_legs_enchant_model() const;
    EnchantModel* get_shoulder_enchant_model() const;
    EnchantModel* get_back_enchant_model() const;
    EnchantModel* get_wrist_enchant_model() const;
    EnchantModel* get_gloves_enchant_model() const;
    EnchantModel* get_chest_enchant_model() const;
    EnchantModel* get_boots_enchant_model() const;
    /* End of Equipment */

    /* ItemModel */
    ItemModel* get_item_model() const;
    WeaponModel* get_weapon_model() const;
    ItemTypeFilterModel* get_item_type_filter_model() const;
    ActiveItemStatFilterModel* get_active_stat_filter_model() const;
    AvailableItemStatFilterModel* get_available_stat_filter_model() const;
    Q_INVOKABLE bool getFilterActive(const int filter) const;
    Q_INVOKABLE void toggleSingleFilter(const int filter);
    Q_INVOKABLE void clearFiltersAndSelectSingle(const int filter);
    Q_INVOKABLE void selectRangeOfFiltersFromPrevious(const int filter);
    /* End of ItemModel */

    /* Random affixes model */
    RandomAffixModel* get_random_affix_model() const;
    Q_INVOKABLE void setRandomAffixesModelId(const int item_id);
    /* End of Random affixes model */

    /* Buffs and debuffs */
    BuffModel* get_buff_model() const;
    DebuffModel* get_debuff_model() const;
    Q_INVOKABLE void toggleSingleBuff(const QString& buff);
    Q_INVOKABLE void clearBuffsAndSelectSingleBuff(const QString& buff);
    Q_INVOKABLE void selectRangeOfBuffs(const QString& buff);
    Q_INVOKABLE bool buffActive(const QString& buff) const;
    Q_INVOKABLE void toggleSingleDebuff(const QString& debuff);
    Q_INVOKABLE void clearDebuffsAndSelectSingleDebuff(const QString& buff);
    Q_INVOKABLE void selectRangeOfDebuffs(const QString& buff);
    Q_INVOKABLE bool debuffActive(const QString& debuff) const;
    Q_INVOKABLE void setBuffSetup(const int buff_index);
    /* End of Buffs and debuffs */

    /* Statistics */
    BuffBreakdownModel* get_buff_breakdown_model() const;
    DebuffBreakdownModel* get_debuff_breakdown_model() const;
    EngineBreakdownModel* get_engine_breakdown_model() const;
    MeleeDamageBreakdownModel* get_dmg_breakdown_model() const;
    MeleeDamageAvoidanceBreakdownModel* get_dmg_breakdown_avoidance_model() const;
    ProcBreakdownModel* get_proc_breakdown_model() const;
    ResourceBreakdownModel* get_resource_breakdown_model() const;
    RotationExecutorBreakdownModel* get_rotation_executor_model() const;
    RotationExecutorListModel* get_rotation_executor_list_model() const;
    ScaleResultModel* get_dps_scale_result_model() const;
    ScaleResultModel* get_tps_scale_result_model() const;
    ThreatBreakdownModel* get_thrt_breakdown_model() const;
    TemplateCharacterModel* get_template_character_model() const;
    Q_SLOT void compile_thread_results(const QString& error);
    Q_PROPERTY(QString minDps READ get_min_dps NOTIFY statisticsReady)
    Q_PROPERTY(QString maxDps READ get_max_dps NOTIFY statisticsReady)
    Q_PROPERTY(QString dpsStdDev READ get_standard_deviation NOTIFY statisticsReady)
    Q_PROPERTY(QString dpsConfInterval READ get_confidence_interval NOTIFY statisticsReady)
    Q_PROPERTY(QString engineHandledEventsPerSecond READ get_handled_events_per_second NOTIFY statisticsReady)
    QString get_handled_events_per_second() const;
    /* End of Statistics */

    /* Target */
    Q_PROPERTY(QString creatureType READ get_creature_type NOTIFY creatureTypeChanged)
    Q_PROPERTY(int targetArmor READ get_target_armor NOTIFY targetUpdated)
    Q_PROPERTY(int targetBaseArmor READ get_target_base_armor NOTIFY targetUpdated)
    Q_INVOKABLE void setCreatureType(const QString& creature_type);
    Q_SIGNAL void targetUpdated();
    int get_target_armor() const;
    int get_target_base_armor() const;
    Q_INVOKABLE void setTargetBaseArmor(const int armor);
    /* End of Target */

    /* Content phase */
    Q_INVOKABLE void setPhase(const int phase);
    Q_INVOKABLE QString getDescriptionForPhase(const int phase);
    /* End of Content phase */

    /* Rotation */
    RotationModel* get_rotation_model() const;
    Q_INVOKABLE void selectRotation();
    Q_INVOKABLE void selectInformationRotation(const int);
    Q_PROPERTY(QString rotationName READ get_curr_rotation_name NOTIFY rotationChanged)
    Q_PROPERTY(QString rotationDescription READ get_curr_rotation_description NOTIFY rotationChanged)
    Q_PROPERTY(QString rotationInfoName READ get_information_rotation_name NOTIFY informationRotationChanged)
    Q_PROPERTY(QString rotationInfoDesc READ get_information_rotation_description NOTIFY informationRotationChanged)
    /* End of Rotation */

    /* SimSettings */
    Q_INVOKABLE void resetDefaultSettings();
    Q_PROPERTY(int combatLength READ get_combat_length NOTIFY combatLengthChanged)
    Q_PROPERTY(int combatIterationsFullSim READ get_combat_iterations_full_sim NOTIFY combatIterationsChanged)
    Q_PROPERTY(int combatIterationsQuickSim READ get_combat_iterations_quick_sim NOTIFY combatIterationsChanged)
    Q_PROPERTY(int numThreads READ get_num_threads NOTIFY numThreadsChanged)
    Q_PROPERTY(int maxThreads READ get_max_threads NOTIFY numThreadsChanged)
    Q_INVOKABLE void setCombatLength(const int);
    Q_INVOKABLE void setCombatIterationsFullSim(const int);
    Q_INVOKABLE void setCombatIterationsQuickSim(const int);
    Q_INVOKABLE void setNumThreads(const int);
    Q_SIGNAL void combatLengthChanged();
    Q_SIGNAL void combatIterationsChanged();
    Q_SIGNAL void numThreadsChanged();
    Q_INVOKABLE void selectRuleset(const int);
    Q_PROPERTY(QString simProgressString READ get_sim_progress_string NOTIFY simProgressChanged)
    Q_SIGNAL void simProgressChanged();
    Q_INVOKABLE void runQuickSim();
    Q_INVOKABLE void runFullSim();
    Q_SIGNAL void simPersonalResultUpdated(QString dps, QString dpsChange, QString tps, bool positive);
    Q_SIGNAL void simRaidResultUpdated(QString dps, QString dpsChange, bool positive);
    SimScaleModel* get_sim_scale_model() const;
    Q_PROPERTY(int combatProgress READ get_combat_progress NOTIFY combatProgressChanged)
    Q_PROPERTY(bool simInProgress READ get_sim_in_progress NOTIFY simProgressChanged)
    int get_combat_progress() const;
    bool get_sim_in_progress() const;
    Q_SIGNAL void combatProgressChanged() const;
    /* End of SimSettings */

    /* Raid setup */
    Q_INVOKABLE void selectPartyMember(const int party, const int member);
    Q_INVOKABLE void clearPartyMember(const int party, const int member);
    Q_INVOKABLE QVariantMap partyMemberInfo(const int party, const int member);
    Q_INVOKABLE void selectTemplateCharacter(QString template_char);
    Q_SIGNAL void partyMembersUpdated();
    Q_SIGNAL void selectedPartyMemberChanged();
    DamageMetersModel* get_damage_meters_model();
    /* End of Raid setup */

    /* GUI initialization */
    Q_INVOKABLE QString getStartWindow() const;
    Q_INVOKABLE void changeActiveWindow(const QString& active_window);
    Q_INVOKABLE int getCurrentRuleset() const;
    Q_INVOKABLE int getCurrentCreatureType() const;
    Q_INVOKABLE int getContentPhase() const;
    /* End of GUI initialization */

    bool simulating = false;
    QString curError;

signals:
    void tankingChanged();
    void classChanged();
    void raceChanged();
    void factionChanged();
    void talentsUpdated();
    void statsChanged();
    void equipmentChanged();
    void tooltipChanged();
    void statisticsCleared();
    void statisticsReady();
    void creatureTypeChanged();
    void filtersUpdated();
    void equipmentSlotSelected();
    void rotationChanged();
    void informationRotationChanged();

public slots:
    void update_progress(double percent);

public:
    int get_talent_points_remaining() const;
    QString get_class_color() const;
    QString get_class_name() const;
    QString get_race_name() const;
    bool get_is_alliance() const;
    bool get_is_horde() const;

    void reset_race(Character* pchar);

    QString get_creature_type() const;

    QString getLeftBackgroundImage() const;
    QString getMidBackgroundImage() const;
    QString getRightBackgroundImage() const;

    unsigned get_strength() const;
    unsigned get_agility() const;
    unsigned get_stamina() const;
    unsigned get_intellect() const;
    unsigned get_spirit() const;

    QString get_melee_crit_chance() const;
    QString get_melee_hit_chance() const;
    QString get_ranged_crit_chance() const;
    QString get_ranged_hit_chance() const;

    unsigned get_melee_attack_power() const;
    unsigned get_ranged_attack_power() const;
    unsigned get_mainhand_wpn_skill() const;
    unsigned get_offhand_wpn_skill() const;

    QString get_curr_rotation_name() const;
    QString get_curr_rotation_description() const;
    QString get_information_rotation_name() const;
    QString get_information_rotation_description() const;

    int get_combat_iterations_full_sim() const;
    int get_combat_iterations_quick_sim() const;
    int get_combat_length() const;
    int get_num_threads() const;
    int get_max_threads() const;

    QString get_mainhand_icon() const;
    QString get_offhand_icon() const;
    QString get_ranged_icon() const;
    QString get_head_icon() const;
    QString get_neck_icon() const;
    QString get_shoulders_icon() const;
    QString get_back_icon() const;
    QString get_chest_icon() const;
    QString get_wrist_icon() const;
    QString get_gloves_icon() const;
    QString get_belt_icon() const;
    QString get_legs_icon() const;
    QString get_boots_icon() const;
    QString get_ring1_icon() const;
    QString get_ring2_icon() const;
    QString get_trinket1_icon() const;
    QString get_trinket2_icon() const;
    QString get_projectile_icon() const;
    QString get_relic_icon() const;
    QString get_quiver_icon() const;

    QString get_initial_upper_case_rest_lower_case(const QString&) const;
    void set_character(Character* pchar);
    void run_sim(const bool full_sim);
    void calculate_displayed_dps_value();
    void update_displayed_dps_value(const double new_dps_value, const double new_tps_value);
    void update_displayed_raid_dps_value(const double new_dps_value);

    QString get_sim_progress_string() const;

    QString get_min_dps() const;
    QString get_max_dps() const;
    QString get_standard_deviation() const;
    QString get_confidence_interval() const;

    Character* load_character(const QString& class_name);
    Character* load_character_from_str(const QByteArray& data);
    Character* get_new_character(const QString& class_name);
    void save_user_setup(Character* pchar);

    void save_configuration();
    void load_configuration();
    void activate_configuration(const QStringRef& name, const QString& value);

    EquipmentDb* equipment_db;
    RandomAffixes* random_affixes_db;
    CharacterEncoder* character_encoder;
    CharacterDecoder* character_decoder;
    SimulationThreadPool* thread_pool;
    SimControl* sim_control;
    SimSettings* sim_settings;
    Target* target;
    RaidControl* raid_control;
    NumberCruncher* number_cruncher;
    QMap<QString, Character*> chars;
    QMap<QString, Race*> races;
    QSet<QString> supported_classes;
    QMap<QString, RaidControl*> raid_controls;
    QVector<QVector<QVariantMap>> raid_setup;
    Character* current_char;
    ItemModel* item_model;
    ActiveItemStatFilterModel* active_stat_filter_model;
    AvailableItemStatFilterModel* available_stat_filter_model;
    ItemTypeFilterModel* item_type_filter_model;
    WeaponModel* weapon_model;
    BuffModel* buff_model;
    DamageMetersModel* damage_meters_model;
    DebuffModel* debuff_model;
    RotationModel* rotation_model;
    BuffBreakdownModel* buff_breakdown_model;
    DebuffBreakdownModel* debuff_breakdown_model;
    EngineBreakdownModel* engine_breakdown_model;
    MeleeDamageBreakdownModel* damage_breakdown_model;
    MeleeDamageAvoidanceBreakdownModel* damage_avoidance_breakdown_model;
    ProcBreakdownModel* proc_breakdown_model;
    ResourceBreakdownModel* resource_breakdown_model;
    RotationExecutorListModel* rotation_executor_list_model;
    SimScaleModel* sim_scale_model;
    ScaleResultModel* dps_scale_result_model;
    ScaleResultModel* tps_scale_result_model;
    ScaleResult* dps_distribution;
    ThreatBreakdownModel* threat_breakdown_model;
    TemplateCharacterModel* template_character_model;
    EnchantModel* mh_enchants;
    EnchantModel* mh_temporary_enchants;
    EnchantModel* oh_enchants;
    EnchantModel* oh_temporary_enchants;
    EnchantModel* ranged_enchants;
    EnchantModel* head_legs_enchants;
    EnchantModel* shoulder_enchants;
    EnchantModel* back_enchants;
    EnchantModel* wrist_enchants;
    EnchantModel* gloves_enchants;
    EnchantModel* chest_enchants;
    EnchantModel* boots_enchants;
    RandomAffixModel* random_affixes;
    double last_personal_sim_result {0.0};
    double last_personal_sim_result_tps {0.0};
    double last_raid_sim_result {0.0};
    double last_engine_handled_events_per_second {0.0};
    bool sim_in_progress;
    double sim_percent_completed {0.0};
    int current_party {1};
    int current_member {1};
    QString active_window;
    QString stats_type_to_display;
    QVector<Race*> raid_member_races;
};

  

Qt 6.0正式发布了_Qt中国的博客-CSDN博客 https://blog.csdn.net/Qt_China/article/details/111034861

核心库和API

我们为Qt Core做了大量工作,因为它是实现Qt最核心部分的模块,我们做了许多改进。 列举几个最重要的例子:

  • 新的属性和绑定系统:该系统将绑定的概念(使QML在Qt5取得了巨大成功)带回到了Qt的核心,并使其可用于C ++。
  • 字符串和Unicode:Qt 5时我们朝着使Qt与Unicode完全对齐的方向发展,所以许多工作已经完成。 但是,剩下的一些部分已在Qt 6中得到了清理。更多详细信息将很快在另一篇博文中介绍。
  • QList在Qt 5中经常受到批评,因为它是对存储在其中的大于指针的对象进行堆分配,这给内存分配器带来了很大的压力。 在Qt 6中,我们对此进行了更改,并将QList和QVector统一为一个类。 有关更多详细信息,请参见我们在Qt 6中有关QList的博客
  • QMetaType和QVariant是Qt元对象系统的基础。 没有QMetaType,信号和插槽将无法实现,动态调用需要QVariant。 Qt 6中的这两个类几乎完全重写,您可以在此处找到详细信息。

Qt中与图形无关的其他部分也完成了显著的改进。比如完成了Qt Concurrent的大量重写,使得多线程应用程序的开发更加简单。我们对Qt Network也做了大幅整理和改进(具体内容请参考这篇博文

 

Qt 6.0 Released https://www.qt.io/blog/qt-6.0-released

Core libraries and APIs

Much work has gone into Qt Core, as it is the module that implements the most central parts of Qt. We've gone through many areas there and made improvements. To name some of the most central ones:

  • The new property and binding system: This system now brings the concept of bindings that made QML such a huge success in Qt 5 available from C++.
  • Strings and Unicode: With Qt 5, we started aligning Qt fully with Unicode, where we completed a lot of the work, but a few items remained that we now cleaned up for Qt 6. More details will come in a separate blog post later on.
  • QList has been a class that was often criticized in Qt 5, as it was heap allocating objects stored in there that were larger than a pointer, leading to pressure on heap allocation methods. In Qt 6, we changed this and unified QList and QVector into one class. See our blog post about QList in Qt 6 for details.
  • QMetaType and QVariant are fundamental to how our Qt’s meta-object system works. Signals and slots would not be possible without QMetaType and QVariant is required for dynamic invocations. Those two classes got an almost complete rewrite with Qt 6, and you can read about the details here.

Other parts of Qt that are not related to graphics have also seen large changes. For example, Qt Concurrent has undergone an almost complete rewrite and now makes development of multi-threaded applications more effortless than ever. Qt Network has seen lots of clean-up and improvements. See this blog post for details.

 

The Meta-Object System | Qt Core 6.0.1 https://doc.qt.io/qt-6/metaobjects.html

Signals & Slots | Qt Core 6.0.1 https://doc.qt.io/qt-6/signalsandslots.html

 

https://doc.qt.io/qt-6/signalsandslots.html

 

Q_PROPERTY:这个宏用于声明一个可以被 QML 访问的属性,包括它的类型、getter/setter、发生变化时会出发的信号。一般来说哪怕对于 QML 端是只读的属性,也需要添加一个信号。这在宏的 NOTIFY 项之后声明。
当这个信号被触发的时候,QML 端会重新渲染所有依赖于这个属性值的界面组件。

Q_INVOKABLE:这个宏用于声明一个可以被 QML 调用的方法。

 

// 伪代码 以此代码为例讨论
connect(sender, signal, receiver, slot, connectionType);

 

QT中简单的emit使用_CSDN_dyq111的博客-CSDN博客_emit https://blog.csdn.net/CSDN_dyq111/article/details/107179722

***A类的.h中***
class A
{
public:
	***//公共的行为或属性***
 	void Dome();
 	***//这个是演示的例子属性***
private:

    
signals:
	***//信号***
	void AmySignal();
	***//在信号的里面加上一个你自定义的信号.***

slots:
	***//槽***

};


***B类的.h中***
class B
{
public:
    ***//公共的行为或属性***

private:


signals:
	***//信号***

slots:
	***//槽***
	void BmySlot1();
	***//在B类中填一个你想要的现象的定义。***
};


***A类的cpp***
void A::Dome()
{
	B = new B;
	******//在这里要先将B类实例化***
	***//信号与槽需要实例化对象******
	
	connect(this, SIGNAL(mySignal()), B, SLOT( BmySlot1()));
	***//将A类的信号和B类的槽函数链接起来***
	
	emit void AmySignal();
	***//发出信号***
}

***B类的cpp***
void B::BmySlot1()
{
	printf("hello world\n");
	***//实现***
}

3.这样就可以在A中对B使用信号了。

  

Qt emit的使用 - 我是张洪铭我是熊博士 - 博客园 https://www.cnblogs.com/azbane/p/8651810.html

1. 假设现在我定义了一个类A,现在想在A的一个函数void A::function1()当中的结尾处emit一个信号signal1(),然后利用这个信号触发另一个类B进行某项操作void B::function2(),请问connect应该如何书写呢(尤其是sender和SIGNAL参数)?另外,对于类A和类B,有什么特殊要求吗?

KEY:

比如在一个QMainwindow中,包含类A,B的头文件,是的类A,和类B可见,定义一个类A *a,和一个类B *b,(当然要分配空间).你就可以这么connect他们.

connect(a,SIGNAL(signal1()),b,SLOT(function2()));

对于A,B两个类出来都必须继承于QObject类没其他要求,还有若是类A,B定义在了main()函数中,那么应该使用QObject::connect( )。

 

QT 中 关键字讲解(emit,signal,slot) - FelixWang - 博客园 https://www.cnblogs.com/felix-wang/p/6212197.html

Qt中的类库有接近一半是从基类QObject上继承下来,信号与反应槽(signals/slot)机制就是用来在QObject类或其子类间通讯的方法。作为一种通用的处理机制,信号与反应槽非常灵活,可以携带任意数量的参数,参数的类型也由用户自定。同时其本身也是类型安全的,任何一个从QObject或其子类继承的用户类都可以使用信号与反应槽。

 
    信号的作用如同Windows系统中的消息。在Qt中,对于发出信号的对象来说,它并不知道是谁接收了这个信号。这样的设计可能在某些地方会有些不便,但却杜绝了紧耦合,于总体设计有利。反应槽是用来接收信号的, 但它实际上也是普通的函数,程序员可以象调用普通函数一样来调用反应槽。与信号类似的是,反应槽的拥有者也不知道是谁向它发出了信号。在程序设计过程中,多个信号可以连接至一个反应槽,类似的,一个信号也可以连接至多个反应槽,甚至一个信号可以连接至另一个信号。
 
    在Windows中,如果我们需要多个菜单都激发一个函数,一般是先写一个共用函数,然后在每个菜单的事件中调用此函数。在Qt中如果要实现同样的功能,就可以把实现部分写在一个菜单中,然后把其他菜单与这个菜单级联起来。
 
    虽然信号/反应槽机制有很多优点,使用也很方便,但它也不是没有缺点。最大的缺点在于要稍微牺牲一点性能。根据Trolltech公司的自测,在CPU为Intel PentiumII 500 Mhz的PC机上,对于一个信号对应一个反应槽的连接来说,一秒钟可以调用两百万次;对于一个信号对应两个反应槽的连接来说,一秒钟可以调用一百二十万次。这个速度是不经过连接而直接进行回调的速度的十分之一。请注意这里的十分之一速度比是调用速度的比较,而不是一个完整函数执行时间的比较。事实上一般情况下一个函数的总执行时间大部分是在执行部分,只有小部分是在调用部分,因些这个速度是可以接受的。这就象面向对象的编程和早些年的结构化编程相比一样:
 
程序的执行效率并没有提高,反而是有所下降的,但现在大家都在用面向对象的方法编写程序。用一部分执行效率换回开发效率与维护效率是值得的,况且现在已是P4为主流的时代。
 
    我们先来看一个简单的样例:
 
复制代码
          class Demo : public QObject
          {
              Q_OBJECT
 
          public:
              Demo();
              int value() const { return val; };
 
          public slots:
              void setValue( int );
          
          signals:
              void valueChanged( int );
          
          private:
              int val;
          };
          
    由样例可看到,类的定义中有两个关键字slots和signals,还有一个宏Q_OBJECT。在Qt的程序中如果使用了信号与反应槽就必须在类的定义中声明这个宏,不过如果你声明了该宏但在程序中并没有信号与反应槽,对程序也不会有任何影响,所以建议大家在用Qt写程序时不妨都把这个宏加上。使用slots定义的就是信号的功能实现,即反应槽,例如:
 
          void Demo::setValue( int v )
          {
               if ( v != val )
               {
                   val = v;
                   emit valueChanged(v);
               }
          }
          
    这段程序表明当setValue执行时它将释放出valueChanged这个信号。
    以下程序示范了不同对象间信号与反应槽的连接。
 
          Demo a, b;
          
          connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int)));
          
          b.setValue( 11 );
          
          a.setValue( 79 );
          
          b.value(); // b的值将是79而不是原先设的11
复制代码

 

          
          
    在以上程序中,一旦信号与反应槽连接,当执行a.setValue(79)时就会释放出一个valueChanged(int)的信号,对象b将会收到这个信号并触发setValue(int)这个函数。当b在执行setValue(int)这个函数时,它也将释放valueChanged(int)这个信号,当然b的信号无人接收,因此就什么也没干。请注意,在样例中我们仅当输入变量v不等于val时才释放信号,因此就算对a与b进行了交叉连接也不会导致死循环的发生。由于在样例中使用了Qt特有的关键字和宏,而Qt本身并不包括C++的编译器,因此如果用流行的编译程序(如Windows下的Visual C++或Linux下的gcc)是不能直接编译这段代码的,必须用Qt的中间编译工具moc.exe把该段代码转换为无专用关键字和宏的C++代码才能为这些编译程序所解析、编译与链接。
    以上代码中信号与反应槽的定义是在类中实现的。那么,非类成员的函数,比如说一个全局函数可不可以也这样做呢?答案是不行,只有是自身定义了信号的类或其子类才可以发出该种信号。一个对象的不同信号可以连接至不同的对象。当一个信号被释放时,与之连接的反应槽将被立刻执行,就象是在程序中直接调用该函数一样。信号的释放过程是阻塞的,这意味着只有当反应槽执行完毕后该信号释放过程才返回。如果一个信号与多个反应槽连接,则这些反应槽将被顺序执行,排序过程则是任意的。因此如果程序中对这些反应槽的先后执行次序有严格要求的,应特别注意。使用信号时还应注意:信号的定义过程是在类的定义过程即头文件中实现的。为了中间编译工具moc的正常运行,不要在源文件(.cpp)中定义信号,同时信号本身不应返回任何数据类型,即是空值(void)。如果你要设计一个通用的类或控件,则在信号或反应槽的参数中应尽可能使用常规数据以增加通用性。如上例代码中valueChanged的参数为int型,如果它使用了特殊类型如QRangeControl::Range,那么这种信号只能与RangeControl中的反应槽连接。如前所述,反应槽也是常规函数,与未定义slots的用户函数在执行上没有任何区别。
    但在程序中不可把信号与常规函数连接在一起,否则信号的释放不会引起对应函数的执行。要命的是中间编译程序moc并不会对此种情况报错,C++编译程序更不会报错。初学者比较容易忽略这一点,往往是程序编好了没有错误,逻辑上也正确,但运行时就是不按自己的意愿出现结果,这时候应检查一下是不是这方面的疏忽。
    Qt的设计者之所以要这样做估计是为了信号与反应槽之间匹配的严格性。既然反应槽与常规函数在执行时没有什么区别,因此它也可以定义成公共反应槽(public slots)、保护反应槽(protected slots)和私有反应槽(private slots)。如果需要,我们也可以把反应槽定义成虚函数以便子类进行不同的实现,这一点是非常有用的。
    只讨论一下信号与反应槽的使用好象还不过瘾,既然Qt的X11 Free版提供了源代码,我们就进去看一下在QObject中connect的实现。由于Qt是一个跨平台的开发库,为了与不同平台上的编译器配合,它定义了一个中间类QMetaObject,该类的作用是存放有关信号/反应槽以及对象自身的信息。这个类是Qt内部使用的,用户不应去使用它。
    以下是QMetaObject的定义(为了浏览方便,删除了一部分次要代码):
          
复制代码
class Q_EXPORT QMetaObject
          {
               public:
                   QMetaObject( const char * const class_name, QMetaObject *superclass,
                   const QMetaData * const slot_data, int n_slots,
                   const QMetaData * const signal_data, int n_signals);
                   virtual ~QMetaObject();
                   int numSlots( bool super = FALSE ) const;  
                   int numSignals( bool super = FALSE ) const;
                   int findSlot( const char *, bool super = FALSE ) const;
                      
                   int findSignal( const char *, bool super = FALSE ) const;
                      
                   const QMetaData *slot( int index, bool super = FALSE ) const;
                      
                   const QMetaData *signal( int index, bool super = FALSE ) const;
                      
                   QStrList slotNames( bool super = FALSE ) const;
                      
                   QStrList signalNames( bool super = FALSE ) const;
                      
                   int slotOffset() const;
                   int signalOffset() const;
                   static QMetaObject *metaObject( const char *class_name );
               private:
                   QMemberDict *init( const QMetaData *, int );
                   const QMetaData *slotData;  
                   QMemberDict *slotDict;      
                   const QMetaData *signalData;
                   QMemberDict *signalDict;    
                   int signaloffset;
                   int slotoffset;
          };
复制代码

 

          
    再看一下QObject中connect的实现。剥去粗枝,函数中便露出一个更细化的函数:connectInternal,它又做了哪些工作呢?让我们看一下:
          
复制代码
void QObject::connectInternal( const QObject *sender, int signal_index,const QObject *receiver,int membcode, int member_index )
          {
              QObject *s = (QObject*)sender;
              QObject *r = (QObject*)receiver;
              if ( !s->connections )
              {
                  s->connections = new QSignalVec( 7 );
                       s->connections->setAutoDelete( TRUE );                     
              }
              QConnectionList *clist = s->connections->at( signal_index );
              if ( !clist )
              {
                   clist = new QConnectionList;
                   clist->setAutoDelete( TRUE );
                   s->connections->insert( signal_index, clist );
              }
              QMetaObject *rmeta = r->metaObject();
              switch ( membcode ) {     
                   case QSLOT_CODE:
                        rm = rmeta->slot( member_index, TRUE );
                        break;
                   case QSIGNAL_CODE:
                        rm = rmeta->signal( member_index, TRUE );
                        break;
              }
              QConnection *c = new QConnection( r, member_index,
              rm ? rm->name : "qt_invoke", membcode );
                
              clist->append( c );    
              if ( !r->senderObjects )
              {
                 
                  r->senderObjects = new QObjectList;
              }
              r->senderObjects->append( s );
          }
复制代码

 

    到此,信号与反应槽的连接已建立完毕,那么信号产生时又是如何触发反应槽的呢?从QObject的定义中可以看出其有多个activate_signal的成员函数,这些函数都是protected的,也即只有其自身或子类才可以使用。看一下它的实现:
          
复制代码
void QObject::activate_signal( QConnectionList *clist, QUObject *o )
          {
              if ( !clist )
                  return;
              QObject *object;
              QConnection *c;
              if ( clist->count() == 1 ) {
                     
                     
                 c = clist->first();
                 object = c->object();
                 sigSender = this;
                 if ( c->memberType() == QSIGNAL_CODE )
                     object->qt_emit( c->member(), o );
                 else
                     object->qt_invoke( c->member(), o );
              } else {
                  QConnectionListIt it(*clist);
                  while ( (c=it.current()) ) {
                      ++it;
                      object = c->object();
                      sigSender = this;
                      if ( c->memberType() == QSIGNAL_CODE )
                          object->qt_emit( c->member(), o );
                      else
                          object->qt_invoke( c->member(), o );
                  }
              }
          }
复制代码

 

          
    至此我们已经可以基本了解Qt中信号/反应槽的流程。我们再看一下Qt为此而新增的语法:三个关键字:slots、signals和emit,三个宏:SLOT()、SIGNAL()和Q_OBJECT。在头文件qobjectdefs.h中,我们可以看到这些新增语法的定义如下:
         
 #define slots // slots: in class
          #define signals protected // signals: in class
          #define emit // emit signal
          #define SLOT(a) "1"#a
          #define SIGNAL(a) "2"#a

 

    由此可知其实三个关键字没有做什么事情,而SLOT()和SIGNAL()宏也只是在字符串前面简单地加上单个字符,以便程序仅从名称就可以分辨谁是信号、谁是反应槽。中间编译程序moc.exe则可以根据这些关键字和宏对相应的函数进行“翻译”,以便在C++编译器中编译。剩下一个宏Q_OBJECT比较复杂,它的定义如下:
         
复制代码
 #define Q_OBJECT \
                  public: \
                      virtual QMetaObject *metaObject() const { \
                           return staticMetaObject(); \
                      }
                      \
                      virtual const char *className() const; \
                      virtual void* qt_cast( const char* ); \
                      virtual bool qt_invoke( int, QUObject* ); \
                      virtual bool qt_emit( int, QUObject* ); \
                      QT_PROP_FUNCTIONS
                      \
                      static QMetaObject* staticMetaObject(); \
                      QObject* qObject() { return (QObject*)this; } \
                      QT_TR_FUNCTIONS
                      \
                  private: \
                      static QMetaObject *metaObj;
复制代码

 

    从定义中可以看出该宏的作用有两个:一是对与自己相关的QMetaObject中间类操作进行声明,另一个是对信号的释放操作和反应槽的激活操作进行声明。当moc.exe对头文件进行预编译之后,将会产生一个可供C++编译器编译的源文件。以上述的Demo类为例,假设它的代码文件分别为demo.h和demo.cpp,预编译后将产生moc_demo.cpp,其主要内容如下:
 
          
复制代码
QMetaObject *Demo::metaObj = 0;
          void Demo::initMetaObject()
          {
              if ( metaObj )
                  return;
              if ( strcmp(QObject::className(), "QObject") != 0 )
                  badSuperclassWarning("Demo","QObject");
              (void) staticMetaObject();
          }
          
          QMetaObject* Demo::staticMetaObject()
          {
              if ( metaObj )
                  return metaObj;
              (void) QObject::staticMetaObject();
              typedef void(Demo::*m1_t0)(int);
              m1_t0 v1_0 = Q_AMPERSAND Demo::setValue;
              QMetaData *slot_tbl = QMetaObject::new_metadata(1);
             
              QMetaData::Access *slot_tbl_access = QMetaObject::new_metaaccess(1);
              slot_tbl[0].name = "setValue(int)";
              slot_tbl[0].ptr = *((QMember*)&v1_0);
             
              slot_tbl_access[0] = QMetaData::Public;
              typedef void(Demo::*m2_t0)(int);
              m2_t0 v2_0 = Q_AMPERSAND Demo::valueChanged;
              QMetaData *signal_tbl = QMetaObject::new_metadata(1);
              signal_tbl[0].name = "valueChanged(int)";
              signal_tbl[0].ptr = *((QMember*)&v2_0);
             
              metaObj = QMetaObject::new_metaobject(
             
              "Demo", "QObject",
              slot_tbl, 1,
              signal_tbl, 1,
              0, 0 );
              metaObj->set_slot_access( slot_tbl_access );
              return metaObj;
          }
          // 有信号时即激活对应的反应槽或另一个信号
          void Demo::valueChanged( int t0 )
          {
              activate_signal( "valueChanged(int)", t0 );
          }
复制代码

 

该文件中既没有Qt特有的关键字,也没有特殊的宏定义,完全符合普通的C++语法,因此可以顺利编译和链接。
 
 
 

 

posted @ 2021-02-10 17:20  papering  阅读(175)  评论(0编辑  收藏  举报