Start hops table display. The calculated preboil_sg value is stored global in memory. Added calculations for IBU, hop flavour and aroma.

Sat, 09 Apr 2022 21:50:19 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 09 Apr 2022 21:50:19 +0200
changeset 125
2e79e0975e58
parent 124
ba26b19572ab
child 126
3c013ef88a00

Start hops table display. The calculated preboil_sg value is stored global in memory. Added calculations for IBU, hop flavour and aroma.

src/EditRecipe.cpp file | annotate | diff | comparison | revisions
src/EditRecipe.h file | annotate | diff | comparison | revisions
src/MainWindow.h file | annotate | diff | comparison | revisions
src/Utils.cpp file | annotate | diff | comparison | revisions
src/Utils.h file | annotate | diff | comparison | revisions
ui/EditRecipe.ui file | annotate | diff | comparison | revisions
--- a/src/EditRecipe.cpp	Sat Apr 09 13:34:45 2022 +0200
+++ b/src/EditRecipe.cpp	Sat Apr 09 21:50:19 2022 +0200
@@ -488,6 +488,8 @@
     connect(ui->addFermentable, SIGNAL(clicked()), this, SLOT(on_addFermentRow_clicked()));
 
     // All signals from tab "Hops"
+    connect(ui->hop_tasteShow, &QProgressBar::valueChanged, this, &EditRecipe::on_Flavour_valueChanged);
+    connect(ui->hop_aromaShow, &QProgressBar::valueChanged, this, &EditRecipe::on_Aroma_valueChanged);
 //    connect(ui->hopsTable, SIGNAL(cellChanged(int, int)), this, SLOT(cell_Changed(int, int)));
 
     // All signals from tab "Miscs"
@@ -643,8 +645,186 @@
 }
 
 
