<commit_before>/*
 *
 * Error Codes
 * 1.x - Sql Errors
 * 2.x - Launcher Errors
 * 3.x - Editor Errors
 * 4.x - Builder Errors
 * 5.x - Save Errors
 * 6.x - Edit Idea Name Errors
 *
 */

#include "MPLauncher.h"

MPLauncher::MPLauncher(void)
	:	BWindow(BRect(100, 100, 840, 400), "MasterPiece Launcher", B_TITLED_WINDOW,  B_NOT_H_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS, B_CURRENT_WORKSPACE)
{
	// mplauncher is the main window of the application

	// gui control initialization
	AddShortcut('m', 0, new BMessage(CREATE_NEW_MP));
	AddShortcut('t', 0, new BMessage(CREATE_NEW_THT));
	AddShortcut('d', 0, new BMessage(START_DELETE));
	mainGroup = new BGroupLayout(B_HORIZONTAL, 0.0);
	newThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Create a New...", new BMessage(CREATE_NEW_THT), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	newMasterpieceButton = new BButton(BRect(0, 10, 80, 35), NULL, "Create a New...", new BMessage(CREATE_NEW_MP), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	delThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Delete Selected...", new BMessage(DELETE_LAUNCHER_THT), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	delMasterpieceButton = new BButton(BRect(10, 10, 90, 35), NULL, "Delete Selected...", new BMessage(DELETE_MP), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	importThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Import Thought(s)...", new BMessage(IMPORT_THT), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	delThoughtButton->SetEnabled(false);
	delMasterpieceButton->SetEnabled(false);
	thoughtStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Work on a Thought");
	masterpieceStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Work on a Masterpiece");
	openMasterpieceStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Open an Existing...");
	openThoughtStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Open an Existing...");
	openThoughtListView = new BListView(BRect(10, 10, 100, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	importPanel = NULL;
	openMasterpieceListView = new BListView(BRect(10, 10, 100, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	backView = new BView(Bounds(), "backview", B_FOLLOW_ALL, B_WILL_DRAW);
	backView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	AddChild(backView);
	// layout builder code
	backView->SetLayout(mainGroup);
	backView->AddChild(BGridLayoutBuilder()
		.Add(masterpieceStringView, 0, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
		.Add(thoughtStringView, 2, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 3, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 4, 0, 2, 1)
		.Add(newMasterpieceButton, 0, 1)
		.Add(delMasterpieceButton, 1, 1)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
		.Add(newThoughtButton, 2, 1)
		.Add(delThoughtButton, 4, 1)
		.Add(importThoughtButton, 3, 1)
		.Add(openMasterpieceStringView, 0, 2)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 2)
		.Add(openThoughtStringView, 2, 2)
		.Add(BSpaceLayoutItem::CreateGlue(), 3, 2)
		.Add(new BScrollView("scroll_masterpiecelist", openMasterpieceListView,  B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 0, 3, 2, 3)
		.Add(new BScrollView("scroll_thoughtlist", openThoughtListView,  B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 2, 3, 3, 3)
		.SetInsets(5, 5, 5, 2)
	);
	PopulateLauncherListViews(); // populate listview's here
	openMasterpieceListView->SetSelectionMessage(new BMessage(SELECT_EXIST_MP)); // single click action
	openThoughtListView->SetSelectionMessage(new BMessage(SELECT_EXIST_THT)); // single click action
	openMasterpieceListView->SetInvocationMessage(new BMessage(OPEN_EXISTING_MP)); // double click action
	openThoughtListView->SetInvocationMessage(new BMessage(OPEN_EXISTING_THT)); // double click action
	newMasterpieceButton->MakeFocus(true);
}
void MPLauncher::MessageReceived(BMessage* msg)
{
	BEntry entry;
	BPath path;
	entry_ref ref;
	status_t err;

	switch(msg->what)
	{
		case CREATE_NEW_MP: // create new mp by opening mp builder
			mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Builder - untitled", -1);
			mpBuilder->Show();
			this->Hide();
			break;
		case CREATE_NEW_THT: // create new thought by opening thought editor
			mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
			mpEditor->Show();
			this->Hide();
			break;
		case OPEN_EXISTING_MP: // open existing mp by selecting from listview
			selected = openMasterpieceListView->CurrentSelection(); // list item value
			if(selected < 0) // if selected nothing, open empty builder window
			{
				mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Builder - untitled", -1);
				mpBuilder->Show();
				this->Hide();
			}
			else // you selected an actual existing mp from listview
			{
				IdeaStringItem* item;
				item = dynamic_cast<IdeaStringItem*>(openMasterpieceListView->ItemAt(selected));
				BString tmpText;
				tmpText = "MasterPiece Builder - ";
				tmpText += item->Text();
				mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), tmpText, item->ReturnID());
				mpBuilder->Show();
				this->Hide();
			}
			break;
		case OPEN_EXISTING_THT: // open existing thought by selecting from listview
			selected = openThoughtListView->CurrentSelection(); // list item value
			if(selected < 0) // if selected nothing, open empty builder window
			{
				mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
				mpEditor->Show();
				this->Hide();
			}
			else // you selected an actual existing thought from listview
			{
				IdeaStringItem* item;
				item = dynamic_cast<IdeaStringItem*>(openThoughtListView->ItemAt(selected));
				BString tmpText;
				tmpText = "MasterPiece Editor - ";
				tmpText += item->Text();
				mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), tmpText, item->ReturnID());
				mpEditor->Show();
				this->Hide();
			}
			break;
		case IMPORT_THT:
			if(!importPanel) importPanel = new BFilePanel(B_OPEN_PANEL, new BMessenger(this), NULL, B_FILE_NODE, false);
			importPanel->Show();
			break;
		case SELECT_EXIST_MP:
			if(openMasterpieceListView->CurrentSelection() >= 0)
			{
				openThoughtListView->DeselectAll();
				delMasterpieceButton->SetEnabled(true);
				delThoughtButton->SetEnabled(false);
			}
			else
			{
				delMasterpieceButton->SetEnabled(false);
			}
			break;
		case SELECT_EXIST_THT:
			if(openThoughtListView->CurrentSelection() >= 0)
			{
				openMasterpieceListView->DeselectAll();
				delThoughtButton->SetEnabled(true);
				delMasterpieceButton->SetEnabled(false);
			}
			else
			{
				delThoughtButton->SetEnabled(false);
			}
			break;
		case DELETE_LAUNCHER_THT:
			IdeaStringItem* item;
			item = dynamic_cast<IdeaStringItem*>(openThoughtListView->ItemAt(openThoughtListView->CurrentSelection()));
			sqlObject = new SqlObject(ideaStatement, "7"); // open sqldb
			sqlObject->PrepareSql("delete from ideatable where ideaid = ?"); // prepare sql
			sqlObject->BindValue(1, item->ReturnID());
			sqlObject->StepSql();
			sqlObject->FinalizeSql();
			sqlObject->CloseSql();
			delete sqlObject; // trying to free up memory where available
			PopulateLauncherListViews();
			break;
		case DELETE_MP:
			IdeaStringItem* mpitem;
			mpitem = dynamic_cast<IdeaStringItem*>(openMasterpieceListView->ItemAt(openMasterpieceListView->CurrentSelection()));
			sqlObject = new SqlObject(ideaStatement, "7"); // open sqldb
			sqlObject->PrepareSql("delete from ideatable where ideaid = ?"); // prepare sql
			sqlObject->BindValue(1, mpitem->ReturnID());
			sqlObject->StepSql();
			sqlObject->FinalizeSql();
			sqlObject->CloseSql();
			delete sqlObject; // trying to free up memory
			PopulateLauncherListViews();
			break;
		case SHOW_LAUNCHER:  // once finished with editor or builder, call to show this launcher
			if(msg->FindInt64("showLauncher", &showLauncher) == B_OK) // message was found
			{
				if(showLauncher == 1)
				{
					PopulateLauncherListViews(); // rerun the sql and repopulate the 2 listviews with any updated values
					if(this->IsHidden())
					{
						this->Show();
					}
				}
				else if(showLauncher == 0)
				{
					this->Hide();
				}
				else
				{
					eAlert = new ErrorAlert("2.1 Launcher Error: Illegal Value was returned.");
					eAlert->Launch();
					// big error must display
				}
			}
			else // message not found
			{
				eAlert = new ErrorAlert("2.2 Launcher Error: Message Variable was not found.");
				eAlert->Launch();
			}
			break;
		case B_REFS_RECEIVED:
			err = msg->FindRef("refs", 0, &ref);
			if(err == B_OK)
			{
				entry.SetTo(&ref, true);
				entry.GetRef(&ref);
				entry.GetPath(&path);
			}
			break;
		case START_DELETE:
			if(delThoughtButton->IsEnabled() == true)
			{
				PostMessage(DELETE_LAUNCHER_THT, this);
			}
			if(delMasterpieceButton->IsEnabled() == true)
			{
				PostMessage(DELETE_MP, this);
			}
			break;
		default:
		{
			BWindow::MessageReceived(msg);
			break;
		}
	}
}
	// import file into a string...  use a separator like <tht> to start a new tht.
	// take that string, use findlast to get int32, then use moveinto
	/*

	BFile file;
	// get info from import dialog
	BString contentPath = GetAppDirPath();
	contentPath += "/";
	contentPath += "filename";
	if(file.SetTo(contentPath, B_READ_ONLY) == B_OK)
	{
		off_t length;
		char* text;
		file.GetSize(&length);
		text = (char*) malloc(length);
		if(text && (file.Read(text, length)) >= B_OK)
		{
			insert into db "text" here...
		}
		free(text);
	}

	int32 IFindLast(const BString& string) const;
	BString astring("AbcAbcAbc");
	astring.FindLast("Abc", 7);

	BString& MoveInto(BString& destination, int32 sourceOffset, int32 charCount);
	BString source, destination;
	source.SetTo("abcdefg");
	source.MoveInto(&destination, 2, 3);
	 */
	/*
	// assuming multiple select is true then u can loop like that.
	ref_num = 0;
	do {
		if((err = msg->FindRef("refs", ref_num, &ref)) != B_OK)
			return;
		// call function to do sql insert for the ref value.
		// do sql insert stuff here for the ref.
		ref_num++;
	} while(1);
	*/
bool MPLauncher::QuitRequested(void)
{
	TmpCleanUp("tht");
	TmpCleanUp("html");
	be_app->PostMessage(B_QUIT_REQUESTED); // exit application
	return true;
}
void MPLauncher::PopulateLauncherListViews(void)
{
	openMasterpieceListView->MakeEmpty();
	openThoughtListView->MakeEmpty();
	sqlObject = new SqlObject(ideaStatement, "5"); // open sqldb
	sqlObject->PrepareSql("select ideaname, ideaid from ideatable where ismp = 1"); // prepare sql
	while(sqlObject->StepSql() == SQLITE_ROW) // step through the sql
	{
		openMasterpieceListView->AddItem(new IdeaStringItem(sqlObject->ReturnText(0), sqlObject->ReturnInt(1))); // populate listview
	}
	sqlObject->FinalizeSql(); // finalize sql
	sqlObject->CloseSql(); // close sql

	sqlObject = new SqlObject(ideaStatement, "6"); // open sqldb
	sqlObject->PrepareSql("select ideaname, ideaid from ideatable where ismp = 0"); // prepare sql
	while(sqlObject->StepSql() == SQLITE_ROW) // step through the sql
	{
		openThoughtListView->AddItem(new IdeaStringItem(sqlObject->ReturnText(0), sqlObject->ReturnInt(1))); // populate listview
	}
	sqlObject->FinalizeSql(); // finalize sql
	sqlObject->CloseSql(); // close sql
	delete sqlObject; // trying to free up memory
}
<commit_msg>working on import functionality<commit_after>/*
 *
 * Error Codes
 * 1.x - Sql Errors
 * 2.x - Launcher Errors
 * 3.x - Editor Errors
 * 4.x - Builder Errors
 * 5.x - Save Errors
 * 6.x - Edit Idea Name Errors
 *
 */

#include "MPLauncher.h"

MPLauncher::MPLauncher(void)
	:	BWindow(BRect(100, 100, 840, 400), "MasterPiece Launcher", B_TITLED_WINDOW,  B_NOT_H_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS, B_CURRENT_WORKSPACE)
{
	// mplauncher is the main window of the application

	// gui control initialization
	AddShortcut('m', 0, new BMessage(CREATE_NEW_MP));
	AddShortcut('t', 0, new BMessage(CREATE_NEW_THT));
	AddShortcut('d', 0, new BMessage(START_DELETE));
	mainGroup = new BGroupLayout(B_HORIZONTAL, 0.0);
	newThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Create a New...", new BMessage(CREATE_NEW_THT), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	newMasterpieceButton = new BButton(BRect(0, 10, 80, 35), NULL, "Create a New...", new BMessage(CREATE_NEW_MP), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	delThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Delete Selected...", new BMessage(DELETE_LAUNCHER_THT), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	delMasterpieceButton = new BButton(BRect(10, 10, 90, 35), NULL, "Delete Selected...", new BMessage(DELETE_MP), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	importThoughtButton = new BButton(BRect(10, 10, 90, 35), NULL, "Import Thought(s)...", new BMessage(IMPORT_THT), B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE);
	delThoughtButton->SetEnabled(false);
	delMasterpieceButton->SetEnabled(false);
	thoughtStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Work on a Thought");
	masterpieceStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Work on a Masterpiece");
	openMasterpieceStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Open an Existing...");
	openThoughtStringView = new BStringView(BRect(10, 10, 200, 30), NULL, "Open an Existing...");
	openThoughtListView = new BListView(BRect(10, 10, 100, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	importPanel = NULL;
	openMasterpieceListView = new BListView(BRect(10, 10, 100, 30), NULL, B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
	backView = new BView(Bounds(), "backview", B_FOLLOW_ALL, B_WILL_DRAW);
	backView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	AddChild(backView);
	// layout builder code
	backView->SetLayout(mainGroup);
	backView->AddChild(BGridLayoutBuilder()
		.Add(masterpieceStringView, 0, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
		.Add(thoughtStringView, 2, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 3, 0)
		.Add(BSpaceLayoutItem::CreateGlue(), 4, 0, 2, 1)
		.Add(newMasterpieceButton, 0, 1)
		.Add(delMasterpieceButton, 1, 1)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
		.Add(newThoughtButton, 2, 1)
		.Add(delThoughtButton, 4, 1)
		.Add(importThoughtButton, 3, 1)
		.Add(openMasterpieceStringView, 0, 2)
		.Add(BSpaceLayoutItem::CreateGlue(), 1, 2)
		.Add(openThoughtStringView, 2, 2)
		.Add(BSpaceLayoutItem::CreateGlue(), 3, 2)
		.Add(new BScrollView("scroll_masterpiecelist", openMasterpieceListView,  B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 0, 3, 2, 3)
		.Add(new BScrollView("scroll_thoughtlist", openThoughtListView,  B_FOLLOW_ALL_SIDES, 0, false, true, B_FANCY_BORDER), 2, 3, 3, 3)
		.SetInsets(5, 5, 5, 2)
	);
	PopulateLauncherListViews(); // populate listview's here
	openMasterpieceListView->SetSelectionMessage(new BMessage(SELECT_EXIST_MP)); // single click action
	openThoughtListView->SetSelectionMessage(new BMessage(SELECT_EXIST_THT)); // single click action
	openMasterpieceListView->SetInvocationMessage(new BMessage(OPEN_EXISTING_MP)); // double click action
	openThoughtListView->SetInvocationMessage(new BMessage(OPEN_EXISTING_THT)); // double click action
	newMasterpieceButton->MakeFocus(true);
}
void MPLauncher::MessageReceived(BMessage* msg)
{
	BEntry entry;
	BPath path;
	BFile file;
	entry_ref ref;
	status_t err;

	switch(msg->what)
	{
		case CREATE_NEW_MP: // create new mp by opening mp builder
			mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Builder - untitled", -1);
			mpBuilder->Show();
			this->Hide();
			break;
		case CREATE_NEW_THT: // create new thought by opening thought editor
			mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
			mpEditor->Show();
			this->Hide();
			break;
		case OPEN_EXISTING_MP: // open existing mp by selecting from listview
			selected = openMasterpieceListView->CurrentSelection(); // list item value
			if(selected < 0) // if selected nothing, open empty builder window
			{
				mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Builder - untitled", -1);
				mpBuilder->Show();
				this->Hide();
			}
			else // you selected an actual existing mp from listview
			{
				IdeaStringItem* item;
				item = dynamic_cast<IdeaStringItem*>(openMasterpieceListView->ItemAt(selected));
				BString tmpText;
				tmpText = "MasterPiece Builder - ";
				tmpText += item->Text();
				mpBuilder = new MPBuilder(BMessage(SHOW_LAUNCHER), BMessenger(this), tmpText, item->ReturnID());
				mpBuilder->Show();
				this->Hide();
			}
			break;
		case OPEN_EXISTING_THT: // open existing thought by selecting from listview
			selected = openThoughtListView->CurrentSelection(); // list item value
			if(selected < 0) // if selected nothing, open empty builder window
			{
				mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), "MasterPiece Editor - untitled", -1);
				mpEditor->Show();
				this->Hide();
			}
			else // you selected an actual existing thought from listview
			{
				IdeaStringItem* item;
				item = dynamic_cast<IdeaStringItem*>(openThoughtListView->ItemAt(selected));
				BString tmpText;
				tmpText = "MasterPiece Editor - ";
				tmpText += item->Text();
				mpEditor = new MPEditor(BMessage(SHOW_LAUNCHER), BMessenger(this), tmpText, item->ReturnID());
				mpEditor->Show();
				this->Hide();
			}
			break;
		case IMPORT_THT:
			if(!importPanel) importPanel = new BFilePanel(B_OPEN_PANEL, new BMessenger(this), NULL, B_FILE_NODE, false);
			importPanel->Show();
			break;
		case SELECT_EXIST_MP:
			if(openMasterpieceListView->CurrentSelection() >= 0)
			{
				openThoughtListView->DeselectAll();
				delMasterpieceButton->SetEnabled(true);
				delThoughtButton->SetEnabled(false);
			}
			else
			{
				delMasterpieceButton->SetEnabled(false);
			}
			break;
		case SELECT_EXIST_THT:
			if(openThoughtListView->CurrentSelection() >= 0)
			{
				openMasterpieceListView->DeselectAll();
				delThoughtButton->SetEnabled(true);
				delMasterpieceButton->SetEnabled(false);
			}
			else
			{
				delThoughtButton->SetEnabled(false);
			}
			break;
		case DELETE_LAUNCHER_THT:
			IdeaStringItem* item;
			item = dynamic_cast<IdeaStringItem*>(openThoughtListView->ItemAt(openThoughtListView->CurrentSelection()));
			sqlObject = new SqlObject(ideaStatement, "7"); // open sqldb
			sqlObject->PrepareSql("delete from ideatable where ideaid = ?"); // prepare sql
			sqlObject->BindValue(1, item->ReturnID());
			sqlObject->StepSql();
			sqlObject->FinalizeSql();
			sqlObject->CloseSql();
			delete sqlObject; // trying to free up memory where available
			PopulateLauncherListViews();
			break;
		case DELETE_MP:
			IdeaStringItem* mpitem;
			mpitem = dynamic_cast<IdeaStringItem*>(openMasterpieceListView->ItemAt(openMasterpieceListView->CurrentSelection()));
			sqlObject = new SqlObject(ideaStatement, "7"); // open sqldb
			sqlObject->PrepareSql("delete from ideatable where ideaid = ?"); // prepare sql
			sqlObject->BindValue(1, mpitem->ReturnID());
			sqlObject->StepSql();
			sqlObject->FinalizeSql();
			sqlObject->CloseSql();
			delete sqlObject; // trying to free up memory
			PopulateLauncherListViews();
			break;
		case SHOW_LAUNCHER:  // once finished with editor or builder, call to show this launcher
			if(msg->FindInt64("showLauncher", &showLauncher) == B_OK) // message was found
			{
				if(showLauncher == 1)
				{
					PopulateLauncherListViews(); // rerun the sql and repopulate the 2 listviews with any updated values
					if(this->IsHidden())
					{
						this->Show();
					}
				}
				else if(showLauncher == 0)
				{
					this->Hide();
				}
				else
				{
					eAlert = new ErrorAlert("2.1 Launcher Error: Illegal Value was returned.");
					eAlert->Launch();
					// big error must display
				}
			}
			else // message not found
			{
				eAlert = new ErrorAlert("2.2 Launcher Error: Message Variable was not found.");
				eAlert->Launch();
			}
			break;
		case B_REFS_RECEIVED:
			err = msg->FindRef("refs", 0, &ref);
			if(err == B_OK)
			{
				entry.SetTo(&ref, true);
				entry.GetRef(&ref);
				entry.GetPath(&path);
				if(file.SetTo(path.Path(), B_READ_ONLY) == B_OK)
				{
					off_t length;
					char* text;
					file.GetSize(&length);
					text = (char*) malloc length;
					if(text && (file.Read(text, length)) >= B_OK)
					{
						// save it to a string and loop for thoughts or
						// force it to save as 1 thought only
						// save it to a single thought
						// insert into db text here...
					}
				}
			}
			break;
		case START_DELETE:
			if(delThoughtButton->IsEnabled() == true)
			{
				PostMessage(DELETE_LAUNCHER_THT, this);
			}
			if(delMasterpieceButton->IsEnabled() == true)
			{
				PostMessage(DELETE_MP, this);
			}
			break;
		default:
		{
			BWindow::MessageReceived(msg);
			break;
		}
	}
}
	// import file into a string...  use a separator like <tht> to start a new tht.
	// take that string, use findlast to get int32, then use moveinto
	/*

	BFile file;
	// get info from import dialog
	BString contentPath = GetAppDirPath();
	contentPath += "/";
	contentPath += "filename";
	if(file.SetTo(contentPath, B_READ_ONLY) == B_OK)
	{
		off_t length;
		char* text;
		file.GetSize(&length);
		text = (char*) malloc(length);
		if(text && (file.Read(text, length)) >= B_OK)
		{
			insert into db "text" here...
		}
		free(text);
	}

	int32 IFindLast(const BString& string) const;
	BString astring("AbcAbcAbc");
	astring.FindLast("Abc", 7);

	BString& MoveInto(BString& destination, int32 sourceOffset, int32 charCount);
	BString source, destination;
	source.SetTo("abcdefg");
	source.MoveInto(&destination, 2, 3);
	 */
	/*
	// assuming multiple select is true then u can loop like that.
	ref_num = 0;
	do {
		if((err = msg->FindRef("refs", ref_num, &ref)) != B_OK)
			return;
		// call function to do sql insert for the ref value.
		// do sql insert stuff here for the ref.
		ref_num++;
	} while(1);
	*/
bool MPLauncher::QuitRequested(void)
{
	TmpCleanUp("tht");
	TmpCleanUp("html");
	be_app->PostMessage(B_QUIT_REQUESTED); // exit application
	return true;
}
void MPLauncher::PopulateLauncherListViews(void)
{
	openMasterpieceListView->MakeEmpty();
	openThoughtListView->MakeEmpty();
	sqlObject = new SqlObject(ideaStatement, "5"); // open sqldb
	sqlObject->PrepareSql("select ideaname, ideaid from ideatable where ismp = 1"); // prepare sql
	while(sqlObject->StepSql() == SQLITE_ROW) // step through the sql
	{
		openMasterpieceListView->AddItem(new IdeaStringItem(sqlObject->ReturnText(0), sqlObject->ReturnInt(1))); // populate listview
	}
	sqlObject->FinalizeSql(); // finalize sql
	sqlObject->CloseSql(); // close sql

	sqlObject = new SqlObject(ideaStatement, "6"); // open sqldb
	sqlObject->PrepareSql("select ideaname, ideaid from ideatable where ismp = 0"); // prepare sql
	while(sqlObject->StepSql() == SQLITE_ROW) // step through the sql
	{
		openThoughtListView->AddItem(new IdeaStringItem(sqlObject->ReturnText(0), sqlObject->ReturnInt(1))); // populate listview
	}
	sqlObject->FinalizeSql(); // finalize sql
	sqlObject->CloseSql(); // close sql
	delete sqlObject; // trying to free up memory
}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include "MarbleTest.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QTime>
#include <QtGui/QFileDialog>

#include <lib/global.h>
#include <lib/MarbleWidget.h>
#include <lib/MarbleModel.h>

MarbleTest::MarbleTest( MarbleWidget* marbleWidget )
    : m_marbleWidget(marbleWidget)
{
}

void MarbleTest::timeDemo()
{
    m_marbleWidget->zoomView( 1500 );
    m_marbleWidget->setMapThemeId( "earth/srtm/srtm.dgml" );
    m_marbleWidget->setMapQuality( Marble::Normal );
//    m_marbleWidget->resize( 800, 600 );
    m_marbleWidget->centerOn( 9.4, 54.8 );
    QTime t;
    //m_marbleWidget->setMapTheme( "plain/plain.dgml" );
    //m_marbleWidget->setMapTheme( "bluemarble/bluemarble.dgml" );

/*
    m_marbleWidget->setShowGrid( false );
    m_marbleWidget->setShowPlaces( false );
    m_marbleWidget->setShowBorders( false );
    m_marbleWidget->setShowRivers( false );
    m_marbleWidget->setShowLakes( false );
*/

        for ( int k = 0; k < 10; ++k ) {
            m_marbleWidget->moveRight();
            QCoreApplication::flush();
        }
        for ( int k = 0; k < 10; ++k ) {
            m_marbleWidget->moveLeft();
            QCoreApplication::flush();
        }

    qDebug() << "Starting Performance Test";

    t.start();

    for ( int j = 0; j < 10; ++j ) {
        for ( int k = 0; k < 10; ++k ) {
            m_marbleWidget->moveRight();
            QCoreApplication::flush();
        }
        for ( int k = 0; k < 10; ++k ) {
            m_marbleWidget->moveLeft();
            QCoreApplication::flush();
        }
    }

    qDebug( "Timedemo finished in %ims", t.elapsed() );
    qDebug() <<  QString("= %1 fps").arg(200*1000/(double)(t.elapsed()));

}

void MarbleTest::gpsDemo(){
    //
    //set up for the test
    //
    qDebug("stopping polling now");

    m_marbleWidget->model()->stopPolling();
    m_marbleWidget->centerOn( -15.2325, 58.3723 );

    m_marbleWidget->setShowGps( true );

    //get the gpx file
    QString fileName = QFileDialog::getOpenFileName(m_marbleWidget,
            "Open File", QString(),
            "GPS Data (*.gpx);;KML (*.kml)");

    if ( ! fileName.isNull() ) {
        QString extension = fileName.section( '.', -1 );

        if ( extension.compare( "gpx", Qt::CaseInsensitive ) == 0 ) {
            m_marbleWidget->openGpxFile( fileName );
        }
    }

    QTime t;
    QTime totalTime;

    QVector<int> movingStats;
    QVector<int> staticStats;
    int temp=0;
    int totalMoving =0;
    int totalStatic =0;

    //
    //Start the test
    //
    totalTime.start();
    for( int i = 0; i< 5 ; i++) {

        m_marbleWidget->zoomViewBy( 400 );
        totalMoving =0;
        totalStatic =0;
        m_marbleWidget->centerOn( -15.2325, 58.3723 );

        for( int i = 0; i< 5 ;i++ ){
            if( i%2) {
                m_marbleWidget->moveLeft();
            } else {
                m_marbleWidget->moveRight();
            }
            t.start();
            m_marbleWidget->updateGps();
            temp = t.elapsed();
//             qDebug("time elapsed moving %d",temp);
            totalMoving += temp;

        }

        for( int i = 0; i< 10 ;i++ ){
            t.start();
            m_marbleWidget->updateGps();
            temp=t.elapsed();
//             qDebug("time elapsed static %d",t.elapsed());
            totalStatic+=temp;
        }

//         qDebug ( "average of moving is %d at %d zoom",
//                  (totalMoving/10), m_marbleWidget->zoom() );
//         qDebug( "average of static is %d at %d zoom",
//                 (totalStatic/10) , m_marbleWidget->zoom() );
        movingStats.append( totalMoving/10 );
        staticStats.append( totalStatic/10 );

    }
    qDebug("total test time: %d", totalTime.elapsed());

    qDebug("full moving stats: ") ;
    qDebug() << movingStats;

    qDebug("full static stats: ");
    qDebug() << staticStats;

}
<commit_msg>- Reenabling Marble test<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include "MarbleTest.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QTime>
#include <QtGui/QMessageBox>
#include <QtGui/QFileDialog>

#include <lib/global.h>
#include <lib/MarbleWidget.h>
#include <lib/MarbleModel.h>

MarbleTest::MarbleTest( MarbleWidget* marbleWidget )
    : m_marbleWidget(marbleWidget)
{
}

void MarbleTest::timeDemo()
{
    m_marbleWidget->zoomView( 1500 );
    m_marbleWidget->setMapThemeId( "earth/srtm/srtm.dgml" );
    m_marbleWidget->setMapQuality( Marble::Normal );
//    m_marbleWidget->resize( 800, 600 );
    m_marbleWidget->centerOn( 9.4, 54.8 );

    QMessageBox::information(m_marbleWidget, QString( "Marble Speed Test" ), QString( "Press Ok to start test" ) );

    QTime t;
    //m_marbleWidget->setMapTheme( "plain/plain.dgml" );
    //m_marbleWidget->setMapTheme( "bluemarble/bluemarble.dgml" );

/*
    m_marbleWidget->setShowGrid( false );
    m_marbleWidget->setShowPlaces( false );
    m_marbleWidget->setShowBorders( false );
    m_marbleWidget->setShowRivers( false );
    m_marbleWidget->setShowLakes( false );
*/

        for ( int k = 0; k < 10; ++k ) {
            m_marbleWidget->moveRight();
            QCoreApplication::flush();
        }
        for ( int k = 0; k < 10; ++k ) {
            m_marbleWidget->moveLeft();
            QCoreApplication::flush();
        }

    qDebug() << "Starting Performance Test";

    t.start();

    for ( int j = 0; j < 10; ++j ) {
        for ( int k = 0; k < 10; ++k ) {
            m_marbleWidget->moveRight();
            QCoreApplication::flush();
        }
        for ( int k = 0; k < 10; ++k ) {
            m_marbleWidget->moveLeft();
            QCoreApplication::flush();
        }
    }

    qDebug( "Timedemo finished in %ims", t.elapsed() );
    qDebug() <<  QString("= %1 fps").arg(200*1000/(double)(t.elapsed()));

}

void MarbleTest::gpsDemo(){
    //
    //set up for the test
    //
    qDebug("stopping polling now");

    m_marbleWidget->model()->stopPolling();
    m_marbleWidget->centerOn( -15.2325, 58.3723 );

    m_marbleWidget->setShowGps( true );

    //get the gpx file
    QString fileName = QFileDialog::getOpenFileName(m_marbleWidget,
            "Open File", QString(),
            "GPS Data (*.gpx);;KML (*.kml)");

    if ( ! fileName.isNull() ) {
        QString extension = fileName.section( '.', -1 );

        if ( extension.compare( "gpx", Qt::CaseInsensitive ) == 0 ) {
            m_marbleWidget->openGpxFile( fileName );
        }
    }

    QTime t;
    QTime totalTime;

    QVector<int> movingStats;
    QVector<int> staticStats;
    int temp=0;
    int totalMoving =0;
    int totalStatic =0;

    //
    //Start the test
    //
    totalTime.start();
    for( int i = 0; i< 5 ; i++) {

        m_marbleWidget->zoomViewBy( 400 );
        totalMoving =0;
        totalStatic =0;
        m_marbleWidget->centerOn( -15.2325, 58.3723 );

        for( int i = 0; i< 5 ;i++ ){
            if( i%2) {
                m_marbleWidget->moveLeft();
            } else {
                m_marbleWidget->moveRight();
            }
            t.start();
            m_marbleWidget->updateGps();
            temp = t.elapsed();
//             qDebug("time elapsed moving %d",temp);
            totalMoving += temp;

        }

        for( int i = 0; i< 10 ;i++ ){
            t.start();
            m_marbleWidget->updateGps();
            temp=t.elapsed();
//             qDebug("time elapsed static %d",t.elapsed());
            totalStatic+=temp;
        }

//         qDebug ( "average of moving is %d at %d zoom",
//                  (totalMoving/10), m_marbleWidget->zoom() );
//         qDebug( "average of static is %d at %d zoom",
//                 (totalStatic/10) , m_marbleWidget->zoom() );
        movingStats.append( totalMoving/10 );
        staticStats.append( totalStatic/10 );

    }
    qDebug("total test time: %d", totalTime.elapsed());

    qDebug("full moving stats: ") ;
    qDebug() << movingStats;

    qDebug("full static stats: ");
    qDebug() << staticStats;

}
<|endoftext|>


<commit_before>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/StaticMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/BoundingBox>
#include <osg/CopyOp>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/KdTree>
#include <osg/Object>
#include <osg/Shape>
#include <osg/Vec3>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

TYPE_NAME_ALIAS(std::multiset< osg::KdTree::LineSegmentIntersection >, osg::KdTree::LineSegmentIntersections)

TYPE_NAME_ALIAS(int, osg::KdTree::value_type)

TYPE_NAME_ALIAS(std::vector< osg::KdTree::value_type >, osg::KdTree::Indices)

TYPE_NAME_ALIAS(std::vector< unsigned int >, osg::KdTree::AxisStack)

TYPE_NAME_ALIAS(std::vector< osg::KdTree::KdNode >, osg::KdTree::KdNodeList)

TYPE_NAME_ALIAS(std::vector< osg::KdTree::KdLeaf >, osg::KdTree::KdLeafList)

TYPE_NAME_ALIAS(std::vector< osg::BoundingBox >, osg::KdTree::BoundingBoxList)

TYPE_NAME_ALIAS(std::vector< osg::KdTree::Triangle >, osg::KdTree::TriangleList)

TYPE_NAME_ALIAS(std::vector< osg::Vec3 >, osg::KdTree::CenterList)

BEGIN_OBJECT_REFLECTOR(osg::KdTree)
	I_DeclaringFile("osg/KdTree");
	I_BaseType(osg::Shape);
	I_Constructor0(____KdTree,
	               "",
	               "");
	I_ConstructorWithDefaults2(IN, const osg::KdTree &, rhs, , IN, const osg::CopyOp &, copyop, osg::CopyOp::SHALLOW_COPY,
	                           ____KdTree__C5_KdTree_R1__C5_osg_CopyOp_R1,
	                           "",
	                           "");
	I_Method0(osg::Object *, cloneType,
	          Properties::VIRTUAL,
	          __osg_Object_P1__cloneType,
	          "Clone the type of an attribute, with Object* return type. ",
	          "Must be defined by derived classes. ");
	I_Method1(osg::Object *, clone, IN, const osg::CopyOp &, copyop,
	          Properties::VIRTUAL,
	          __osg_Object_P1__clone__C5_osg_CopyOp_R1,
	          "Clone an attribute, with Object* return type. ",
	          "Must be defined by derived classes. ");
	I_Method1(bool, isSameKindAs, IN, const osg::Object *, obj,
	          Properties::VIRTUAL,
	          __bool__isSameKindAs__C5_osg_Object_P1,
	          "return true if this and obj are of the same kind of object. ",
	          "");
	I_Method0(const char *, libraryName,
	          Properties::VIRTUAL,
	          __C5_char_P1__libraryName,
	          "return the name of the attribute's library. ",
	          "");
	I_Method0(const char *, className,
	          Properties::VIRTUAL,
	          __C5_char_P1__className,
	          "return the name of the attribute's class type. ",
	          "");
	I_Method1(void, accept, IN, osg::ShapeVisitor &, sv,
	          Properties::VIRTUAL,
	          __void__accept__osg_ShapeVisitor_R1,
	          "accept a non const shape visitor which can be used on non const shape objects. ",
	          "Must be defined by derived classes. ");
	I_Method1(void, accept, IN, osg::ConstShapeVisitor &, csv,
	          Properties::VIRTUAL,
	          __void__accept__osg_ConstShapeVisitor_R1,
	          "accept a const shape visitor which can be used on const shape objects. ",
	          "Must be defined by derived classes. ");
	I_Method2(bool, build, IN, osg::KdTree::BuildOptions &, buildOptions, IN, osg::Geometry *, geometry,
	          Properties::VIRTUAL,
	          __bool__build__BuildOptions_R1__osg_Geometry_P1,
	          "Build the kdtree from the specified source geometry object. ",
	          "retun true on success. ");
	I_Method3(bool, intersect, IN, const osg::Vec3 &, start, IN, const osg::Vec3 &, end, IN, osg::KdTree::LineSegmentIntersections &, intersections,
	          Properties::VIRTUAL,
	          __bool__intersect__C5_osg_Vec3_R1__C5_osg_Vec3_R1__LineSegmentIntersections_R1,
	          "compute the intersection of a line segment and the kdtree, return true if an intersection has been found. ",
	          "");
	I_Method1(int, addLeaf, IN, const osg::KdTree::KdLeaf &, leaf,
	          Properties::NON_VIRTUAL,
	          __int__addLeaf__C5_KdLeaf_R1,
	          "note, leafNum is negative to distinguish from nodeNum ",
	          "");
	I_Method2(int, replaceLeaf, IN, int, leafNum, IN, const osg::KdTree::KdLeaf &, leaf,
	          Properties::NON_VIRTUAL,
	          __int__replaceLeaf__int__C5_KdLeaf_R1,
	          "",
	          "");
	I_Method1(osg::KdTree::KdLeaf &, getLeaf, IN, int, leafNum,
	          Properties::NON_VIRTUAL,
	          __KdLeaf_R1__getLeaf__int,
	          "note, leafNum is negative to distinguish from nodeNum ",
	          "");
	I_Method1(int, addNode, IN, const osg::KdTree::KdNode &, node,
	          Properties::NON_VIRTUAL,
	          __int__addNode__C5_KdNode_R1,
	          "",
	          "");
	I_Method1(osg::KdTree::KdNode &, getNode, IN, int, nodeNum,
	          Properties::NON_VIRTUAL,
	          __KdNode_R1__getNode__int,
	          "note, nodeNum is positive to distinguish from leftNum ",
	          "");
	I_Method1(osg::BoundingBox &, getBounindingBox, IN, int, nodeNum,
	          Properties::NON_VIRTUAL,
	          __osg_BoundingBox_R1__getBounindingBox__int,
	          "",
	          "");
	I_Method1(void, computeDivisions, IN, osg::KdTree::BuildOptions &, options,
	          Properties::NON_VIRTUAL,
	          __void__computeDivisions__BuildOptions_R1,
	          "",
	          "");
	I_Method4(int, divide, IN, osg::KdTree::BuildOptions &, options, IN, osg::BoundingBox &, bb, IN, int, nodeIndex, IN, unsigned int, level,
	          Properties::NON_VIRTUAL,
	          __int__divide__BuildOptions_R1__osg_BoundingBox_R1__int__unsigned_int,
	          "",
	          "");
	I_Method4(bool, intersect, IN, const osg::KdTree::KdLeaf &, leaf, IN, const osg::Vec3 &, start, IN, const osg::Vec3 &, end, IN, osg::KdTree::LineSegmentIntersections &, intersections,
	          Properties::NON_VIRTUAL,
	          __bool__intersect__C5_KdLeaf_R1__C5_osg_Vec3_R1__C5_osg_Vec3_R1__LineSegmentIntersections_R1,
	          "",
	          "");
	I_PublicMemberProperty(osg::observer_ptr< osg::Geometry >, _geometry);
	I_PublicMemberProperty(osg::BoundingBox, _bb);
	I_PublicMemberProperty(osg::KdTree::AxisStack, _axisStack);
	I_PublicMemberProperty(osg::KdTree::KdNodeList, _kdNodes);
	I_PublicMemberProperty(osg::KdTree::KdLeafList, _kdLeaves);
	I_PublicMemberProperty(osg::ref_ptr< osg::Vec3Array >, _vertices);
	I_PublicMemberProperty(osg::KdTree::Indices, _primitiveIndices);
	I_PublicMemberProperty(osg::KdTree::BoundingBoxList, _boundingBoxes);
	I_PublicMemberProperty(osg::KdTree::TriangleList, _triangles);
	I_PublicMemberProperty(osg::KdTree::CenterList, _centers);
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::KdTree::BuildOptions)
	I_DeclaringFile("osg/KdTree");
	I_Constructor0(____BuildOptions,
	               "",
	               "");
	I_PublicMemberProperty(int, _numVerticesProcessed);
	I_PublicMemberProperty(int, _targetNumTrianglesPerLeaf);
	I_PublicMemberProperty(int, _maxNumLevels);
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::KdTree::KdLeaf)
	I_DeclaringFile("osg/KdTree");
	I_Constructor0(____KdLeaf,
	               "",
	               "");
	I_Constructor2(IN, osg::KdTree::value_type, f, IN, osg::KdTree::value_type, s,
	               ____KdLeaf__value_type__value_type,
	               "",
	               "");
	I_PublicMemberProperty(osg::KdTree::value_type, first);
	I_PublicMemberProperty(osg::KdTree::value_type, second);
	I_PublicMemberProperty(osg::BoundingBox, bb);
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::KdTree::KdNode)
	I_DeclaringFile("osg/KdTree");
	I_Constructor0(____KdNode,
	               "",
	               "");
	I_Constructor2(IN, osg::KdTree::value_type, f, IN, osg::KdTree::value_type, s,
	               ____KdNode__value_type__value_type,
	               "",
	               "");
	I_PublicMemberProperty(osg::KdTree::value_type, first);
	I_PublicMemberProperty(osg::KdTree::value_type, second);
	I_PublicMemberProperty(osg::BoundingBox, bb);
END_REFLECTOR

TYPE_NAME_ALIAS(std::vector< unsigned int >, osg::KdTree::LineSegmentIntersection::IndexList)

TYPE_NAME_ALIAS(std::vector< double >, osg::KdTree::LineSegmentIntersection::RatioList)

BEGIN_VALUE_REFLECTOR(osg::KdTree::LineSegmentIntersection)
	I_DeclaringFile("osg/KdTree");
	I_Constructor0(____LineSegmentIntersection,
	               "",
	               "");
	I_PublicMemberProperty(double, ratio);
	I_PublicMemberProperty(osg::Vec3d, intersectionPoint);
	I_PublicMemberProperty(osg::Vec3, intersectionNormal);
	I_PublicMemberProperty(osg::KdTree::LineSegmentIntersection::IndexList, indexList);
	I_PublicMemberProperty(osg::KdTree::LineSegmentIntersection::RatioList, ratioList);
	I_PublicMemberProperty(unsigned int, primitiveIndex);
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::KdTree::Triangle)
	I_DeclaringFile("osg/KdTree");
	I_Constructor3(IN, unsigned int, p1, IN, unsigned int, p2, IN, unsigned int, p3,
	               ____Triangle__unsigned_int__unsigned_int__unsigned_int,
	               "",
	               "");
	I_PublicMemberProperty(unsigned int, _p1);
	I_PublicMemberProperty(unsigned int, _p2);
	I_PublicMemberProperty(unsigned int, _p3);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::KdTreeBuilder)
	I_DeclaringFile("osg/KdTree");
	I_BaseType(osg::NodeVisitor);
	I_Constructor0(____KdTreeBuilder,
	               "",
	               "");
	I_Constructor1(IN, const osg::KdTreeBuilder &, rhs,
	               Properties::NON_EXPLICIT,
	               ____KdTreeBuilder__C5_KdTreeBuilder_R1,
	               "",
	               "");
	I_Method0(osg::KdTreeBuilder *, clone,
	          Properties::VIRTUAL,
	          __KdTreeBuilder_P1__clone,
	          "",
	          "");
	I_Method1(void, apply, IN, osg::Geode &, geode,
	          Properties::VIRTUAL,
	          __void__apply__osg_Geode_R1,
	          "",
	          "");
	I_PublicMemberProperty(osg::KdTree::BuildOptions, _buildOptions);
	I_PublicMemberProperty(osg::ref_ptr< osg::KdTree >, _kdTreePrototype);
END_REFLECTOR

STD_SET_REFLECTOR(std::multiset< osg::KdTree::LineSegmentIntersection >)

STD_VECTOR_REFLECTOR(std::vector< double >)

STD_VECTOR_REFLECTOR(std::vector< osg::BoundingBox >)

STD_VECTOR_REFLECTOR(std::vector< osg::KdTree::KdLeaf >)

STD_VECTOR_REFLECTOR(std::vector< osg::KdTree::KdNode >)

STD_VECTOR_REFLECTOR(std::vector< osg::KdTree::Triangle >)

STD_VECTOR_REFLECTOR(std::vector< osg::KdTree::value_type >)

<commit_msg>Updated wrappers<commit_after>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/StaticMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/BoundingBox>
#include <osg/CopyOp>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/KdTree>
#include <osg/Object>
#include <osg/Shape>
#include <osg/Vec3>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

TYPE_NAME_ALIAS(std::multiset< osg::KdTree::LineSegmentIntersection >, osg::KdTree::LineSegmentIntersections)

TYPE_NAME_ALIAS(int, osg::KdTree::value_type)

TYPE_NAME_ALIAS(std::vector< osg::KdTree::value_type >, osg::KdTree::Indices)

TYPE_NAME_ALIAS(std::vector< unsigned int >, osg::KdTree::AxisStack)

TYPE_NAME_ALIAS(std::vector< osg::KdTree::KdNode >, osg::KdTree::KdNodeList)

TYPE_NAME_ALIAS(std::vector< osg::KdTree::KdLeaf >, osg::KdTree::KdLeafList)

TYPE_NAME_ALIAS(std::vector< osg::BoundingBox >, osg::KdTree::BoundingBoxList)

TYPE_NAME_ALIAS(std::vector< osg::KdTree::Triangle >, osg::KdTree::TriangleList)

TYPE_NAME_ALIAS(std::vector< osg::Vec3 >, osg::KdTree::CenterList)

BEGIN_OBJECT_REFLECTOR(osg::KdTree)
	I_DeclaringFile("osg/KdTree");
	I_BaseType(osg::Shape);
	I_Constructor0(____KdTree,
	               "",
	               "");
	I_ConstructorWithDefaults2(IN, const osg::KdTree &, rhs, , IN, const osg::CopyOp &, copyop, osg::CopyOp::SHALLOW_COPY,
	                           ____KdTree__C5_KdTree_R1__C5_osg_CopyOp_R1,
	                           "",
	                           "");
	I_Method0(osg::Object *, cloneType,
	          Properties::VIRTUAL,
	          __osg_Object_P1__cloneType,
	          "Clone the type of an attribute, with Object* return type. ",
	          "Must be defined by derived classes. ");
	I_Method1(osg::Object *, clone, IN, const osg::CopyOp &, copyop,
	          Properties::VIRTUAL,
	          __osg_Object_P1__clone__C5_osg_CopyOp_R1,
	          "Clone an attribute, with Object* return type. ",
	          "Must be defined by derived classes. ");
	I_Method1(bool, isSameKindAs, IN, const osg::Object *, obj,
	          Properties::VIRTUAL,
	          __bool__isSameKindAs__C5_osg_Object_P1,
	          "return true if this and obj are of the same kind of object. ",
	          "");
	I_Method0(const char *, libraryName,
	          Properties::VIRTUAL,
	          __C5_char_P1__libraryName,
	          "return the name of the attribute's library. ",
	          "");
	I_Method0(const char *, className,
	          Properties::VIRTUAL,
	          __C5_char_P1__className,
	          "return the name of the attribute's class type. ",
	          "");
	I_Method1(void, accept, IN, osg::ShapeVisitor &, sv,
	          Properties::VIRTUAL,
	          __void__accept__osg_ShapeVisitor_R1,
	          "accept a non const shape visitor which can be used on non const shape objects. ",
	          "Must be defined by derived classes. ");
	I_Method1(void, accept, IN, osg::ConstShapeVisitor &, csv,
	          Properties::VIRTUAL,
	          __void__accept__osg_ConstShapeVisitor_R1,
	          "accept a const shape visitor which can be used on const shape objects. ",
	          "Must be defined by derived classes. ");
	I_Method2(bool, build, IN, osg::KdTree::BuildOptions &, buildOptions, IN, osg::Geometry *, geometry,
	          Properties::VIRTUAL,
	          __bool__build__BuildOptions_R1__osg_Geometry_P1,
	          "Build the kdtree from the specified source geometry object. ",
	          "retun true on success. ");
	I_Method3(bool, intersect, IN, const osg::Vec3 &, start, IN, const osg::Vec3 &, end, IN, osg::KdTree::LineSegmentIntersections &, intersections,
	          Properties::VIRTUAL,
	          __bool__intersect__C5_osg_Vec3_R1__C5_osg_Vec3_R1__LineSegmentIntersections_R1,
	          "compute the intersection of a line segment and the kdtree, return true if an intersection has been found. ",
	          "");
	I_Method1(int, addLeaf, IN, const osg::KdTree::KdLeaf &, leaf,
	          Properties::NON_VIRTUAL,
	          __int__addLeaf__C5_KdLeaf_R1,
	          "note, leafNum is negative to distinguish from nodeNum ",
	          "");
	I_Method2(int, replaceLeaf, IN, int, leafNum, IN, const osg::KdTree::KdLeaf &, leaf,
	          Properties::NON_VIRTUAL,
	          __int__replaceLeaf__int__C5_KdLeaf_R1,
	          "",
	          "");
	I_Method1(osg::KdTree::KdLeaf &, getLeaf, IN, int, leafNum,
	          Properties::NON_VIRTUAL,
	          __KdLeaf_R1__getLeaf__int,
	          "note, leafNum is negative to distinguish from nodeNum ",
	          "");
	I_Method1(const osg::KdTree::KdLeaf &, getLeaf, IN, int, leafNum,
	          Properties::NON_VIRTUAL,
	          __C5_KdLeaf_R1__getLeaf__int,
	          "",
	          "");
	I_Method1(int, addNode, IN, const osg::KdTree::KdNode &, node,
	          Properties::NON_VIRTUAL,
	          __int__addNode__C5_KdNode_R1,
	          "",
	          "");
	I_Method1(osg::KdTree::KdNode &, getNode, IN, int, nodeNum,
	          Properties::NON_VIRTUAL,
	          __KdNode_R1__getNode__int,
	          "note, nodeNum is positive to distinguish from leftNum ",
	          "");
	I_Method1(const osg::KdTree::KdNode &, getNode, IN, int, nodeNum,
	          Properties::NON_VIRTUAL,
	          __C5_KdNode_R1__getNode__int,
	          "note, nodeNum is positive to distinguish from leftNum ",
	          "");
	I_Method1(osg::BoundingBox &, getBoundingBox, IN, int, nodeNum,
	          Properties::NON_VIRTUAL,
	          __osg_BoundingBox_R1__getBoundingBox__int,
	          "",
	          "");
	I_Method1(void, computeDivisions, IN, osg::KdTree::BuildOptions &, options,
	          Properties::NON_VIRTUAL,
	          __void__computeDivisions__BuildOptions_R1,
	          "",
	          "");
	I_Method4(int, divide, IN, osg::KdTree::BuildOptions &, options, IN, osg::BoundingBox &, bb, IN, int, nodeIndex, IN, unsigned int, level,
	          Properties::NON_VIRTUAL,
	          __int__divide__BuildOptions_R1__osg_BoundingBox_R1__int__unsigned_int,
	          "",
	          "");
	I_Method4(bool, intersect, IN, const osg::KdTree::KdLeaf &, leaf, IN, const osg::Vec3 &, start, IN, const osg::Vec3 &, end, IN, osg::KdTree::LineSegmentIntersections &, intersections,
	          Properties::NON_VIRTUAL,
	          __bool__intersect__C5_KdLeaf_R1__C5_osg_Vec3_R1__C5_osg_Vec3_R1__LineSegmentIntersections_R1,
	          "",
	          "");
	I_Method6(bool, intersect, IN, const osg::KdTree::KdNode &, node, IN, const osg::Vec3 &, start, IN, const osg::Vec3 &, end, IN, const osg::Vec3 &, s, IN, const osg::Vec3 &, e, IN, osg::KdTree::LineSegmentIntersections &, intersections,
	          Properties::NON_VIRTUAL,
	          __bool__intersect__C5_KdNode_R1__C5_osg_Vec3_R1__C5_osg_Vec3_R1__C5_osg_Vec3_R1__C5_osg_Vec3_R1__LineSegmentIntersections_R1,
	          "",
	          "");
	I_Method3(bool, intersectAndClip, IN, osg::Vec3 &, s, IN, osg::Vec3 &, e, IN, const osg::BoundingBox &, bb,
	          Properties::NON_VIRTUAL,
	          __bool__intersectAndClip__osg_Vec3_R1__osg_Vec3_R1__C5_osg_BoundingBox_R1,
	          "",
	          "");
	I_PublicMemberProperty(osg::observer_ptr< osg::Geometry >, _geometry);
	I_PublicMemberProperty(osg::BoundingBox, _bb);
	I_PublicMemberProperty(osg::KdTree::AxisStack, _axisStack);
	I_PublicMemberProperty(osg::KdTree::KdNodeList, _kdNodes);
	I_PublicMemberProperty(osg::KdTree::KdLeafList, _kdLeaves);
	I_PublicMemberProperty(osg::ref_ptr< osg::Vec3Array >, _vertices);
	I_PublicMemberProperty(osg::KdTree::Indices, _primitiveIndices);
	I_PublicMemberProperty(osg::KdTree::BoundingBoxList, _boundingBoxes);
	I_PublicMemberProperty(osg::KdTree::TriangleList, _triangles);
	I_PublicMemberProperty(osg::KdTree::CenterList, _centers);
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::KdTree::BuildOptions)
	I_DeclaringFile("osg/KdTree");
	I_Constructor0(____BuildOptions,
	               "",
	               "");
	I_PublicMemberProperty(int, _numVerticesProcessed);
	I_PublicMemberProperty(int, _targetNumTrianglesPerLeaf);
	I_PublicMemberProperty(int, _maxNumLevels);
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::KdTree::KdLeaf)
	I_DeclaringFile("osg/KdTree");
	I_Constructor0(____KdLeaf,
	               "",
	               "");
	I_Constructor2(IN, osg::KdTree::value_type, f, IN, osg::KdTree::value_type, s,
	               ____KdLeaf__value_type__value_type,
	               "",
	               "");
	I_PublicMemberProperty(osg::KdTree::value_type, first);
	I_PublicMemberProperty(osg::KdTree::value_type, second);
	I_PublicMemberProperty(osg::BoundingBox, bb);
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::KdTree::KdNode)
	I_DeclaringFile("osg/KdTree");
	I_Constructor0(____KdNode,
	               "",
	               "");
	I_Constructor2(IN, osg::KdTree::value_type, f, IN, osg::KdTree::value_type, s,
	               ____KdNode__value_type__value_type,
	               "",
	               "");
	I_PublicMemberProperty(osg::KdTree::value_type, first);
	I_PublicMemberProperty(osg::KdTree::value_type, second);
	I_PublicMemberProperty(osg::BoundingBox, bb);
