!7 // class AIConcept comes from #1007160 concept ImportedFrom { S snippetID; long lastTime; } static JTable table; static JCheckBox cbGrabImages; volatile sbool grabImages; volatile static double imageGrabberDelay = 1; // seconds, min 1 static Q uploadQ; p { grabImages = headless(); dbIndexing(AIConcept, 'searchedForSuggestedImage); framesBot(); // bot to activate my frames methodsBot("AI Concepts Import.", "importFrom", "importFromAI1Lol", "export"); uploadQ = new Q(true); startImageGrabber(); if (isHeadless()) ret; substance(); swingMain(); aiEnhancements(); } svoid swingMain swing { showConceptsTable_postProcess.set(f reversedList); table = makeConceptsTable(AIConcept, func(AIConcept c) { litorderedmap( "Concept ID" := c.globalID, "Name/Description" := c.name, "Comments" := c.comment, "Has Image?" := c.pngFile.has(), //"Imported From" := c.importedFrom, "Originating Universe" := c.originatingUniverse, "Exportable" := c.exportable) }); showFrame(makeTitle(), tableWithSearcher(table)); onEnter(tableSearchField(table), f newConcept); onDoubleClick(table, r { editConcept(selectedConcept()) }); addToWindow(table, withMargin(vstack( jRightAlignedLine( jbutton("New Concept...", f newConcept), tableDependButton(table, "Edit", r { editConcept(selectedConcept()) }), tableDependButton(table, "Duplicate", r { newConcept(selectedConcept()) }), jbutton("Export", f doExport), jbutton("Import...", f doImport)), withTopMargin(jRightAlignedLine(cbGrabImages = jCheckBox("Google For Images", grabImages)))))); tablePopupMenu(table, voidfunc(JPopupMenu menu, final int row) { final S globalID = (S) getTableCell(table, row, 0); final AIConcept c = findConcept(AIConcept, +globalID); addMenuItem(menu, "Edit...", r { editConcept(c) }); addMenuItem(menu, "Delete", r { withDBLock(r { deleteConcept(c) }); }); if (c.searchedForSuggestedImage) addMenuItem(menu, "Search for image again", r { deleteConcept(c.suggestedImage); cset(c, suggestedImage := null, searchedForSuggestedImage := false) }); }); tableEnableTextDrag(table); awtOnConceptChanges(table, 1000, r { setFrameTitle(table, makeTitle()) }); addAISuiteMenu(table, "AI"); hideConsole(); } svoid editConcept(final AIConcept c) { if (c == null) ret; final JTextField a = jTextField(c.name); final JTextField b = jTextField(c.comment); final JTextField cc = jTextField(c.globalID); final ImageChooser ic = new ImageChooser(c.pngFile.has() ? c.pngFile->getImageSafe() : null); ic.setTitleForUpload(c.name); PNGFile png = c.suggestedImage!; final ImageChooser ic2 = new ImageChooser(png != null ? png.getImageSafe() : null); final Var md5 = new Var(md5OfPNGFile(png)); awtOnConceptChanges(ic2, r { ic2.setTitleForUpload(c.name); PNGFile png = c.suggestedImage!; S newMD5 = md5OfPNGFile(png); if (png != null && neq(md5.get(), newMD5)) { md5.set(newMD5); ic2.setImage(png.getImageSafe()); } }, true); Runnable r = r { BufferedImage image = ic.getImage(); if (image == null && c.pngFile.has()) { //c.pngFile->delete(); c.pngFile.clear(); cset(c, imageMD5 := null); } else if (image != null && (!c.pngFile.has() || !imagesIdentical(c.pngFile->getImage(), image))) { //if (c.pngFile.has()) c.pngFile->delete(); setConceptImage(c, image); } cset(c, touched := now(), name := getTextTrim(a), comment := getTextTrim(b), globalID := getTextTrim(cc)); }; O[] params = { "Description/Name", a, "Comment (optional)", b, "Global ID", cc, "Example Image (optional)", westAndEast(ic, withLeftMargin(20, northAndCenter(vstack( jbutton("Accept", r { ic.setImage(ic2.getImage()); findButton(getFrame(ic), "Save").doClick(); }), jCenteredLabel("Suggested image:")), ic2))), r }; //for i over params: print("#" + i + ": " + params[i]); renameSubmitButton("Save", showFormTitled("Edit concept " + c.globalID, params)); } sS searcherInput() { ret getTextTrim(tableSearchField(table)); } svoid newConcept { newConcept(null); } svoid newConcept(final AIConcept c) { final JTextField a = jTextField(c == null ? searcherInput() : c.name); final JTextField b = jTextField(getString(c, "comment")); final JTextField cc = jTextField(aGlobalID()); final JLabel lbl = jCenteredLabel("Suggested image:"); final new ImageChooser ic; final new ImageChooser ic2; final new Var md5; awtCalcRegularly(ic2, 500, 0, new Runnable { S lastTyped, lastSearched; public void run { S s = getTextTrim(a); if (nempty(s) && eq(s, lastTyped) && neq(s, lastSearched)) { lastSearched = s; lbl.setIcon(imageIcon(#1007255)); try { final BufferedImage img = quickVisualize(s); if (img != null) swing { ic2.setImage(img); } } finally { lbl.setIcon(null); } } lastTyped = s; } }); Runnable r = r { AIConcept c = cnew(AIConcept, touched := now(), name := getTextTrim(a), comment := getTextTrim(b), globalID := getTextTrim(cc)); setConceptImage(c, ic.getImage()); }; renameSubmitButton("Create", showFormTitled("New concept", "Description/Name", a, "Comment (optional)", b, "Global ID", cc, "Example Image (optional)", westAndEast(ic, withLeftMargin(20, northAndCenter(vstack( jbutton("Accept", r { ic.setImage(ic2.getImage()) }), lbl), ic2))), r)); } static AIConcept selectedConcept() { ret findConcept(AIConcept, globalID := selectedTableCell(table, 0)); } svoid doImport { ImportedFrom last = last(sortedByField("lastTime", list(ImportedFrom))); final JTextField tf = jTextField(last == null ? #1007208 : last.snippetID); showFormTitled("Import A. I. Concepts", "Snippet ID", tf, r-thread { loading { importFrom(getTextTrim(tf)); } }); } svoid importFromAI1Lol { importFrom(freshConceptsFromAI1Lol(), "ai1.lol"); } svoid importFrom(S snippetID) { snippetID = fsI(snippetID); cset(uniq(ImportedFrom, +snippetID), lastTime := now()); S text = loadSnippet(snippetID); Concepts newConcepts = new Concepts(snippetID).safeLoad(text); importFrom(newConcepts, snippetID); } svoid importFrom(Concepts newConcepts, S snippetID) { print(n(list(newConcepts, "AIConcept"), "concept") + " loaded from " + snippetID); Concepts myConcepts = mainConcepts; print("I have " + n(list(myConcepts, "AIConcept"), "concept"); Map myIDs = indexByField(list(myConcepts, AIConcept), "globalID"); int nNew = 0; for (Concept c : list(newConcepts, "AIConcept")) { S id = getString(c, "globalID"); bool has = myIDs.containsKey(id); print("ID: " + id + " - " + (has ? "I have it" : "I don't have it")); if (!has) { // Creating AIConcept c2 = cnew(AIConcept, importedFrom := snippetID, imported := now()); importFields(c, c2); myIDs.put(id, c2); ++nNew; } else { // Updating AIConcept c2 = myIDs.get(id); if (c2.touched > c2.imported) print(" Concept touched locally! Not changing."); else { long time = now(); cset(c2, imported := time, touched := time); int changes = importFields(c, c2); if (changes == 0) print(" No change."); else print(" Updated concept! " + n(changes, "fields") + " changed"); } } } infoBox("Import done. " + n(nNew, "new concepts")); } static int importFields(Concept c, AIConcept c2) { c2.created = c.created; ret copyConceptFields(c, c2, "globalID", "name", "comment", "imageMD5", "originatingUniverse"); } svoid doExport { swingExportConcepts("AI Concepts"); } svoid export { swingExportConcepts_impl("AI Concepts"); } sS makeTitle() { ret "My AI Concepts [" + countConcepts(AIConcept) + "]"; } svoid startImageGrabber { thread "Image Grabber" { repeat with sleep imageGrabberDelay { if (headless() ? grabImages : isChecked(cbGrabImages)) { AIConcept c = findConcept(AIConcept, searchedForSuggestedImage := false); if (c != null) { cset(c, searchedForSuggestedImage := true); if (c.suggestedImage != null || c.importedFrom != null) continue; S query = c.name; //Window box = infoBox("Visualizing: " + c.name); BufferedImage img = quickVisualize(query); //disposeWindow(box); if (img != null) { showAnimation(img, c.name, 4); cset(c, suggestedImage := new PNGFile(quickVisualize_imagePath(query)), suggestedImageMD5 := md5OfBufferedImage(img)); } else infoBox("No image found"); } } } } } svoid setConceptImage(final AIConcept c, final BufferedImage img) { if (img == null) { c.pngFile.clear(); cset(c, imageMD5 := null); } else { c.pngFile.set(new PNGFile(img)); cset(c, imageMD5 := c.pngFile->md5()); uploadQ.add(r { uploadToImageServerIfNotThere(img, aiConceptToString(c)) }); } }