+bool EditRecipe::hop_sort_test(const Hops &D1, const Hops &D2)
+{
+    return (D1.h_useat <= D2.h_useat ) && (D1.h_time >= D2.h_time) && (D1.h_amount >= D2.h_amount);
+}
+
+
 void EditRecipe::refreshHops()
 {
+    QString w;
+    QWidget* pWidget;
+    QHBoxLayout* pLayout;
+    QTableWidgetItem *item;
+
+    qDebug() << "refreshHops" << recipe->hops.size();
+    // std::sort(recipe->hops.begin(), recipe->hops.end(), hop_sort_test);
+
+    /*
+     * During filling the table turn off the cellChanged signal because every cell that is filled
+     * triggers the cellChanged signal. The QTableWidget has no better signal to use.
+     */
+    this->ignoreChanges = true;
+
+    const QStringList labels({tr("Origin"), tr("Hop"), tr("Type"), tr("Form"), tr("Alpha"), tr("Use at"), tr("Time"),
+                              tr("IBU"), tr("Amount"), tr("Delete"), tr("Edit") });
+
+    ui->hopsTable->setColumnCount(11);
+    ui->hopsTable->setColumnWidth(0, 150);     /* Origin	*/
+    ui->hopsTable->setColumnWidth(1, 225);     /* Hop		*/
+    ui->hopsTable->setColumnWidth(2,  75);     /* Type		*/
+    ui->hopsTable->setColumnWidth(3,  75);     /* Form          */
+    ui->hopsTable->setColumnWidth(4,  75);     /* Alpha%	*/
+    ui->hopsTable->setColumnWidth(5,  75);     /* Added         */
+    ui->hopsTable->setColumnWidth(6,  75);     /* Time		*/
+    ui->hopsTable->setColumnWidth(7,  60);     /* IBU		*/
+    ui->hopsTable->setColumnWidth(8,  75);     /* Amount	*/
+    ui->hopsTable->setColumnWidth(9,  80);     /* Delete        */
+    ui->hopsTable->setColumnWidth(10, 80);     /* Edit          */
+    ui->hopsTable->setHorizontalHeaderLabels(labels);
+    ui->hopsTable->verticalHeader()->hide();
+    ui->hopsTable->setRowCount(recipe->hops.size());
+
+    for (int i = 0; i < recipe->hops.size(); i++) {
+
+	ui->hopsTable->setItem(i, 0, new QTableWidgetItem(recipe->hops.at(i).h_origin));
+	ui->hopsTable->setItem(i, 1, new QTableWidgetItem(recipe->hops.at(i).h_name));
+
+	item = new QTableWidgetItem(h_types[recipe->hops.at(i).h_type]);
+        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+        ui->hopsTable->setItem(i, 2, item);
+
+	item = new QTableWidgetItem(h_forms[recipe->hops.at(i).h_form]);
+        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+        ui->hopsTable->setItem(i, 3, item);
+
+	item = new QTableWidgetItem(QString("%1%").arg(recipe->hops.at(i).h_alpha, 2, 'f', 1, '0'));
+        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->hopsTable->setItem(i, 4, item);
+
+	item = new QTableWidgetItem(h_useat[recipe->hops.at(i).h_useat]);
+        item->setTextAlignment(Qt::AlignCenter|Qt::AlignVCenter);
+        ui->hopsTable->setItem(i, 5, item);
+
+	if (recipe->hops.at(i).h_useat == 2 || recipe->hops.at(i).h_useat == 4) {	// Boil or whirlpool
+	    item = new QTableWidgetItem(QString("%1 min.").arg(recipe->hops.at(i).h_time, 1, 'f', 0, '0'));
+	} else if (recipe->hops.at(i).h_useat == 5) {					// Dry-hop
+	    item = new QTableWidgetItem(QString("%1 days.").arg(recipe->hops.at(i).h_time / 1440, 1, 'f', 0, '0'));
+	} else {
+	    item = new QTableWidgetItem(QString(""));
+	}
+	item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->hopsTable->setItem(i, 6, item);
+
+	double ibu = Utils::toIBU(recipe->hops.at(i).h_useat, recipe->hops.at(i).h_form, recipe->preboil_sg, recipe->batch_size, recipe->hops.at(i).h_amount,
+	                   recipe->hops.at(i).h_time, recipe->hops.at(i).h_alpha, recipe->ibu_method, 0, recipe->hops.at(i).h_time, 0);
+	item = new QTableWidgetItem(QString("%1").arg(ibu, 2, 'f', 1, '0'));
+        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->hopsTable->setItem(i, 7, item);
+
+	if (recipe->hops.at(i).h_amount < 1.0) {
+	    item = new QTableWidgetItem(QString("%1 gr").arg(recipe->hops.at(i).h_amount * 1000.0, 2, 'f', 1, '0'));
+	} else {
+	    item = new QTableWidgetItem(QString("%1 kg").arg(recipe->hops.at(i).h_amount, 4, 'f', 3, '0'));
+	}
+        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+        ui->hopsTable->setItem(i, 8, item);
+
+	/* Add the Delete row button */
+        pWidget = new QWidget();
+        QPushButton* btn_dele = new QPushButton();
+        btn_dele->setObjectName(QString("%1").arg(i));  /* Send row with the button */
+        btn_dele->setText(tr("Delete"));
+        connect(btn_dele, SIGNAL(clicked()), this, SLOT(on_deleteHopRow_clicked()));
+        pLayout = new QHBoxLayout(pWidget);
+        pLayout->addWidget(btn_dele);
+        pLayout->setContentsMargins(5, 0, 5, 0);
+        pWidget->setLayout(pLayout);
+        ui->hopsTable->setCellWidget(i, 9, pWidget);
+
+        pWidget = new QWidget();
+        QPushButton* btn_edit = new QPushButton();
+        btn_edit->setObjectName(QString("%1").arg(i));  /* Send row with the button */
+        btn_edit->setText(tr("Edit"));
+        connect(btn_edit, SIGNAL(clicked()), this, SLOT(on_editHopRow_clicked()));
+        pLayout = new QHBoxLayout(pWidget);
+        pLayout->addWidget(btn_edit);
+        pLayout->setContentsMargins(5, 0, 5, 0);
+        pWidget->setLayout(pLayout);
+        ui->hopsTable->setCellWidget(i, 10, pWidget);
+    }
+    this->ignoreChanges = false;
+}
+
+
+void EditRecipe::on_Flavour_valueChanged(int value)
+{
+    if (value < 20) {
+        ui->hop_tasteShow->setStyleSheet(bar_20);
+	ui->hop_tasteShow->setFormat(tr("Very low"));
+    } else if (value < 40) {
+	ui->hop_tasteShow->setStyleSheet(bar_40);
+	ui->hop_tasteShow->setFormat(tr("Low"));
+    } else if (value < 60) {
+        ui->hop_tasteShow->setStyleSheet(bar_60);
+        ui->hop_tasteShow->setFormat(tr("Moderate"));
+    } else if (value < 80) {
+        ui->hop_tasteShow->setStyleSheet(bar_80);
+        ui->hop_tasteShow->setFormat(tr("High"));
+    } else {
+        ui->hop_tasteShow->setStyleSheet(bar_100);
+	ui->hop_tasteShow->setFormat(tr("Very high"));
+    }
+}
+
+
+void EditRecipe::on_Aroma_valueChanged(int value)
+{
+    if (value < 20) {
+        ui->hop_aromaShow->setStyleSheet(bar_20);
+        ui->hop_aromaShow->setFormat(tr("Very low"));
+    } else if (value < 40) {
+        ui->hop_aromaShow->setStyleSheet(bar_40);
+        ui->hop_aromaShow->setFormat(tr("Low"));
+    } else if (value < 60) {
+        ui->hop_aromaShow->setStyleSheet(bar_60);
+        ui->hop_aromaShow->setFormat(tr("Moderate"));
+    } else if (value < 80) {
+        ui->hop_aromaShow->setStyleSheet(bar_80);
+        ui->hop_aromaShow->setFormat(tr("High"));
+    } else {
+        ui->hop_aromaShow->setStyleSheet(bar_100);
+        ui->hop_aromaShow->setFormat(tr("Very high"));
+    }
+}
+
+
+void EditRecipe::calcIBUs()
+{
+    double hop_flavour = 0, hop_aroma = 0, ibus = 0;
+
+    for (int i = 0; i < recipe->hops.size(); i++) {
+
+	ibus += Utils::toIBU(recipe->hops.at(i).h_useat, recipe->hops.at(i).h_form, recipe->preboil_sg, recipe->batch_size, recipe->hops.at(i).h_amount,
+                           recipe->hops.at(i).h_time, recipe->hops.at(i).h_alpha, recipe->ibu_method, 0, recipe->hops.at(i).h_time, 0);
+	hop_flavour += Utils::hopFlavourContribution(recipe->hops.at(i).h_time, recipe->batch_size, recipe->hops.at(i).h_useat, recipe->hops.at(i).h_amount);
+        hop_aroma += Utils::hopAromaContribution(recipe->hops.at(i).h_time, recipe->batch_size, recipe->hops.at(i).h_useat, recipe->hops.at(i).h_amount);
+    }
+
+    hop_flavour = round(hop_flavour * 1000.0 / 5.0) / 10;
+    hop_aroma = round(hop_aroma * 1000.0 / 6.0) / 10;
+    if (hop_flavour > 100)
+        hop_flavour = 100;
+    if (hop_aroma > 100)
+        hop_aroma = 100;
+    qDebug() << "ibu" << recipe->est_ibu << ibus << "flavour" << hop_flavour << "aroma" << hop_aroma;
+
+    recipe->est_ibu = ibus;
+    ui->est_ibuEdit->setValue(recipe->est_ibu);
+    ui->est_ibu2Edit->setValue(recipe->est_ibu);
+    ui->hop_tasteShow->setValue(hop_flavour);
+    ui->hop_aromaShow->setValue(hop_aroma);
 }
 
 