END_REFLECTOR

TYPE_NAME_ALIAS(std::vector< unsigned int >, osg::KdTree::LineSegmentIntersection::IndexList)

TYPE_NAME_ALIAS(std::vector< double >, osg::KdTree::LineSegmentIntersection::RatioList)

BEGIN_VALUE_REFLECTOR(osg::KdTree::LineSegmentIntersection)
	I_DeclaringFile("osg/KdTree");
	I_Constructor0(____LineSegmentIntersection,
	               "",
	               "");
	I_PublicMemberProperty(double, ratio);
	I_PublicMemberProperty(osg::Vec3d, intersectionPoint);
	I_PublicMemberProperty(osg::Vec3, intersectionNormal);
	I_PublicMemberProperty(osg::KdTree::LineSegmentIntersection::IndexList, indexList);
	I_PublicMemberProperty(osg::KdTree::LineSegmentIntersection::RatioList, ratioList);
	I_PublicMemberProperty(unsigned int, primitiveIndex);
END_REFLECTOR

BEGIN_VALUE_REFLECTOR(osg::KdTree::Triangle)
	I_DeclaringFile("osg/KdTree");
	I_Constructor3(IN, unsigned int, p1, IN, unsigned int, p2, IN, unsigned int, p3,
	               ____Triangle__unsigned_int__unsigned_int__unsigned_int,
	               "",
	               "");
	I_PublicMemberProperty(unsigned int, _p1);
	I_PublicMemberProperty(unsigned int, _p2);
	I_PublicMemberProperty(unsigned int, _p3);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osg::KdTreeBuilder)
	I_DeclaringFile("osg/KdTree");
	I_BaseType(osg::NodeVisitor);
	I_Constructor0(____KdTreeBuilder,
	               "",
	               "");
	I_Constructor1(IN, const osg::KdTreeBuilder &, rhs,
	               Properties::NON_EXPLICIT,
	               ____KdTreeBuilder__C5_KdTreeBuilder_R1,
	               "",
	               "");
	I_Method0(osg::KdTreeBuilder *, clone,
	          Properties::VIRTUAL,
	          __KdTreeBuilder_P1__clone,
	          "",
	          "");
	I_Method1(void, apply, IN, osg::Geode &, geode,
	          Properties::VIRTUAL,
	          __void__apply__osg_Geode_R1,
	          "",
	          "");
	I_PublicMemberProperty(osg::KdTree::BuildOptions, _buildOptions);
	I_PublicMemberProperty(osg::ref_ptr< osg::KdTree >, _kdTreePrototype);
