src/primitives.cpp

changeset 293
a0ed563e14b2
parent 292
4779ca562d5e
child 294
2892deee4c1b
--- a/src/primitives.cpp	Sat Jun 15 19:14:42 2013 +0300
+++ b/src/primitives.cpp	Sun Jun 16 00:10:11 2013 +0300
@@ -1,11 +1,46 @@
 #include <QDir>
 #include <QThread>
+#include <QRegExp>
 #include "file.h"
 #include "gui.h"
 #include "primitives.h"
 
-PrimitiveLister* g_activePrimLister = null;
-vector<Primitive> g_Primitives;
+vector<PrimitiveCategory> g_PrimitiveCategories;
+static PrimitiveLister* g_activePrimLister = null;
+static bool g_primListerMutex = false;
+vector<Primitive> g_primitives;
+
+static void populateCategories ();
+static void loadPrimitiveCatgories ();
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+void loadPrimitives () {
+	print ("Loading primitives...\n");
+	
+	loadPrimitiveCatgories ();
+	
+	// Try to load prims.cfg
+	File conf (config::dirpath () + "prims.cfg", File::Read);
+	if (!conf) {
+		// No prims.cfg, build it
+		PrimitiveLister::start ();
+	} else {
+		for (str line : conf) {
+			int space = line.indexOf (" ");
+			if (space == -1)
+				continue;
+			
+			Primitive info;
+			info.name = line.left (space);
+			info.title = line.mid (space + 1);
+			g_primitives << info;
+		}
+	}
+	
+	populateCategories ();
+}
 
 // =============================================================================
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -23,6 +58,9 @@
 	}
 }
 
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
 void PrimitiveLister::work () {
 	g_activePrimLister = this;
 	m_prims.clear ();
@@ -54,6 +92,9 @@
 			info.title = info.title.simplified ();
 		}
 		
+		// Figure which category to use
+		info.cat = null;
+		
 		m_prims << info;
 		emit update (++i);
 	}
@@ -66,13 +107,15 @@
 	conf.close ();
 	
 	g_primListerMutex = true;
-	g_Primitives = m_prims;
+	g_primitives = m_prims;
 	g_primListerMutex = false;
-	
 	g_activePrimLister = null;
 	emit workDone ();
 }
 
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
 void PrimitiveLister::start () {
 	if (g_activePrimLister)
 		return;
@@ -88,25 +131,122 @@
 	listerThread->start ();
 }
 
-void loadPrimitives () {
-	g_Primitives.clear ();
+static PrimitiveCategory* findCategory (str name) {
+	for (PrimitiveCategory& cat : g_PrimitiveCategories)
+		if (cat.name () == name)
+			return &cat;
 	
-	// Try to load prims.cfg
-	File conf (config::dirpath () + "prims.cfg", File::Read);
-	if (!conf) {
-		// No prims.cfg, build it
-		PrimitiveLister::start ();
-		return;
+	return null;
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+static void populateCategories () {
+	for (PrimitiveCategory& cat : g_PrimitiveCategories)
+		cat.prims.clear ();
+	
+	PrimitiveCategory* unmatched = findCategory ("Other");
+	
+	if (!unmatched) {
+		// Shouldn't happen.. but catch it anyway.
+		print ("No `Other` category found! Creating one...\n");
+		PrimitiveCategory cat;
+		cat.setName ("Other");
+		unmatched = &(g_PrimitiveCategories << cat);
 	}
 	
-	for (str line : conf) {
-		int space = line.indexOf (" ");
-		if (space == -1)
-			continue;
+	for (Primitive& prim : g_primitives) {
+		bool matched = false;
+		
+		// Go over the categories and their regexes, if and when there's a match,
+		// the primitive's category is set to the category the regex beloings to.
+		for (PrimitiveCategory& cat : g_PrimitiveCategories) {
+			for (PrimitiveCategory::RegexEntry& entry : cat.regexes) {
+				switch (entry.type) {
+				case PrimitiveCategory::Filename:
+					// f-regex, check against filename
+					matched = entry.regex.exactMatch (prim.name);
+					break;
+					
+				case PrimitiveCategory::Title:
+					// t-regex, check against title
+					matched = entry.regex.exactMatch (prim.title);
+					break;
+				}
+				
+				if (matched) {
+					prim.cat = &cat;
+					break;
+				}
+			}
+			
+			// Drop out if a category was decided on.
+			if (prim.cat)
+				break;
+		}
 		
-		Primitive info;
-		info.name = line.left (space);
-		info.title = line.mid (space + 1);
-		g_Primitives << info;
+		// If there was a match, add the primitive to the category.
+		// Otherwise, add it to the list of unmatched primitives.
+		if (prim.cat)
+			prim.cat->prims << prim;
+		else
+			unmatched->prims << prim;
 	}
+}
+
+// =============================================================================
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+// =============================================================================
+static void loadPrimitiveCatgories () {
+	g_PrimitiveCategories.clear ();
+	
+	File f (config::dirpath () + "primregexps.cfg", File::Read);
+	
+	if (!f)
+		f.open (":/data/primitive-categories.cfg", File::Read);
+	
+	if (!f)
+		critical ("Failed to open primitive categories!");
+	
+	if (f) {
+		PrimitiveCategory cat;
+		
+		for (str line : f) {
+			int colon;
+			
+			if (line.length () == 0 || line[0] == '#')
+				continue;
+			
+			if ((colon = line.indexOf (":")) == -1) {
+				if (cat.regexes.size () > 0)
+					g_PrimitiveCategories << cat;
+				
+				cat.regexes.clear ();
+				cat.prims.clear ();
+				cat.setName (line);
+			} else {
+				str cmd = line.left (colon);
+				
+				PrimitiveCategory::Type type = PrimitiveCategory::Filename;
+				if (cmd == "f") {
+					type = PrimitiveCategory::Filename;
+				} else if (cmd == "t") {
+					type = PrimitiveCategory::Title;
+				}
+				
+				QRegExp regex (line.mid (colon + 1));
+				PrimitiveCategory::RegexEntry entry = { regex, type };
+				cat.regexes << entry;
+			}
+		}
+		
+		if (cat.regexes.size () > 0)
+			g_PrimitiveCategories << cat;
+	}
+	
+	// Add a category for unmatched primitives
+	PrimitiveCategory cat;
+	cat.setName ("Other");
+	g_PrimitiveCategories << cat;
 }
\ No newline at end of file

mercurial