@@ -666,8 +846,12 @@
 void EditRecipe::refreshAll()
 {
     refreshFermentables();
-
-    calcFermentables();
+    calcFermentables();		/* Must be before Hops */
+    refreshHops();
+    calcIBUs();
+    refreshMiscs();
+    refreshYeasts();
+    refreshMashs();
 }
 
 
@@ -789,8 +973,8 @@
     ui->est_og3Edit->setValue(og);
     ui->est_ogShow->setValue(og);
 
-    double preboil_sg = Utils::estimate_sg(sugarsm, ui->boil_sizeEdit->value());
-    qDebug() << "  preboil SG" << preboil_sg;
+    recipe->preboil_sg = Utils::estimate_sg(sugarsm, ui->boil_sizeEdit->value());
+    qDebug() << "  preboil SG" << recipe->preboil_sg;
 
     /*
      * Color of the wort
--- a/src/EditRecipe.h	Sat Apr 09 13:34:45 2022 +0200
+++ b/src/EditRecipe.h	Sat Apr 09 21:50:19 2022 +0200
@@ -233,6 +233,7 @@
     int		misc_row;
     int		yeasts_row;
     int		mashs_row;
+    double	preboil_sg;
 };
 
 
@@ -280,6 +281,8 @@
     void on_perc_sugars_valueChanged(int value);
     void on_perc_cara_valueChanged(int value);
     void on_lintner_valueChanged(int value);
+    void on_Flavour_valueChanged(int value);
+    void on_Aroma_valueChanged(int value);
 
 private:
     Ui::EditRecipe *ui;
@@ -287,9 +290,17 @@
     QStringList f_types = { tr("Grain"), tr("Sugar"), tr("Extract"), tr("Dry extract"), tr("Adjunct") };
     QStringList f_graintypes = { tr("Base"), tr("Roast"), tr("Crystal"), tr("Kilned"), tr("Sour Malt"), tr("Special"), tr("No malt")};
     QStringList f_added = { tr("Mash"), tr("Boil"), tr("Fermentation"), tr("Lagering"), tr("Bottle"), tr("Kegs") };
+    QStringList h_types = { tr("Bittering"), tr("Aroma"), tr("Both") };
+    QStringList h_forms = { tr("Pellet"), tr("Plug"), tr("Leaf"), tr("Leaf wet"), tr("Cryo") };
+    QStringList h_useat = { tr("Mash"), tr("First wort"), tr("Boil"), tr("Aroma"), tr("Whirlpool"), tr("Dry hop") };
     QString bar_red = "QProgressBar::chunk {background: #FF0000;}";
     QString bar_orange = "QProgressBar::chunk {background: #EB7331;}";
     QString bar_green = "QProgressBar::chunk {background: #008C00;}";
+    QString bar_20 = "QProgressBar::chunk {background: #004D00;}";
+    QString bar_40 = "QProgressBar::chunk {background: #008C00;}";
+    QString bar_60 = "QProgressBar::chunk {background: #00BF00;}";
+    QString bar_80 = "QProgressBar::chunk {background: #00FF00;}";
+    QString bar_100 = "QProgressBar::chunk {background: #80FF80;}";
     int recno;
     bool textIsChanged = false;
     bool ignoreChanges = false;
@@ -304,8 +315,10 @@
 
     void to100Fermentables(int row);
     static bool ferment_sort_test(const Fermentables &D1, const Fermentables &D2);
+    static bool hop_sort_test(const Hops &D1, const Hops &D2);
     void WindowTitle();
     void calcFermentables();
+    void calcIBUs();
 };
 
 #endif
--- a/src/MainWindow.h	Sat Apr 09 13:34:45 2022 +0200
+++ b/src/MainWindow.h	Sat Apr 09 21:50:19 2022 +0200
@@ -77,7 +77,19 @@
 
 static IniWS wsProd;
 static IniWS wsDev;
+
+
+static QString my_brewery_name = "No-name";
+static double my_factor_mashhop = -30;
+static double my_factor_fwh = 10;
+static double my_factor_pellet = 10;
+static double my_factor_plug = 2;
+static double my_factor_wethop = -82;
+static double my_factor_cryohop = 100;
+static int my_ibu_method = 0;
+static int my_color_method = 0;
 static double my_brix_correction = 1.04;
+static double my_grain_absorbtion = 1.01;
 
 
 namespace Ui {
--- a/src/Utils.cpp	Sat Apr 09 13:34:45 2022 +0200
+++ b/src/Utils.cpp	Sat Apr 09 21:50:19 2022 +0200
@@ -330,3 +330,136 @@
 }
 
 
+double Utils::toIBU(int Use, int Form, double SG, double Volume, double Amount, double Boiltime, double Alpha,
+		    int Method, double Whirlpool9, double Whirlpool7, double Whirlpool6)
+{
+    double	fmoment = 1.0, pfactor = 1.0, ibu = 0, boilfactor;
+    double	sgfactor, AddedAlphaAcids, Bigness_factor, BoilTime_factor, utiisation;
+
+    double gravity = SG;
+    double liters = Volume;
+    double alpha = Alpha / 100.0;
+    double mass = Amount * 1000.0;
+    double time = Boiltime;
+
+    if ((Use == 3) || (Use == 4) || (Use == 5)) {	// Aroma, Whirlpool or Dry hop.
+	fmoment = 0.0;
+    } else if (Use == 0) { // Mash
+	fmoment += my_factor_mashhop / 100.0;		// Brouwhulp
+    } else if (Use == 1) { // First wort
+	fmoment += my_factor_fwh / 100.0;			// Brouwhulp, Louis, Ozzie
+    }
+
+    if (Form == 0) {				// Pellet
+	pfactor += my_factor_pellet / 100.0;
+    } else if (Form == 1) {			// Plug
+	pfactor += my_factor_plug / 100.0;
+    } else if (Form == 3) {			// Wet leaf
+	pfactor += my_factor_wethop / 100.0;	// From https://github.com/chrisgilmerproj/brewday/blob/master/brew/constants.py
+    } else if (Form == 4) {			// Cryo hop
+	pfactor += my_factor_cryohop / 100.0;
+    }
+
+    // Ideas from Zymurgy March-April 2018. These are not exact formulas!
+    double whirlibus = 0.0;
+    if (Use == 3 || Use == 4) { // Flameout or any whirlpool
+
+	if (Whirlpool9) {
+	    // 20 mg/l/50 min
+	    whirlibus += (alpha * mass * 20) / liters * (Whirlpool9 / 50.0);
+	    qDebug() << "Whirlpool9" << alpha * mass * 20 << " liter:" << liters << " time:" << Whirlpool9 << " ibu" << (alpha * mass * 20) / liters * (Whirlpool9 / 50.0);
+	} else {
+	    if (Use == 3) { // Flameout hops are 2 minutes in this range.
+		whirlibus += (alpha * mass * 20) / liters * (2.0 / 50.0);
+	    }
+	}
+	if (Whirlpool7) {
+	    // 6 mg/l/50 min
+	    whirlibus += (alpha * mass * 6) / liters * (Whirlpool7 / 50.0);
+	    qDebug() << "Whirlpool7" << alpha * mass * 6 << " liter:" << liters << " time:" << Whirlpool7 << " ibu" << (alpha * mass * 6) / liters * (Whirlpool7 / 50.0);
+	} else {
+	    if (Use == 3) { // Flameout hops are 4 minutes in this range.
+		whirlibus += (alpha * mass * 6) / liters * (4.0 / 50.0);
+	    }
+	}
+	if (Whirlpool6) {
+	    // 2 mg/l/50 min
+	    whirlibus += (alpha * mass * 2) / liters * (Whirlpool6 / 50.0);
+	    //console.log('Whirlpool6:' + alpha * mass * 2 + ' liter:' + liters + ' time:' + Whirlpool6 + ' ibu' + (alpha * mass * 2) / liters * (Whirlpool6 / 50));
+	}
+    }
+
+    if (Method == 0) { // Tinseth
+	/* http://realbeer.com/hops/research.html */
+	AddedAlphaAcids = (alpha * mass * 1000) / liters;
+	Bigness_factor = 1.65 * pow(0.000125, gravity - 1);
+	BoilTime_factor = ((1 - exp(-0.04 * time)) / 4.15);
+	utiisation = Bigness_factor * BoilTime_factor;
+	ibu = round((utiisation * AddedAlphaAcids * fmoment * pfactor + whirlibus) * 100) / 100;
+    }
+    if (Method == 2) { // Daniels
+	if (Form == 2) // Leaf
+	    boilfactor = -(0.0041 * time * time) + (0.6162 * time) + 1.5779;
+	else
+	    boilfactor = -(0.0051 * time * time) + (0.7835 * time) + 1.9348;
+	if (gravity < 1050)
+	    sgfactor = 0;
+	else
+	    sgfactor = (gravity - 1050) / 200;
+	ibu = round((fmoment * ((mass * (alpha * 100) * boilfactor * 0.1) / (liters * (1 + sgfactor))) + whirlibus) * 100) / 100;
+    }
+    if (Method == 1) { // Rager
+	boilfactor = fmoment * 18.11 + 13.86 * tanh((time * 31.32) / 18.27);
+	if (gravity < 1050)
+	    sgfactor = 0;
+	else
+	    sgfactor = (gravity - 1050) / 200;
+	ibu = round(((mass * (alpha * 100) * boilfactor * 0.1) / (liters * (1 + sgfactor)) + whirlibus) * 100) / 100;
+    }
+
+    return ibu;
+}
+
+
+double Utils::hopFlavourContribution(double bt, double vol, int use, double amount)
+{
+    double result;
+
+    if (use == 4 || use == 5) // Whirlpool or Dry-hop
+	return 0;
+    if (use == 1) {   // First wort
+	result = 0.15;   // assume 15% flavourcontribution for fwh
+    } else if (bt > 50) {
+	result = 0.10;   // assume 10% flavourcontribution as a minimum
+    } else {
+	result = 15.25 / (6 * sqrt(2 * 3.1416)) * exp(-0.5 * pow((bt - 21.0) / 6.0, 2.0));
+	if (result < 0.10)
+	    result = 0.10;  // assume 10% flavourcontribution as a minimum
+    }
+    return (result * amount * 1000.0) / vol;
+}
+
+
+double Utils::hopAromaContribution(double bt, double vol, int use, double amount)
+{
+    double result = 0.0;
+
+    if (use == 5) {         // Dry hop
+	result = 1.33;
+    } else if (use == 4) { // Whirlpool
+	if (bt > 30)
+	    bt = 30; // Max 30 minutes
+	result = 0.62 * bt / 30.0;
+    } else if (bt > 20) {
+	result = 0.0;
+    } else if (bt > 7.5) {
+	result = 10.03 / (4 * sqrt(2 * 3.1416)) * exp(-0.5 * pow((bt - 7.5) / 4.0, 2.0));
+    } else if (use == 2) {  // Boil
+	result = 1;
+    } else if (use == 3) {  // Aroma
+	result = 1.2;
+    }
+    return (result * amount * 1000.0) / vol;
+}
+
+
--- a/src/Utils.h	Sat Apr 09 13:34:45 2022 +0200
+++ b/src/Utils.h	Sat Apr 09 21:50:19 2022 +0200
@@ -28,6 +28,10 @@
     double kw_to_srm(int colormethod, double c);
     double kw_to_ebc(int colormethod, double c);
     double abvol(double og, double fg);