END_REFLECTOR

STD_SET_REFLECTOR(std::multiset< osg::KdTree::LineSegmentIntersection >)

STD_VECTOR_REFLECTOR(std::vector< double >)

STD_VECTOR_REFLECTOR(std::vector< osg::BoundingBox >)

STD_VECTOR_REFLECTOR(std::vector< osg::KdTree::KdLeaf >)

STD_VECTOR_REFLECTOR(std::vector< osg::KdTree::KdNode >)

STD_VECTOR_REFLECTOR(std::vector< osg::KdTree::Triangle >)

STD_VECTOR_REFLECTOR(std::vector< osg::KdTree::value_type >)

<|endoftext|>


<commit_before>#include <nan.h>
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <stdlib.h>
#include <stdio.h>

#include <poppler/qt5/poppler-form.h>
#include <poppler/qt5/poppler-qt5.h>

#include <cairo/cairo.h>
#include <cairo/cairo-pdf.h>

#include <QtCore/QBuffer>
#include <QtCore/QFile>
#include <QtGui/QImage>

#include "NodePoppler.h"    // NOLINT(build/include)

using namespace std;
using v8::Number;
using v8::String;
using v8::Local;
using v8::Object;
using v8::Array;
using v8::Value;
using v8::Boolean;

inline bool fileExists (const std::string& name) {
  if (FILE *file = fopen(name.c_str(), "r")) {
    fclose(file);
    return true;
  } else {
    return false;
  }
}

