Typica is a free program for professional coffee roasters. https://typica.us
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

roastspec.xml 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <window id="roastspec">
  2. <layout type="horizontal">
  3. <layout type="vertical">
  4. <layout type="horizontal">
  5. <label>Coffee:</label>
  6. <sqldrop data="0" display="1" showdata="false" id="currentitems">
  7. <query>SELECT id, name FROM items WHERE id IN (SELECT item FROM current_items) ORDER BY name</query>
  8. </sqldrop>
  9. </layout>
  10. <tabbar id="tabs" />
  11. <layout type="stack" id="pages">
  12. <page>
  13. <layout type="vertical">
  14. <layout type="horizontal">
  15. <label>Expected % weight loss:</label>
  16. <line validator="numeric" id="expectedloss" />
  17. </layout>
  18. <layout type="horizontal">
  19. <label>Tolerance</label>
  20. <line validator="numeric" id="tolerance" />
  21. </layout>
  22. <stretch />
  23. </layout>
  24. </page>
  25. <page>
  26. <layout type="vertical">
  27. <layout type="horizontal">
  28. <label>Whole color:</label>
  29. <line validator="numeric" id="expectedwhole" />
  30. </layout>
  31. <layout type="horizontal">
  32. <label>Tolerance:</label>
  33. <line validator="numeric" id="wholetolerance" />
  34. </layout>
  35. <layout type="horizontal">
  36. <label>Ground color:</label>
  37. <line validator="numeric" id="expectedground" />
  38. </layout>
  39. <layout type="horizontal">
  40. <label>Tolerance:</label>
  41. <line validator="numeric" id="groundtolerance" />
  42. </layout>
  43. <stretch />
  44. </layout>
  45. </page>
  46. <page>
  47. <layout type="vertical">
  48. <label>Specification Notes:</label>
  49. <textarea id="notes" />
  50. <stretch />
  51. </layout>
  52. </page>
  53. </layout>
  54. <layout type="horizontal">
  55. <stretch />
  56. <button id="save" type="push" name="Save" />
  57. </layout>
  58. </layout>
  59. </layout>
  60. <program>
  61. <![CDATA[
  62. var window = this;
  63. this.windowTitle = TTR("roastspec", "Typica - Edit Roasting Specification");
  64. var tabs = findChildObject(this, 'tabs');
  65. tabs.addTab("Weight Loss");
  66. tabs.addTab("Color");
  67. tabs.addTab("Notes");
  68. var pages = findChildObject(this, 'pages');
  69. tabs.currentChanged.connect(function(index) {
  70. pages.setCurrentIndex(index);
  71. });
  72. var selector = findChildObject(this, 'currentitems');
  73. var expected = findChildObject(this, 'expectedloss');
  74. var tolerance = findChildObject(this, 'tolerance');
  75. var notes = findChildObject(this, 'notes');
  76. var savebutton = findChildObject(this, 'save');
  77. var wholecolor = findChildObject(this, 'expectedwhole');
  78. var groundcolor = findChildObject(this, 'expectedground');
  79. var wholetolerance = findChildObject(this, 'wholetolerance');
  80. var groundtolerance = findChildObject(this, 'groundtolerance');
  81. var updateDisplay = function() {
  82. var query = new QSqlQuery();
  83. query.prepare("SELECT loss, tolerance, notes, spec FROM roasting_specification WHERE item = :id1 AND time = (SELECT max(time) FROM roasting_specification WHERE item = :id2)");
  84. query.bind(":id1", selector.currentData());
  85. query.bind(":id2", selector.currentData());
  86. query.exec();
  87. if(query.next()) {
  88. if(query.value(0).length > 0) {
  89. expected.text = Number(query.value(0)) * 100;
  90. } else {
  91. expected.text = "";
  92. }
  93. if(query.value(1).length > 0) {
  94. tolerance.text = Number(query.value(1)) * 100;
  95. } else {
  96. tolerance.text = "";
  97. }
  98. notes.plainText = query.value(2);
  99. if(query.value(3).length > 0) {
  100. var spec = JSON.parse(query.value(3));
  101. if(spec.color === undefined) {
  102. wholecolor.text = "";
  103. wholetolerance.text = "";
  104. groundcolor.text = "";
  105. groundtolerance.text = "";
  106. } else {
  107. if(spec.color.whole === undefined) {
  108. wholecolor.text = "";
  109. wholetolerance.text = "";
  110. } else {
  111. if(spec.color.whole.expected === undefined) {
  112. wholecolor.text = "";
  113. } else {
  114. wholecolor.text = spec.color.whole.expected;
  115. }
  116. if(spec.color.whole.tolerance === undefined) {
  117. wholetolerance.text = "";
  118. } else {
  119. wholetolerance.text = spec.color.whole.tolerance;
  120. }
  121. }
  122. if(spec.color.ground === undefined) {
  123. groundcolor.text = "";
  124. groundtolerance.text = "";
  125. } else {
  126. if(spec.color.ground.expected === undefined) {
  127. groundcolor.text = "";
  128. } else {
  129. groundcolor.text = spec.color.ground.expected;
  130. }
  131. if(spec.color.ground.tolerance === undefined) {
  132. groundtolerance.text = "";
  133. } else {
  134. groundtolerance.text = spec.color.ground.tolerance;
  135. }
  136. }
  137. }
  138. }
  139. } else {
  140. expected.text = "";
  141. tolerance.text = "";
  142. notes.plainText = "";
  143. wholecolor.text = "";
  144. wholetolerance.text = "";
  145. groundcolor.text = "";
  146. groundtolerance.text = "";
  147. }
  148. query = query.invalidate();
  149. };
  150. updateDisplay();
  151. selector['currentIndexChanged(int)'].connect(function() {
  152. updateDisplay();
  153. });
  154. savebutton.clicked.connect(function() {
  155. var specobject = new Object;
  156. var query = new QSqlQuery();
  157. var columnspec = "time, item, ";
  158. var valuespec = "'now', :id, ";
  159. if(expected.text.length > 0) {
  160. columnspec += "loss, ";
  161. valuespec += ":loss, ";
  162. var lossspec = new Object;
  163. lossspec.expected = expected.text;
  164. if(tolerance.text.length > 0) {
  165. columnspec += "tolerance, ";
  166. valuespec += ":tolerance, ";
  167. lossspec.tolerance = tolerance.text;
  168. }
  169. specobject.loss = lossspec;
  170. }
  171. colorspec = new Object;
  172. if(wholecolor.text.length > 0) {
  173. wholespec = new Object;
  174. wholespec.expected = wholecolor.text;
  175. if(wholetolerance.text.length > 0) {
  176. wholespec.tolerance = wholetolerance.text;
  177. }
  178. colorspec.whole = wholespec;
  179. }
  180. if(groundcolor.text.length > 0) {
  181. groundspec = new Object;
  182. groundspec.expected = groundcolor.text;
  183. if(groundtolerance.text.length > 0) {
  184. groundspec.tolerance = groundtolerance.text;
  185. }
  186. colorspec.ground = groundspec;
  187. }
  188. if(colorspec.whole || colorspec.ground) {
  189. specobject.color = colorspec;
  190. }
  191. if(notes.plainText.length > 0) {
  192. specobject.notes = notes.plainText;
  193. }
  194. columnspec += "notes, spec";
  195. valuespec += ":notes, :spec";
  196. query.prepare("INSERT INTO roasting_specification (" + columnspec + ") VALUES (" + valuespec + ")");
  197. query.bind(":id", selector.currentData());
  198. if(expected.text.length > 0) {
  199. query.bind(":loss", Number(expected.text) / 100);
  200. }
  201. if(tolerance.text.length > 0) {
  202. query.bind(":tolerance", Number(tolerance.text) / 100);
  203. }
  204. query.bind(":notes", notes.plainText);
  205. query.bind(":spec", JSON.stringify(specobject));
  206. query.exec();
  207. displayInfo(TTR("roastspec", "New Specification Saved"),
  208. TTR("roastspec", "New roasting specification saved"));
  209. });
  210. ]]>
  211. </program>
  212. </window>