+    double toIBU(int Use, int Form, double SG, double Volume, double Amount, double Boiltime, double Alpha,
+                 int Method, double Whirlpool9, double Whirlpool7, double Whirlpool6);
+    double hopFlavourContribution(double bt, double vol, int use, double amount);
+    double hopAromaContribution(double bt, double vol, int use, double amount);
     QString hours_to_string(int hours);
 
     /**
--- a/ui/EditRecipe.ui	Sat Apr 09 13:34:45 2022 +0200
+++ b/ui/EditRecipe.ui	Sat Apr 09 21:50:19 2022 +0200
@@ -1400,7 +1400,7 @@
          <rect>
           <x>140</x>
           <y>10</y>
-          <width>71</width>
+          <width>81</width>
           <height>24</height>
          </rect>
         </property>
@@ -1509,12 +1509,29 @@
         <property name="geometry">
          <rect>
           <x>10</x>
-          <y>50</y>
+          <y>100</y>
           <width>1101</width>
-          <height>411</height>
+          <height>361</height>
          </rect>
         </property>
        </widget>
+       <widget class="QPushButton" name="addHop">
+        <property name="geometry">
+         <rect>
+          <x>140</x>
+          <y>70</y>
+          <width>80</width>
+          <height>23</height>
+         </rect>
+        </property>
+        <property name="text">
+         <string>Add</string>
+        </property>
+        <property name="icon">
+         <iconset resource="../../../../../../home/mbroek/MyProjects/bmsapp/resources/icons.qrc">
+          <normaloff>:/icons/bms/hop.png</normaloff>:/icons/bms/hop.png</iconset>
+        </property>
+       </widget>
       </widget>
       <widget class="QWidget" name="miscs">
        <attribute name="icon">

mercurial