void CountryCollection::WriteTags(const std::string& fileName) const
{
  std::ofstream tagsFile(fileName);
  if (!tagsFile)
    throw std::runtime_error("Error creating tags file");
  for (const auto& countryPair : countries)
    tagsFile << countryPair.first << " = " << "countries/" << NormalizeName(countryPair.second.GetName()) << ".txt\n";
}
void TikzCommandInserter::getCommands()
{
	QFile tagsFile(":/tikzcommands.xml");
	if (!tagsFile.open(QFile::ReadOnly))
		return;

	QApplication::setOverrideCursor(Qt::WaitCursor);
	xml.setDevice(&tagsFile);
	if (xml.readNextStartElement())
	{
		if (xml.name() == "tikzcommands")
			m_tikzSections = getChildCommands();
		else
			xml.raiseError(tr("Cannot parse the TikZ commands file."));
	}
	if (xml.error()) // this should never happen in a final release because tikzcommands.xml is built in the binary
		qCritical("Parse error in TikZ commands file at line %d, column %d:\n%s", (int)xml.lineNumber(), (int)xml.columnNumber(), qPrintable(xml.errorString()));
	QApplication::restoreOverrideCursor();
}
void uiFileDetailsTreeView::show_file_details(const Gtk::TreeModel::iterator& iter)
{
	Gtk::TreeModel::Row row = *iter;

	sqlite3_stmt *stmt = 0;
	const char query[] = "SELECT header FROM files WHERE animalID=? AND cellID=? AND fileID=?";
	sqlite3_prepare_v2(*db, query, strlen(query), &stmt, NULL);
	sqlite3_bind_text(stmt, 1, row.get_value(m_Columns.m_col_animalID).c_str(), -1, SQLITE_TRANSIENT);
	sqlite3_bind_int(stmt, 2, row.get_value(m_Columns.m_col_cellID));
	sqlite3_bind_int(stmt, 3, row.get_value(m_Columns.m_col_filenum));

	int r = sqlite3_step(stmt);

	if (r == SQLITE_ROW) {

		SpikeData sd;
		void *header = (void*)sqlite3_column_blob(stmt, 0);
		sd.setHeader(header);

		Gtk::Dialog dialog("File Details", true);
		dialog.set_transient_for(*m_parent);
		dialog.set_resizable(false);
		dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
		dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);

		Gtk::HBox hbTime;
		Gtk::Label lblTimeName("Recording Time: ");
		Gtk::Label lblTime(sd.iso8601(sd.m_head.cDateTime));
		hbTime.pack_start(lblTimeName);
		hbTime.pack_start(lblTime);
		dialog.get_vbox()->pack_start(hbTime);

		Gtk::CheckButton cbHidden("Hide file in file list");
		cbHidden.set_active(row.get_value(m_Columns.m_col_hidden));
		dialog.get_vbox()->pack_start(cbHidden);

		sqlite3_stmt *stmt2 = 0;
		const char query2[] = "SELECT tag FROM tags WHERE animalID=? AND cellID=? AND fileID=?";
		sqlite3_prepare_v2(*db, query2, -1, &stmt2, 0);
		sqlite3_bind_text(stmt2, 1, row.get_value(m_Columns.m_col_animalID).c_str(), -1, SQLITE_TRANSIENT);
		sqlite3_bind_int(stmt2, 2, row.get_value(m_Columns.m_col_cellID));
		sqlite3_bind_int(stmt2, 3, row.get_value(m_Columns.m_col_filenum));
		std::vector<Glib::ustring> tags;
		while (sqlite3_step(stmt2) == SQLITE_ROW) {
			Glib::ustring t = (char*)sqlite3_column_text(stmt2, 0);
			tags.push_back(t);
		}
		sqlite3_finalize(stmt2);
		Gtk::Frame frameTags("File Tags");
		uiTags tagsFile(m_parent);
		tagsFile.tags(tags);
		tagsFile.delete_assist = true;
		frameTags.add(tagsFile);
		dialog.get_vbox()->pack_start(frameTags);
		tagsFile.signal_deleted().connect(sigc::mem_fun(*this, &uiFileDetailsTreeView::on_tag_deleted));
		tagsFile.signal_added().connect(sigc::mem_fun(*this, &uiFileDetailsTreeView::on_tag_added));
		dialog.show_all_children();
		int result = dialog.run();


		switch (result) {
			case (Gtk::RESPONSE_OK):
				if (row.get_value(m_Columns.m_col_hidden) != cbHidden.get_active())
					m_signal_file_set_hidden.emit(cbHidden.get_active());
				break;
		}

	} else {
		Gtk::MessageDialog dialog(*m_parent, "Error loading file from database.", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
		dialog.set_secondary_text(sqlite3_errmsg(*db));
		dialog.run();
	}
	sqlite3_finalize(stmt);

}