// Cairo write and read functions (to QBuffer)
static cairo_status_t readPngFromBuffer(void *closure, unsigned char *data, unsigned int length) {
  QBuffer *myBuffer = (QBuffer *)closure;
  size_t bytes_read;
  bytes_read = myBuffer->read((char *)data, length);
  if (bytes_read != length)
    return CAIRO_STATUS_READ_ERROR;

  return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t writePngToBuffer(void *closure, const unsigned char *data, unsigned int length) {
  QBuffer *myBuffer = (QBuffer *)closure;
  size_t bytes_wrote;
  bytes_wrote = myBuffer->write((char *)data, length);
  if (bytes_wrote != length)
    return CAIRO_STATUS_READ_ERROR;

  return CAIRO_STATUS_SUCCESS;
}

void createPdf(QBuffer *buffer, Poppler::Document *document) {
  ostringstream ss;

  Poppler::PDFConverter *converter = document->pdfConverter();
  converter->setPDFOptions(converter->pdfOptions() | Poppler::PDFConverter::WithChanges);
  converter->setOutputDevice(buffer);
  if (!converter->convert()) {
    // enum Error
    // {
    //     NoError,
    //     FileLockedError,
    //     OpenOutputError,
    //     NotSupportedInputFileError
    // };
    ss << "Error occurred when converting PDF: " << converter->lastError();
    delete converter;
    throw ss.str();
  }
  delete converter;
}

void createImgPdf(QBuffer *buffer, Poppler::Document *document) {
  // Calculate max page sizes. The output PDF will have its size set to max width/height.
  double maxWidth = 0;
  double maxHeight = 0;

  int n = document->numPages();

  for (int i = 0; i < n; i += 1) {
    Poppler::Page *page = document->page(i);

    QSizeF size = page->pageSizeF();

    if (size.height() > maxHeight)
      maxHeight = size.height();

    if (size.width() > maxWidth)
      maxWidth = size.width();
  }

  // Initialize Cairo writing surface, and since we have images at 360 DPI, we'll set scaling.
  cairo_surface_t *surface = cairo_pdf_surface_create_for_stream(writePngToBuffer, buffer, maxWidth, maxHeight);
  cairo_t *cr = cairo_create(surface);
  cairo_scale(cr, 0.2, 0.2);

  for (int i = 0; i < n; i += 1) {
    Poppler::Page *page = document->page(i);

    // Save the page as PNG image to buffer. (We could use QFile if we want to save images to files)
    QBuffer *pageImage = new QBuffer();
    pageImage->open(QIODevice::ReadWrite);
    QImage img = page->renderToImage(360, 360);
    img.save(pageImage, "png");
    pageImage->seek(0);  // Reading does not work if we don't reset the pointer

    // Ookay, let's try to make new page out of the image
    cairo_surface_t *drawImageSurface = cairo_image_surface_create_from_png_stream(readPngFromBuffer, pageImage);
    cairo_set_source_surface(cr, drawImageSurface, 0, 0);
    cairo_paint(cr);
    cairo_surface_destroy(drawImageSurface);

    // Create new page if multipage document
    if (n > 0) {
      cairo_surface_show_page(surface);
      if (cr != NULL) {
        cairo_destroy(cr);
      }
      cr = cairo_create(surface);
      cairo_scale(cr, 0.2, 0.2);
    }

    pageImage->close();
    delete pageImage;

    delete page;
  }

  // Close Cairo
  cairo_destroy(cr);
  cairo_surface_finish(surface);
  cairo_surface_destroy (surface);
}

WriteFieldsParams v8ParamsToCpp(const Nan::FunctionCallbackInfo<v8::Value>& args) {
  Local<Object> parameters;
  string saveFormat = "imgpdf";
  map<string, string> fields;

  String::Utf8Value sourcePdfFileNameParam(args[0]->ToString());
  string sourcePdfFileName = string(*sourcePdfFileNameParam);

  Local<Object> changeFields = args[1]->ToObject();
  Local<String> saveStr = Nan::New("save").ToLocalChecked();

  // Check if any configuration parameters
  if (args.Length() > 2) {
    parameters = args[2]->ToObject();
    Local<Value> saveParam = Nan::Get(parameters, saveStr).ToLocalChecked();
    if (!saveParam->IsUndefined()) {
      String::Utf8Value saveFormatParam(Nan::Get(parameters, saveStr).ToLocalChecked());
      saveFormat = string(*saveFormatParam);
    }
  }

  // Convert form fields to c++ map
  Local<Array> fieldArray = changeFields->GetPropertyNames();
  for (uint32_t i = 0; i < fieldArray->Length(); i += 1) {
    Local<Value> name = fieldArray->Get(i);
    Local<Value> value = changeFields->Get(name);
    fields[std::string(*String::Utf8Value(name))] = std::string(*String::Utf8Value(value));
  }

  // Create and return PDF
  struct WriteFieldsParams params(sourcePdfFileName, saveFormat, fields);
  return params;
}

// Pdf creator that is not dependent on V8 internals (safe at async?)
QBuffer *writePdfFields(struct WriteFieldsParams params) {

  ostringstream ss;
  // If source file does not exist, throw error and return false
  if (!fileExists(params.sourcePdfFileName)) {
    ss << "File \"" << params.sourcePdfFileName << "\" does not exist";
    throw ss.str();
  }

  // Open document and return false and throw error if something goes wrong
  Poppler::Document *document = Poppler::Document::load(QString::fromStdString(params.sourcePdfFileName));
  if (document == NULL) {
    ss << "Error occurred when reading \"" << params.sourcePdfFileName << "\"";
    throw ss.str();
  }

  // Fill form
  int n = document->numPages();
  stringstream idSS;
  for (int i = 0; i < n; i += 1) {
    Poppler::Page *page = document->page(i);
    QList<Poppler::FormField *> formFields = page->formFields();

    foreach (Poppler::FormField *field, formFields) {
      string fieldName = field->fullyQualifiedName().toStdString();
      // Support writing fields by both fieldName and id.
      // If fieldName is not present in params, try id.
      if (params.fields.count(fieldName) == 0) {
        idSS << field->id();
        fieldName = idSS.str();
        idSS.str("");
        idSS.clear();
      }
      if (!field->isReadOnly() && field->isVisible() && params.fields.count(fieldName) ) {
        // Text
        if (field->type() == Poppler::FormField::FormText) {
          Poppler::FormFieldText *textField = (Poppler::FormFieldText *) field;
          textField->setText(QString::fromUtf8(params.fields[fieldName].c_str()));
        }

        // Choice
        if (field->type() == Poppler::FormField::FormChoice) {
          Poppler::FormFieldChoice *choiceField = (Poppler::FormFieldChoice *) field;
          if (choiceField->isEditable()) {
            choiceField->setEditChoice(QString::fromUtf8(params.fields[fieldName].c_str()));
          }
          else {
            QStringList possibleChoices = choiceField->choices();
            QString proposedChoice = QString::fromUtf8(params.fields[fieldName].c_str());
            int index = possibleChoices.indexOf(proposedChoice);
            if (index >= 0) {
              QList<int> choiceList;
              choiceList << index;
              choiceField->setCurrentChoices(choiceList);
            }
          }
        }

        // Button
        // ! TODO ! Note. Poppler doesn't support checkboxes with hashtag names (aka using exportValue).
        if (field->type() == Poppler::FormField::FormButton) {
          Poppler::FormFieldButton* myButton = (Poppler::FormFieldButton *)field;
          switch (myButton->buttonType()) {
            // Push
            case Poppler::FormFieldButton::Push:     break;
            case Poppler::FormFieldButton::CheckBox:
              if (params.fields[fieldName].compare("true") == 0) {
                myButton->setState(true);
              }
              else {
                myButton->setState(false);
              }
              break;
            case Poppler::FormFieldButton::Radio:
              if (params.fields[fieldName].compare(myButton->caption().toUtf8().constData()) == 0) {
                myButton->setState(true);
              }
              else {
                myButton->setState(false);
              }
              break;
          }
        }
      }
    }

    qDeleteAll(formFields);
    delete page;
  }

  // Now save and return the document
  QBuffer *bufferDevice = new QBuffer();
  bufferDevice->open(QIODevice::ReadWrite);

  // Get save parameters
  if (params.saveFormat == "imgpdf") {
    createImgPdf(bufferDevice, document);
  }
  else {
    createPdf(bufferDevice, document);
  }

  delete document;

  return bufferDevice;
}

//***********************************
//
// Node.js methods
//
//***********************************

// Read PDF form fields
NAN_METHOD(ReadSync) {

  // expect a number as the first argument
  Nan::Utf8String *fileName = new Nan::Utf8String(info[0]);
  ostringstream ss;
  int n = 0;

  // If file does not exist, throw error and return false
  if (!fileExists(**fileName)) {
    ss << "File \"" << **fileName << "\" does not exist";
    Nan::ThrowError(Nan::New<String>(ss.str()).ToLocalChecked());
    info.GetReturnValue().Set(Nan::False());
  }

  // Open document and return false and throw error if something goes wrong
  Poppler::Document *document = Poppler::Document::load(**fileName);
  if (document != NULL) {
    // Get field list
    n = document->numPages();
  } else {
    ss << "Error occurred when reading \"" << **fileName << "\"";
    Nan::ThrowError(Nan::New<String>(ss.str()).ToLocalChecked());
    info.GetReturnValue().Set(Nan::False());
  }

  delete fileName;

  // Store field value objects to v8 array
  Local<Array> fieldArray = Nan::New<Array>();
  int fieldNum = 0;

  for (int i = 0; i < n; i += 1) {
    Poppler::Page *page = document->page(i);
    QList<Poppler::FormField *> formFields = page->formFields();

    foreach (Poppler::FormField *field, formFields) {

      if (!field->isReadOnly() && field->isVisible()) {

        // Make JavaScript object out of the fieldnames
        Local<Object> obj = Nan::New<Object>();
        Nan::Set(obj, Nan::New<String>("name").ToLocalChecked(), Nan::New<String>(field->fullyQualifiedName().toStdString()).ToLocalChecked());
        Nan::Set(obj, Nan::New<String>("page").ToLocalChecked(), Nan::New<Number>(i));

        // ! TODO ! Note. Poppler doesn't support checkboxes with hashtag names (aka using exportValue).
        string fieldType;
        // Set default value undefined
        Nan::Set(obj, Nan::New<String>("value").ToLocalChecked(), Nan::Undefined());
        Poppler::FormFieldButton *myButton;
        Poppler::FormFieldChoice *myChoice;

        Nan::Set(obj, Nan::New<String>("id").ToLocalChecked(), Nan::New<Number>(field->id()));
        switch (field->type()) {

          // FormButton
          case Poppler::FormField::FormButton:
            myButton = (Poppler::FormFieldButton *)field;
            switch (myButton->buttonType()) {
              // Push
              case Poppler::FormFieldButton::Push:        fieldType = "push_button";     break;
              case Poppler::FormFieldButton::CheckBox:
                fieldType = "checkbox";
                Nan::Set(obj, Nan::New<String>("value").ToLocalChecked(), Nan::New<Boolean>(myButton->state()));
                break;
              case Poppler::FormFieldButton::Radio:
                fieldType = "radio";
                Nan::Set(obj, Nan::New<String>("caption").ToLocalChecked(), Nan::New<String>(myButton->caption().toStdString()).ToLocalChecked());
                break;
            }
            break;

          // FormText
          case Poppler::FormField::FormText:
            Nan::Set(obj, Nan::New<String>("value").ToLocalChecked(), Nan::New<String>(((Poppler::FormFieldText *)field)->text().toStdString()).ToLocalChecked());
            fieldType = "text";
            break;

          // FormChoice
          case Poppler::FormField::FormChoice: {
            Local<Array> choiceArray = Nan::New<Array>();
            myChoice = (Poppler::FormFieldChoice *)field;
            QStringList possibleChoices = myChoice->choices();
            for (int i = 0; i < possibleChoices.size(); i++) {
              Nan::Set(choiceArray, i, Nan::New<String>(possibleChoices.at(i).toStdString()).ToLocalChecked());
            }
            Nan::Set(obj, Nan::New<String>("choices").ToLocalChecked(), choiceArray);
            switch (myChoice->choiceType()) {
              case Poppler::FormFieldChoice::ComboBox:    fieldType = "combobox";       break;
              case Poppler::FormFieldChoice::ListBox:     fieldType = "listbox";        break;
            }
            break;
          }

          // FormSignature
          case Poppler::FormField::FormSignature:         fieldType = "formsignature";  break;

          default:
            fieldType = "undefined";
            break;
        }

        Nan::Set(obj, Nan::New<String>("type").ToLocalChecked(), Nan::New<String>(fieldType.c_str()).ToLocalChecked());

        fieldArray->Set(fieldNum, obj);
        fieldNum++;

      }
    }

    qDeleteAll(formFields);
    delete page;
  }

  info.GetReturnValue().Set(fieldArray);

  delete document;
}

// Write PDF form fields
NAN_METHOD(WriteSync) {

  // Check and return parameters given at JavaScript function call
  WriteFieldsParams params = v8ParamsToCpp(info);

  // Create and return pdf
  try
  {
    QBuffer *buffer = writePdfFields(params);
    Local<Object> returnPdf = Nan::CopyBuffer((char *)buffer->data().data(), buffer->size()).ToLocalChecked();
    buffer->close();
    delete buffer;
    info.GetReturnValue().Set(returnPdf);
  }
  catch (string error)
  {
    Nan::ThrowError(Nan::New<String>(error).ToLocalChecked());
    info.GetReturnValue().Set(Nan::Null());
  }
}
<commit_msg>Set radio button "value" to the poppler button state<commit_after>#include <nan.h>
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <stdlib.h>
#include <stdio.h>

#include <poppler/qt5/poppler-form.h>
#include <poppler/qt5/poppler-qt5.h>

#include <cairo/cairo.h>
#include <cairo/cairo-pdf.h>

#include <QtCore/QBuffer>
#include <QtCore/QFile>
#include <QtGui/QImage>

#include "NodePoppler.h"    // NOLINT(build/include)

using namespace std;
using v8::Number;
using v8::String;
using v8::Local;
using v8::Object;
using v8::Array;
using v8::Value;
using v8::Boolean;

inline bool fileExists (const std::string& name) {
  if (FILE *file = fopen(name.c_str(), "r")) {
    fclose(file);
    return true;
  } else {
    return false;
  }
}

// Cairo write and read functions (to QBuffer)
static cairo_status_t readPngFromBuffer(void *closure, unsigned char *data, unsigned int length) {
  QBuffer *myBuffer = (QBuffer *)closure;
  size_t bytes_read;
  bytes_read = myBuffer->read((char *)data, length);
  if (bytes_read != length)
    return CAIRO_STATUS_READ_ERROR;

  return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t writePngToBuffer(void *closure, const unsigned char *data, unsigned int length) {
  QBuffer *myBuffer = (QBuffer *)closure;
  size_t bytes_wrote;
  bytes_wrote = myBuffer->write((char *)data, length);
  if (bytes_wrote != length)
    return CAIRO_STATUS_READ_ERROR;

  return CAIRO_STATUS_SUCCESS;
}

void createPdf(QBuffer *buffer, Poppler::Document *document) {
  ostringstream ss;

  Poppler::PDFConverter *converter = document->pdfConverter();
  converter->setPDFOptions(converter->pdfOptions() | Poppler::PDFConverter::WithChanges);
  converter->setOutputDevice(buffer);
  if (!converter->convert()) {
    // enum Error
    // {
    //     NoError,
    //     FileLockedError,
    //     OpenOutputError,
    //     NotSupportedInputFileError
    // };
    ss << "Error occurred when converting PDF: " << converter->lastError();
    delete converter;
    throw ss.str();
  }
  delete converter;
}

void createImgPdf(QBuffer *buffer, Poppler::Document *document) {
  // Calculate max page sizes. The output PDF will have its size set to max width/height.
  double maxWidth = 0;
  double maxHeight = 0;

  int n = document->numPages();

  for (int i = 0; i < n; i += 1) {
    Poppler::Page *page = document->page(i);

    QSizeF size = page->pageSizeF();

    if (size.height() > maxHeight)
      maxHeight = size.height();

    if (size.width() > maxWidth)
      maxWidth = size.width();
  }

  // Initialize Cairo writing surface, and since we have images at 360 DPI, we'll set scaling.
  cairo_surface_t *surface = cairo_pdf_surface_create_for_stream(writePngToBuffer, buffer, maxWidth, maxHeight);
  cairo_t *cr = cairo_create(surface);
  cairo_scale(cr, 0.2, 0.2);

  for (int i = 0; i < n; i += 1) {
    Poppler::Page *page = document->page(i);

    // Save the page as PNG image to buffer. (We could use QFile if we want to save images to files)
    QBuffer *pageImage = new QBuffer();
    pageImage->open(QIODevice::ReadWrite);
    QImage img = page->renderToImage(360, 360);
    img.save(pageImage, "png");
    pageImage->seek(0);  // Reading does not work if we don't reset the pointer

    // Ookay, let's try to make new page out of the image
    cairo_surface_t *drawImageSurface = cairo_image_surface_create_from_png_stream(readPngFromBuffer, pageImage);
    cairo_set_source_surface(cr, drawImageSurface, 0, 0);
    cairo_paint(cr);
    cairo_surface_destroy(drawImageSurface);

    // Create new page if multipage document
    if (n > 0) {
      cairo_surface_show_page(surface);
      if (cr != NULL) {
        cairo_destroy(cr);
      }
      cr = cairo_create(surface);
      cairo_scale(cr, 0.2, 0.2);
    }

    pageImage->close();
    delete pageImage;

    delete page;
  }

  // Close Cairo
  cairo_destroy(cr);
  cairo_surface_finish(surface);
  cairo_surface_destroy (surface);
}

WriteFieldsParams v8ParamsToCpp(const Nan::FunctionCallbackInfo<v8::Value>& args) {
  Local<Object> parameters;
  string saveFormat = "imgpdf";
  map<string, string> fields;

  String::Utf8Value sourcePdfFileNameParam(args[0]->ToString());
  string sourcePdfFileName = string(*sourcePdfFileNameParam);

  Local<Object> changeFields = args[1]->ToObject();
  Local<String> saveStr = Nan::New("save").ToLocalChecked();

  // Check if any configuration parameters
  if (args.Length() > 2) {
    parameters = args[2]->ToObject();
    Local<Value> saveParam = Nan::Get(parameters, saveStr).ToLocalChecked();
    if (!saveParam->IsUndefined()) {
      String::Utf8Value saveFormatParam(Nan::Get(parameters, saveStr).ToLocalChecked());
      saveFormat = string(*saveFormatParam);
    }
  }

  // Convert form fields to c++ map
  Local<Array> fieldArray = changeFields->GetPropertyNames();
  for (uint32_t i = 0; i < fieldArray->Length(); i += 1) {
    Local<Value> name = fieldArray->Get(i);
    Local<Value> value = changeFields->Get(name);
    fields[std::string(*String::Utf8Value(name))] = std::string(*String::Utf8Value(value));
  }

  // Create and return PDF
  struct WriteFieldsParams params(sourcePdfFileName, saveFormat, fields);
  return params;
}

// Pdf creator that is not dependent on V8 internals (safe at async?)
QBuffer *writePdfFields(struct WriteFieldsParams params) {

  ostringstream ss;
  // If source file does not exist, throw error and return false
  if (!fileExists(params.sourcePdfFileName)) {
    ss << "File \"" << params.sourcePdfFileName << "\" does not exist";
    throw ss.str();
  }

  // Open document and return false and throw error if something goes wrong
  Poppler::Document *document = Poppler::Document::load(QString::fromStdString(params.sourcePdfFileName));
  if (document == NULL) {
    ss << "Error occurred when reading \"" << params.sourcePdfFileName << "\"";
    throw ss.str();
  }

  // Fill form
  int n = document->numPages();
  stringstream idSS;
  for (int i = 0; i < n; i += 1) {
    Poppler::Page *page = document->page(i);
    QList<Poppler::FormField *> formFields = page->formFields();

    foreach (Poppler::FormField *field, formFields) {
      string fieldName = field->fullyQualifiedName().toStdString();
      // Support writing fields by both fieldName and id.
      // If fieldName is not present in params, try id.
      if (params.fields.count(fieldName) == 0) {
        idSS << field->id();
        fieldName = idSS.str();
        idSS.str("");
        idSS.clear();
      }
      if (!field->isReadOnly() && field->isVisible() && params.fields.count(fieldName) ) {
        // Text
        if (field->type() == Poppler::FormField::FormText) {
          Poppler::FormFieldText *textField = (Poppler::FormFieldText *) field;
          textField->setText(QString::fromUtf8(params.fields[fieldName].c_str()));
        }

        // Choice
        if (field->type() == Poppler::FormField::FormChoice) {
          Poppler::FormFieldChoice *choiceField = (Poppler::FormFieldChoice *) field;
          if (choiceField->isEditable()) {
            choiceField->setEditChoice(QString::fromUtf8(params.fields[fieldName].c_str()));
          }
          else {
            QStringList possibleChoices = choiceField->choices();
            QString proposedChoice = QString::fromUtf8(params.fields[fieldName].c_str());
            int index = possibleChoices.indexOf(proposedChoice);
            if (index >= 0) {
              QList<int> choiceList;
              choiceList << index;
              choiceField->setCurrentChoices(choiceList);
            }
          }
        }

        // Button
        // ! TODO ! Note. Poppler doesn't support checkboxes with hashtag names (aka using exportValue).
        if (field->type() == Poppler::FormField::FormButton) {
          Poppler::FormFieldButton* myButton = (Poppler::FormFieldButton *)field;
          switch (myButton->buttonType()) {
            // Push
            case Poppler::FormFieldButton::Push:     break;
            case Poppler::FormFieldButton::CheckBox:
              if (params.fields[fieldName].compare("true") == 0) {
                myButton->setState(true);
              }
              else {
                myButton->setState(false);
              }
              break;
            case Poppler::FormFieldButton::Radio:
              if (params.fields[fieldName].compare(myButton->caption().toUtf8().constData()) == 0) {
                myButton->setState(true);
              }
              else {
                myButton->setState(false);
              }
              break;
          }
        }
      }
    }

    qDeleteAll(formFields);
    delete page;
  }

  // Now save and return the document
  QBuffer *bufferDevice = new QBuffer();
  bufferDevice->open(QIODevice::ReadWrite);

  // Get save parameters
  if (params.saveFormat == "imgpdf") {
    createImgPdf(bufferDevice, document);
  }
  else {
    createPdf(bufferDevice, document);
  }

  delete document;

  return bufferDevice;
}

//***********************************
//
// Node.js methods
//
//***********************************

// Read PDF form fields
NAN_METHOD(ReadSync) {

  // expect a number as the first argument
  Nan::Utf8String *fileName = new Nan::Utf8String(info[0]);
  ostringstream ss;
  int n = 0;

  // If file does not exist, throw error and return false
  if (!fileExists(**fileName)) {
    ss << "File \"" << **fileName << "\" does not exist";
    Nan::ThrowError(Nan::New<String>(ss.str()).ToLocalChecked());
    info.GetReturnValue().Set(Nan::False());
  }

  // Open document and return false and throw error if something goes wrong
  Poppler::Document *document = Poppler::Document::load(**fileName);
  if (document != NULL) {
    // Get field list
    n = document->numPages();
  } else {
    ss << "Error occurred when reading \"" << **fileName << "\"";
    Nan::ThrowError(Nan::New<String>(ss.str()).ToLocalChecked());
    info.GetReturnValue().Set(Nan::False());
  }

  delete fileName;

  // Store field value objects to v8 array
  Local<Array> fieldArray = Nan::New<Array>();
  int fieldNum = 0;

  for (int i = 0; i < n; i += 1) {
    Poppler::Page *page = document->page(i);
    QList<Poppler::FormField *> formFields = page->formFields();

    foreach (Poppler::FormField *field, formFields) {

      if (!field->isReadOnly() && field->isVisible()) {

        // Make JavaScript object out of the fieldnames
        Local<Object> obj = Nan::New<Object>();
        Nan::Set(obj, Nan::New<String>("name").ToLocalChecked(), Nan::New<String>(field->fullyQualifiedName().toStdString()).ToLocalChecked());
        Nan::Set(obj, Nan::New<String>("page").ToLocalChecked(), Nan::New<Number>(i));

        // ! TODO ! Note. Poppler doesn't support checkboxes with hashtag names (aka using exportValue).
        string fieldType;
        // Set default value undefined
        Nan::Set(obj, Nan::New<String>("value").ToLocalChecked(), Nan::Undefined());
        Poppler::FormFieldButton *myButton;
        Poppler::FormFieldChoice *myChoice;

        Nan::Set(obj, Nan::New<String>("id").ToLocalChecked(), Nan::New<Number>(field->id()));
        switch (field->type()) {

          // FormButton
          case Poppler::FormField::FormButton:
            myButton = (Poppler::FormFieldButton *)field;
            switch (myButton->buttonType()) {
              // Push
              case Poppler::FormFieldButton::Push:        fieldType = "push_button";     break;
              case Poppler::FormFieldButton::CheckBox:
                fieldType = "checkbox";
                Nan::Set(obj, Nan::New<String>("value").ToLocalChecked(), Nan::New<Boolean>(myButton->state()));
                break;
              case Poppler::FormFieldButton::Radio:
                fieldType = "radio";
                Nan::Set(obj, Nan::New<String>("caption").ToLocalChecked(), Nan::New<String>(myButton->caption().toStdString()).ToLocalChecked());
                Nan::Set(obj, Nan::New<String>("value").ToLocalChecked(), Nan::New<Boolean>(myButton->state()));
                break;
            }
            break;

          // FormText
          case Poppler::FormField::FormText:
            Nan::Set(obj, Nan::New<String>("value").ToLocalChecked(), Nan::New<String>(((Poppler::FormFieldText *)field)->text().toStdString()).ToLocalChecked());
            fieldType = "text";
            break;

          // FormChoice
          case Poppler::FormField::FormChoice: {
            Local<Array> choiceArray = Nan::New<Array>();
            myChoice = (Poppler::FormFieldChoice *)field;
            QStringList possibleChoices = myChoice->choices();
            for (int i = 0; i < possibleChoices.size(); i++) {
              Nan::Set(choiceArray, i, Nan::New<String>(possibleChoices.at(i).toStdString()).ToLocalChecked());
            }
            Nan::Set(obj, Nan::New<String>("choices").ToLocalChecked(), choiceArray);
            switch (myChoice->choiceType()) {
              case Poppler::FormFieldChoice::ComboBox:    fieldType = "combobox";       break;
              case Poppler::FormFieldChoice::ListBox:     fieldType = "listbox";        break;
            }
            break;
          }

          // FormSignature
          case Poppler::FormField::FormSignature:         fieldType = "formsignature";  break;

          default:
            fieldType = "undefined";
            break;
        }

        Nan::Set(obj, Nan::New<String>("type").ToLocalChecked(), Nan::New<String>(fieldType.c_str()).ToLocalChecked());

        fieldArray->Set(fieldNum, obj);
        fieldNum++;

      }
    }

    qDeleteAll(formFields);
    delete page;
  }

  info.GetReturnValue().Set(fieldArray);

  delete document;
}

// Write PDF form fields
NAN_METHOD(WriteSync) {

  // Check and return parameters given at JavaScript function call
  WriteFieldsParams params = v8ParamsToCpp(info);

  // Create and return pdf
  try
  {
    QBuffer *buffer = writePdfFields(params);
    Local<Object> returnPdf = Nan::CopyBuffer((char *)buffer->data().data(), buffer->size()).ToLocalChecked();
    buffer->close();
    delete buffer;
    info.GetReturnValue().Set(returnPdf);
  }
  catch (string error)
  {
    Nan::ThrowError(Nan::New<String>(error).ToLocalChecked());
    info.GetReturnValue().Set(Nan::Null());
  }
}
<|endoftext|>


<commit_before>#include "argumentparser.hh"
#include "tools.hh"

using namespace nolang;

ArgumentParser::ArgumentParser(Compiler *c, mpc_ast_t *t) :
    compiler(c),
    tree(t)
{
}

void ArgumentParser::reset()
{
    braceOpenLevel = 0;
    params.clear();
}

bool ArgumentParser::isOpenBrace() const
{
    return expect(item, "char", "(");
}

bool ArgumentParser::isCloseBrace() const
{
    return expect(item, "char", ")");
}

bool ArgumentParser::isParamDef() const
{
    return braceOpenLevel == 1 && expect(item, "paramdef");
}

bool ArgumentParser::isTypeIdent() const
{
    return braceOpenLevel == 1 && expect(item, "typeident");
}

bool ArgumentParser::isComma() const
{
    return braceOpenLevel == 1 && expect(item, "char", ",");
}

bool ArgumentParser::isTypeIdentifier(Statement *s) const
{
    return s && s->type() == "TypeIdent";
}

bool ArgumentParser::isOptionalWhitespace() const
{
    return expect(item, "ows");
}

void ArgumentParser::parseTypeIdent()
{
    auto res = compiler->codegen(item, nullptr, 0, true);
    for (auto r : res){
        if (isTypeIdentifier(r)) params.push_back(static_cast<TypeIdent*>(r));
        else throw std::string("Invalid parameter definition: " + r->code());
    }
}

void ArgumentParser::parseParamDef()
{
    mpc_ast_t *paramdef = item;
    iterateTree(paramdef, [&] (mpc_ast_t *def) {
        item = def;
        if (isTypeIdent()) parseTypeIdent();
        else if (isComma() || isOptionalWhitespace());
        else printError("Unknown node in parameter", item);
        /*
        std::string cnts = item->contents;
        if (expect(item, "typeident")) {
            m_parameters = true;
            auto res = codegen(item, m, level + 1);
            m_parameters = false;
            for (auto r : res){
                if (r->type() == "TypeIdent")
                    m->addParameter(static_cast<TypeIdent*>(r));
                else
                    throw std::string("Invalid parameter definition: " + r->code());
            }
        } else if (expect(item, "char") && cnts == ",") {
            // FIXME Can ',' separate in params something else than next param?
        } else printError("Unknown node in parameter", item);
        */
    });
}

void ArgumentParser::parseItem()
{
    if (isOpenBrace()) ++braceOpenLevel;
    else if (isCloseBrace()) --braceOpenLevel;
    else if (isParamDef()) parseParamDef();
    else printError("Unknown node in arguments", item);
}

std::vector<TypeIdent*> ArgumentParser::parse()
{
    reset();
    iterate(item, tree, parseItem);
    return params;
}
<commit_msg>Cleanup<commit_after>#include "argumentparser.hh"
#include "tools.hh"

using namespace nolang;

ArgumentParser::ArgumentParser(Compiler *c, mpc_ast_t *t) :
    compiler(c),
    tree(t)
{
}

void ArgumentParser::reset()
{
    braceOpenLevel = 0;
    params.clear();
}

bool ArgumentParser::isOpenBrace() const
{
    return expect(item, "char", "(");
}

bool ArgumentParser::isCloseBrace() const
{
    return expect(item, "char", ")");
}

bool ArgumentParser::isParamDef() const
{
    return braceOpenLevel == 1 && expect(item, "paramdef");
}

bool ArgumentParser::isTypeIdent() const
{
    return braceOpenLevel == 1 && expect(item, "typeident");
}

bool ArgumentParser::isComma() const
{
    return braceOpenLevel == 1 && expect(item, "char", ",");
}

bool ArgumentParser::isTypeIdentifier(Statement *s) const
{
    return s && s->type() == "TypeIdent";
}

bool ArgumentParser::isOptionalWhitespace() const
{
    return expect(item, "ows");
}

void ArgumentParser::parseTypeIdent()
{
    auto res = compiler->codegen(item, nullptr, 0, true);
    for (auto r : res){
        if (isTypeIdentifier(r)) params.push_back(static_cast<TypeIdent*>(r));
        else throw std::string("Invalid parameter definition: " + r->code());
    }
}

void ArgumentParser::parseParamDef()
{
    mpc_ast_t *paramdef = item;
    iterateTree(paramdef, [&] (mpc_ast_t *def) {
        item = def;
        if (isTypeIdent()) parseTypeIdent();
        else if (isComma() || isOptionalWhitespace());
        else printError("Unknown node in parameter", item);
    });
}

void ArgumentParser::parseItem()
{
    if (isOpenBrace()) ++braceOpenLevel;
    else if (isCloseBrace()) --braceOpenLevel;
    else if (isParamDef()) parseParamDef();
    else printError("Unknown node in arguments", item);
}

std::vector<TypeIdent*> ArgumentParser::parse()
{
    reset();
    iterate(item, tree, parseItem);
    return params;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include <string>
#include "Logger.h"

#ifdef _WIN64
#define PYTHONPATH L"python-embed-amd64"
#else
#define PYTHONPATH L"python-embed-win32"
#endif

EXTERN_C IMAGE_DOS_HEADER __ImageBase;

std::wstring getPythonPath()
{
    // https://stackoverflow.com/questions/6924195/get-dll-path-at-runtime
    WCHAR DllPath[MAX_PATH] = { 0 };
    if (GetModuleFileNameW((HINSTANCE)&__ImageBase, DllPath, _countof(DllPath)) == 0)
    {
        LOG_ERROR("Error getting Pythia DLL path");
        return L"";
    }
    std::wstring DllPath_s = DllPath;

    std::wstring directory;
    const size_t last_slash_idx = DllPath_s.rfind(L'\\');
    if (std::string::npos != last_slash_idx)
    {
        directory = DllPath_s.substr(0, last_slash_idx);
    }

    std::wstring pythonPath = directory + L"\\" + PYTHONPATH;
    return pythonPath;
}
<commit_msg>Change define name to prevent name clashes with the python interpreter<commit_after>#include "stdafx.h"
#include <string>
#include "Logger.h"

#ifdef _WIN64
#define EMBEDDEDPYTHONPATH L"python-embed-amd64"
#else
#define EMBEDDEDPYTHONPATH L"python-embed-win32"
#endif

EXTERN_C IMAGE_DOS_HEADER __ImageBase;

std::wstring getPythonPath()
{
    // https://stackoverflow.com/questions/6924195/get-dll-path-at-runtime
    WCHAR DllPath[MAX_PATH] = { 0 };
    if (GetModuleFileNameW((HINSTANCE)&__ImageBase, DllPath, _countof(DllPath)) == 0)
    {
        LOG_ERROR("Error getting Pythia DLL path");
        return L"";
    }
    std::wstring DllPath_s = DllPath;

    std::wstring directory;
    const size_t last_slash_idx = DllPath_s.rfind(L'\\');
    if (std::string::npos != last_slash_idx)
    {
        directory = DllPath_s.substr(0, last_slash_idx);
    }

    std::wstring pythonPath = directory + L"\\" + EMBEDDEDPYTHONPATH;
    return pythonPath;
}
<|endoftext|>