<commit_before>#include <iostream>
#include <fstream>
#include <string>

using namespace std;

//Function to count the lines of the script to be converted
int linecounter(string dir){
    int counter = 0;

    string line;

    //Create new file stream to file to be converted
    ifstream file(dir);

    while (getline(file, line)){
        counter++;}

    return counter;
}

//Accepts a string and returns the value of the key(s) in digispark language
//Some of the keys are encoded using their usage IDs. Refer to http://www.usb.org/developers/hidpage/Hut1_12v2.pdf  (Page 53-59)
string stringprocessor(string key){

    if((key == "A") || (key == "a")){
        key = "KEY_A";
        return key;
    }

    else if((key == "B") || (key == "b")){
        key = "KEY_B";
        return key;
    }

    else if((key == "C") || (key == "c")){
        key = "KEY_C";
        return key;
    }

    else if((key == "D") || (key == "d")){
        key = "KEY_D";
        return key;
    }

    else if((key == "E") || (key == "e")){
        key = "KEY_E";
        return key;
    }

    else if((key == "F") || (key == "f")){
        key = "KEY_F";
        return key;
    }

    else if((key == "G") || (key == "g")){
        key = "KEY_G";
        return key;
    }

    else if((key == "H") || (key == "h")){
        key = "KEY_H";
        return key;
    }

    else if((key == "I") || (key == "i")){
        key = "KEY_I";
        return key;
    }

    else if((key == "J") || (key == "j")){
        key = "KEY_J";
        return key;
    }

    else if((key == "K") || (key == "k")){
        key = "KEY_K";
        return key;
    }

    else if((key == "L") || (key == "l")){
        key = "KEY_L";
        return key;
    }

    else if((key == "M") || (key == "m")){
        key = "KEY_M";
        return key;
    }

    else if((key == "N") || (key == "n")){
        key = "KEY_N";
        return key;
    }

    else if((key == "O") || (key == "o")){
        key = "KEY_O";
        return key;
    }

    else if((key == "P") || (key == "p")){
        key = "KEY_P";
        return key;
    }

    else if((key == "Q") || (key == "q")){
        key = "KEY_Q";
        return key;
    }

    else if((key == "R") || (key == "r")){
        key = "KEY_R";
        return key;
    }

    else if((key == "S") || (key == "s")){
        key = "KEY_S";
        return key;
    }

    else if((key == "T") || (key == "t")){
        key = "KEY_T";
        return key;
    }

    else if((key == "U") || (key == "u")){
        key = "KEY_U";
        return key;
    }

    else if((key == "V") || (key == "v")){
        key = "KEY_V";
        return key;
    }

    else if((key == "W") || (key == "w")){
        key = "KEY_W";
        return key;
    }

    else if((key == "X") || (key == "x")){
        key = "KEY_X";
        return key;
    }

    else if((key == "Y") || (key == "y")){
        key = "KEY_Y";
        return key;
    }

    else if((key == "Z") || (key == "z")){
        key = "KEY_Z";
        return key;
    }

    else if(key=="1"){
        key = "KEY_1";
        return key;
    }

    else if(key=="2"){
        key = "KEY_2";
        return key;
    }

    else if(key=="3"){
        key = "KEY_3";
        return key;
    }

    else if(key=="4"){
        key = "KEY_4";
        return key;
    }

    else if(key=="5"){
        key = "KEY_5";
        return key;
    }

    else if(key=="6"){
        key = "KEY_6";
        return key;
    }

    else if(key=="7"){
        key = "KEY_7";
        return key;
    }

    else if(key=="8"){
        key = "KEY_8";
        return key;
    }

    else if(key=="9"){
        key = "KEY_9";
        return key;
    }

    else if(key=="0"){
        key = "KEY_0";
        return key;
    }

    else if(key=="ENTER"){
        key = "KEY_ENTER";
        return key;
    }

    else if(key=="F1"){
        key = "KEY_F1";
        return key;
    }

    else if(key=="F2"){
        key = "KEY_F2";
        return key;
    }

    else if(key=="F3"){
        key = "KEY_F3";
        return key;
    }

    else if(key=="F4"){
        key = "KEY_F4";
        return key;
    }

    else if(key=="F5"){
        key = "KEY_F5";
        return key;
    }

    else if(key=="F6"){
        key = "KEY_F6";
        return key;
    }

    else if(key=="F7"){
        key = "KEY_F7";
        return key;
    }

    else if(key=="F8"){
        key = "KEY_F8";
        return key;
    }

    else if(key=="F9"){
        key = "KEY_F9";
        return key;
    }

    else if(key=="F10"){
        key = "KEY_F10";
        return key;
    }

    else if(key=="F11"){
        key = "KEY_F11";
        return key;
    }

    else if(key=="F12"){
        key = "KEY_F12";
        return key;
    }

    else if((key=="GUI") || (key=="WINDOWS")){
        key = "0, MOD_GUI_LEFT"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="APP") || (key=="MENU")){
        key = "101"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if(key=="SHIFT"){
        key = "MOD_SHIFT_LEFT";
        return key;
    }

    else if(key=="ALT"){
        key = "MOD_ALT_LEFT";
        return key;
    }

    else if((key=="CONTROL") || (key=="CTRL")){
        key = "MOD_CONTROL_LEFT"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="DOWNARROW") || (key=="DOWN")){
        key = "84"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="UPARROW") || (key=="UP")){
        key = "83"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="LEFTARROW") || (key=="LEFT")){
        key = "79"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="RIGHTARROW") || (key=="RIGHT")){
        key = "89"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="BREAK") || (key=="PAUSE")){
        key = "126"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if(key=="CAPSLOCK"){
        key = "30";
        return key;
    }

    else if((key=="ESC") || (key=="ESCAPE")){
        key = "110";
        return key;
    }

    else if(key=="DELETE"){
        key = "15";
        return key;
    }

    else if(key=="END"){
        key = "81";
        return key;
    }

    else if(key=="HOME"){
        key = "80";
        return key;
    }

    else if(key=="NUMLOCK"){
        key = "90";
        return key;
    }

    else if(key=="PAGEUP"){
        key = "85";
        return key;
    }

    else if(key=="PAGEDOWN"){
        key = "86";
        return key;
    }

    else if(key=="PRINTSCREEN"){
        key = "124";
        return key;
    }

    else if(key=="SCROLLLOCK"){
        key = "125";
        return key;
    }

    else if(key=="SPACE"){
        key = "61";
        return key;
    }

    else if(key=="TAB"){
        key = "16";
        return key;
    }
}

int main(){

    //Eye-candy
    cout<<"  _      _      _";
    cout<<">(.)__ <(.)__ =(.)__";
    cout<<" (___/  (___/  (___/";
    cout<<endl;
    cout<<endl;
    cout<<"Welcome to digiQuack, the easy DuckyScript to Digispark payload converter!"<<endl;

    //Ask user to enter path to file to be converted
    string dir;
    cout<<"Enter the path of the file to be converted:"<<endl;
    cin>>dir;

    //Open input file stream
    ifstream filein(dir);

    //Check if file stream opened - if file exists and is a valid input
    if(!filein){
        cout<<"File not found or invalid input."<<endl;
        return -1;
    }

    //Check if the input file is empty
    if ( filein.peek() == std::ifstream::traits_type::eof() )
    {
        cout<<"File supplied is empty"<<endl;
        return -1;

    }

    //Create a counter as big as the number of lines in the input file
    int counter = linecounter(dir);

    //Open converted file fstream and create text file
    ofstream fileout;
    fileout.open ("converted.txt");

    //Create a string variable to store each individual ducky command/line to process in the for loop
    string command;

    //Create a trigger for the default delay command - if default delay command encounter, inject converted script with delay lines
    int delay = 0;

    //Insert this line in the beginning of the converted script to make sure that (on older systems) the first keystroke after a delay isn't missed
    fileout << "DigiKeyboard.sendKeyStroke(0);\n";

    //Create temporary string variables to use for string manipulation in the following for-loop
    string tmpstring;
    string tmpstring2;
    string fincom; //Use this variable to keep track of the last converted command to use in the repeat function
    string key; //Variable to be used in the keystroke conversion if clause underneath
    int replays = 0; //Replays counter for the REPLAY feature if clause underneath

    //Open a for loop to process each line/command of the input script
    for(int i=0; i<counter; i++){

        //Set command string equal to current line
        getline(filein, command);

        //Check for DEFAULT_DELAY or DEFAULTDELAY, set the delay variable and re-examine for-loop (Note: writing the delay commands happens at the end of the for-loop).
        tmpstring = tmpstring.assign(command,0,13);
        if((tmpstring.compare("DEFAULTDELAY ")==0) || (tmpstring.compare("DEFAULT_DELAY")==0)){
            command.erase(0,13);
            delay = stoi(command);
            continue;
        }

        //Convert duckyscript comments to Arduino IDE comments: Extract 3 first characters, if == REM, replace them with //, write to output and re-examine for-loop - this helps avoid placing unnecessary delay commands
        tmpstring = tmpstring.assign(command,0,3);
        if(tmpstring.compare("REM") == 0){
            command.replace(0,4,"//");
            fileout << command << "\n";
            continue;
        }

        //Convert duckyscript STRING commands to digispark print commands (Note, used F to store large strings to flash since the digispark has few RAM)
        tmpstring = tmpstring.assign(command,0,6);
        if(tmpstring.compare("STRING") == 0){
            command.replace(0,7,"DigiKeyboard.print(F(\"");
            command += "\"));";
            fincom = command; //See use of fincom above
            fileout << command << "\n";
            command = ""; //Empty the string so it won't trigger the keystroke processor
        }

        //Convert DELAY command (Not DEFAULTDELAY)
        tmpstring = tmpstring.assign(command,0,5);
        if(tmpstring.compare("DELAY") == 0){
            command.erase(0,6);
            fincom = "DigiKeyboard.delay(" + command + ");";
            fileout << fincom << "\n";
            command = ""; //command variable is set to null to bypass keystroke processor but still access default delay
        }

        //REPLAY feature (Note: at the end, command variable is set to null to bypass keystroke processor but still access default delay)
        tmpstring = tmpstring.assign(command,0,5);
        if(tmpstring.compare("REPLAY") == 0){
            command.erase(0,6);
            replays = stoi(command);
            for(int j=0; j < replays; j++){
                fileout << fincom << "\n";
            }
            command = "";
        }

        //Convert keystroke commands by calling the string processor function
        if(!command.empty()){
            key = command.substr(0, command.find(' '));
            tmpstring = "DigiKeyboard.sendKeyStroke(" + stringprocessor(key);
            command.erase(0, command.find(' ')+1);
            if(!command.empty()){
                tmpstring = tmpstring + ",";
                tmpstring = tmpstring + stringprocessor(command);
            }
            tmpstring = tmpstring + ");";
            fincom = tmpstring;
            fileout << fincom << "\n";
        }

        //If default delay trigger is activated, inject output file with a delay command
        if(delay!=0){
            fileout << "DigiKeyboard.delay(" << delay << ");\n";
        }
    }

    //Ask if user wants to execute the script just once - Use the counter variable instead of initialising a new one since counter won't be used anymore.
    cout << "Script has been converted successfully. Do you want the DigiSpark to execute the script once or loop infinitely? Select 0 for infinity and 1 for a single execution." << endl;
    cout << "[0/1]:";
    cin >> counter;

    if(counter){
        fileout << "exit();";
    }

    //Close converted script txt fstream
    fileout.close();
    return 0;
}
<commit_msg>Fixed visual bug with ascii art<commit_after>#include <iostream>
#include <fstream>
#include <string>

using namespace std;

//Function to count the lines of the script to be converted
int linecounter(string dir){
    int counter = 0;

    string line;

    //Create new file stream to file to be converted
    ifstream file(dir);

    while (getline(file, line)){
        counter++;}

    return counter;
}

//Accepts a string and returns the value of the key(s) in digispark language
//Some of the keys are encoded using their usage IDs. Refer to http://www.usb.org/developers/hidpage/Hut1_12v2.pdf  (Page 53-59)
string stringprocessor(string key){

    if((key == "A") || (key == "a")){
        key = "KEY_A";
        return key;
    }

    else if((key == "B") || (key == "b")){
        key = "KEY_B";
        return key;
    }

    else if((key == "C") || (key == "c")){
        key = "KEY_C";
        return key;
    }

    else if((key == "D") || (key == "d")){
        key = "KEY_D";
        return key;
    }

    else if((key == "E") || (key == "e")){
        key = "KEY_E";
        return key;
    }

    else if((key == "F") || (key == "f")){
        key = "KEY_F";
        return key;
    }

    else if((key == "G") || (key == "g")){
        key = "KEY_G";
        return key;
    }

    else if((key == "H") || (key == "h")){
        key = "KEY_H";
        return key;
    }

    else if((key == "I") || (key == "i")){
        key = "KEY_I";
        return key;
    }

    else if((key == "J") || (key == "j")){
        key = "KEY_J";
        return key;
    }

    else if((key == "K") || (key == "k")){
        key = "KEY_K";
        return key;
    }

    else if((key == "L") || (key == "l")){
        key = "KEY_L";
        return key;
    }

    else if((key == "M") || (key == "m")){
        key = "KEY_M";
        return key;
    }

    else if((key == "N") || (key == "n")){
        key = "KEY_N";
        return key;
    }

    else if((key == "O") || (key == "o")){
        key = "KEY_O";
        return key;
    }

    else if((key == "P") || (key == "p")){
        key = "KEY_P";
        return key;
    }

    else if((key == "Q") || (key == "q")){
        key = "KEY_Q";
        return key;
    }

    else if((key == "R") || (key == "r")){
        key = "KEY_R";
        return key;
    }

    else if((key == "S") || (key == "s")){
        key = "KEY_S";
        return key;
    }

    else if((key == "T") || (key == "t")){
        key = "KEY_T";
        return key;
    }

    else if((key == "U") || (key == "u")){
        key = "KEY_U";
        return key;
    }

    else if((key == "V") || (key == "v")){
        key = "KEY_V";
        return key;
    }

    else if((key == "W") || (key == "w")){
        key = "KEY_W";
        return key;
    }

    else if((key == "X") || (key == "x")){
        key = "KEY_X";
        return key;
    }

    else if((key == "Y") || (key == "y")){
        key = "KEY_Y";
        return key;
    }

    else if((key == "Z") || (key == "z")){
        key = "KEY_Z";
        return key;
    }

    else if(key=="1"){
        key = "KEY_1";
        return key;
    }

    else if(key=="2"){
        key = "KEY_2";
        return key;
    }

    else if(key=="3"){
        key = "KEY_3";
        return key;
    }

    else if(key=="4"){
        key = "KEY_4";
        return key;
    }

    else if(key=="5"){
        key = "KEY_5";
        return key;
    }

    else if(key=="6"){
        key = "KEY_6";
        return key;
    }

    else if(key=="7"){
        key = "KEY_7";
        return key;
    }

    else if(key=="8"){
        key = "KEY_8";
        return key;
    }

    else if(key=="9"){
        key = "KEY_9";
        return key;
    }

    else if(key=="0"){
        key = "KEY_0";
        return key;
    }

    else if(key=="ENTER"){
        key = "KEY_ENTER";
        return key;
    }

    else if(key=="F1"){
        key = "KEY_F1";
        return key;
    }

    else if(key=="F2"){
        key = "KEY_F2";
        return key;
    }

    else if(key=="F3"){
        key = "KEY_F3";
        return key;
    }

    else if(key=="F4"){
        key = "KEY_F4";
        return key;
    }

    else if(key=="F5"){
        key = "KEY_F5";
        return key;
    }

    else if(key=="F6"){
        key = "KEY_F6";
        return key;
    }

    else if(key=="F7"){
        key = "KEY_F7";
        return key;
    }

    else if(key=="F8"){
        key = "KEY_F8";
        return key;
    }

    else if(key=="F9"){
        key = "KEY_F9";
        return key;
    }

    else if(key=="F10"){
        key = "KEY_F10";
        return key;
    }

    else if(key=="F11"){
        key = "KEY_F11";
        return key;
    }

    else if(key=="F12"){
        key = "KEY_F12";
        return key;
    }

    else if((key=="GUI") || (key=="WINDOWS")){
        key = "0, MOD_GUI_LEFT"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="APP") || (key=="MENU")){
        key = "101"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if(key=="SHIFT"){
        key = "MOD_SHIFT_LEFT";
        return key;
    }

    else if(key=="ALT"){
        key = "MOD_ALT_LEFT";
        return key;
    }

    else if((key=="CONTROL") || (key=="CTRL")){
        key = "MOD_CONTROL_LEFT"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="DOWNARROW") || (key=="DOWN")){
        key = "84"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="UPARROW") || (key=="UP")){
        key = "83"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="LEFTARROW") || (key=="LEFT")){
        key = "79"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="RIGHTARROW") || (key=="RIGHT")){
        key = "89"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if((key=="BREAK") || (key=="PAUSE")){
        key = "126"; //Doesn't work without the 0, for some reason
        return key;
    }

    else if(key=="CAPSLOCK"){
        key = "30";
        return key;
    }

    else if((key=="ESC") || (key=="ESCAPE")){
        key = "110";
        return key;
    }

    else if(key=="DELETE"){
        key = "15";
        return key;
    }

    else if(key=="END"){
        key = "81";
        return key;
    }

    else if(key=="HOME"){
        key = "80";
        return key;
    }

    else if(key=="NUMLOCK"){
        key = "90";
        return key;
    }

    else if(key=="PAGEUP"){
        key = "85";
        return key;
    }

    else if(key=="PAGEDOWN"){
        key = "86";
        return key;
    }

    else if(key=="PRINTSCREEN"){
        key = "124";
        return key;
    }

    else if(key=="SCROLLLOCK"){
        key = "125";
        return key;
    }

    else if(key=="SPACE"){
        key = "61";
        return key;
    }

    else if(key=="TAB"){
        key = "16";
        return key;
    }
}

int main(){

    //Eye-candy
    cout<<"  _      _      _"<<endl;
    cout<<">(.)__ <(.)__ =(.)__"<<endl;
    cout<<" (___/  (___/  (___/"<<endl;
    cout<<endl;
    cout<<endl;
    cout<<"Welcome to digiQuack, the easy DuckyScript to Digispark payload converter!"<<endl;

    //Ask user to enter path to file to be converted
    string dir;
    cout<<"Enter the path of the file to be converted:"<<endl;
    cin>>dir;

    //Open input file stream
    ifstream filein(dir);

    //Check if file stream opened - if file exists and is a valid input
    if(!filein){
        cout<<"File not found or invalid input."<<endl;
        return -1;
    }

    //Check if the input file is empty
    if ( filein.peek() == std::ifstream::traits_type::eof() )
    {
        cout<<"File supplied is empty"<<endl;
        return -1;

    }

    //Create a counter as big as the number of lines in the input file
    int counter = linecounter(dir);

    //Open converted file fstream and create text file
    ofstream fileout;
    fileout.open ("converted.txt");

    //Create a string variable to store each individual ducky command/line to process in the for loop
    string command;

    //Create a trigger for the default delay command - if default delay command encounter, inject converted script with delay lines
    int delay = 0;

    //Insert this line in the beginning of the converted script to make sure that (on older systems) the first keystroke after a delay isn't missed
    fileout << "DigiKeyboard.sendKeyStroke(0);\n";

    //Create temporary string variables to use for string manipulation in the following for-loop
    string tmpstring;
    string tmpstring2;
    string fincom; //Use this variable to keep track of the last converted command to use in the repeat function
    string key; //Variable to be used in the keystroke conversion if clause underneath
    int replays = 0; //Replays counter for the REPLAY feature if clause underneath

    //Open a for loop to process each line/command of the input script
    for(int i=0; i<counter; i++){

        //Set command string equal to current line
        getline(filein, command);

        //Check for DEFAULT_DELAY or DEFAULTDELAY, set the delay variable and re-examine for-loop (Note: writing the delay commands happens at the end of the for-loop).
        tmpstring = tmpstring.assign(command,0,13);
        if((tmpstring.compare("DEFAULTDELAY ")==0) || (tmpstring.compare("DEFAULT_DELAY")==0)){
            command.erase(0,13);
            delay = stoi(command);
            continue;
        }

        //Convert duckyscript comments to Arduino IDE comments: Extract 3 first characters, if == REM, replace them with //, write to output and re-examine for-loop - this helps avoid placing unnecessary delay commands
        tmpstring = tmpstring.assign(command,0,3);
        if(tmpstring.compare("REM") == 0){
            command.replace(0,4,"//");
            fileout << command << "\n";
            continue;
        }

        //Convert duckyscript STRING commands to digispark print commands (Note, used F to store large strings to flash since the digispark has few RAM)
        tmpstring = tmpstring.assign(command,0,6);
        if(tmpstring.compare("STRING") == 0){
            command.replace(0,7,"DigiKeyboard.print(F(\"");
            command += "\"));";
            fincom = command; //See use of fincom above
            fileout << command << "\n";
            command = ""; //Empty the string so it won't trigger the keystroke processor
        }

        //Convert DELAY command (Not DEFAULTDELAY)
        tmpstring = tmpstring.assign(command,0,5);
        if(tmpstring.compare("DELAY") == 0){
            command.erase(0,6);
            fincom = "DigiKeyboard.delay(" + command + ");";
            fileout << fincom << "\n";
            command = ""; //command variable is set to null to bypass keystroke processor but still access default delay
        }

        //REPLAY feature (Note: at the end, command variable is set to null to bypass keystroke processor but still access default delay)
        tmpstring = tmpstring.assign(command,0,5);
        if(tmpstring.compare("REPLAY") == 0){
            command.erase(0,6);
            replays = stoi(command);
            for(int j=0; j < replays; j++){
                fileout << fincom << "\n";
            }
            command = "";
        }

        //Convert keystroke commands by calling the string processor function
        if(!command.empty()){
            key = command.substr(0, command.find(' '));
            tmpstring = "DigiKeyboard.sendKeyStroke(" + stringprocessor(key);
            command.erase(0, command.find(' ')+1);
            if(!command.empty()){
                tmpstring = tmpstring + ",";
                tmpstring = tmpstring + stringprocessor(command);
            }
            tmpstring = tmpstring + ");";
            fincom = tmpstring;
            fileout << fincom << "\n";
        }

        //If default delay trigger is activated, inject output file with a delay command
        if(delay!=0){
            fileout << "DigiKeyboard.delay(" << delay << ");\n";
        }
    }

    //Ask if user wants to execute the script just once - Use the counter variable instead of initialising a new one since counter won't be used anymore.
    cout << "Script has been converted successfully. Do you want the DigiSpark to execute the script once or loop infinitely? Select 0 for infinity and 1 for a single execution." << endl;
    cout << "[0/1]:";
    cin >> counter;

    if(counter){
        fileout << "exit();";
    }

    //Close converted script txt fstream
    fileout.close();
    return 0;
}
<|endoftext|>


<commit_before>#ifndef _SWITCHBACK_HPP_
#define _SWITCHBACK_HPP_

#include <vector>

#include <boost/array.hpp>
#include <boost/none.hpp>
#include <boost/optional.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/unordered_map.hpp>
#include <boost/utility.hpp>

#include "search/BucketPriorityQueue.hpp"
#include "search/Constants.hpp"
#include "util/PointerOps.hpp"

template <
  class Domain,
  class Node
  >
class Switchback : boost::noncopyable
{
private:
  typedef typename Node::Cost Cost;
  typedef typename Node::State State;

  typedef BucketPriorityQueue<Node> Open;
  typedef boost::optional<typename Open::ItemPointer> MaybeItemPointer;

  typedef boost::unordered_map<
    Node *,
    MaybeItemPointer,
    PointerHash<Node>,
    PointerEq<Node>,
    boost::fast_pool_allocator< std::pair<Node * const, MaybeItemPointer> >
    > Closed;

  typedef typename Closed::iterator ClosedIterator;
  typedef typename Closed::const_iterator ClosedConstIterator;

private:
  const static unsigned hierarchy_height = Domain::num_abstraction_levels + 1;

  const Node *goal;
  bool searched;

  Domain &domain;

  boost::array<unsigned, hierarchy_height> num_expanded;
  boost::array<unsigned, hierarchy_height> num_generated;

  boost::array<Open, hierarchy_height> open;
  Closed closed;

  boost::array<State, hierarchy_height> abstract_goals;

public:
  Switchback(Domain &domain)
    : goal(NULL)
    , searched(false)
    , domain(domain)
    , num_expanded()
    , num_generated()
    , open()
    , closed(INITIAL_CLOSED_SET_SIZE)
    , abstract_goals()
  {
    num_expanded.assign(0);
    num_generated.assign(0);
    initialize();
  }

  ~Switchback()
  {
  }

  void search()
  {
    if (searched)
      return;
    searched = true;

    goal = resume_search(0, domain.get_goal_state());
  }

  const Node * get_goal() const
  {
    std::cerr << "final open/closed sizes:" << std::endl;
    dump_open_sizes(std::cerr);
    dump_closed_sizes(std::cerr);

    return goal;
  }

  const Domain & get_domain() const
  {
    return domain;
  }

  unsigned get_num_generated() const
  {
    unsigned sum = 0;
    for (unsigned i = 0; i < hierarchy_height; i += 1)
      sum += num_generated[i];

    return sum;
  }

  unsigned get_num_generated(const unsigned level) const
  {
    return num_generated[level];
  }

  unsigned get_num_expanded() const
  {
    unsigned sum = 0;
    for (unsigned i = 0; i < hierarchy_height; i += 1)
      sum += num_expanded[i];

    return sum;
  }

  unsigned get_num_expanded(const unsigned level) const
  {
    return num_expanded[level];
  }

private:
  Cost heuristic(const unsigned level, const State &goal_state)
  {
    assert(domain.is_valid_level(level));

    if (goal_state == abstract_goals[level])
      return 0;

    const Cost epsilon = domain.get_epsilon(goal_state);

    if (level == Domain::num_abstraction_levels)
      return epsilon;

    // Need to create a dummy goal node to look up in the hash table.
    // This smells of bad design!
    const unsigned next_level = level + 1;
    const State abstract_goal_state = domain.abstract(next_level, goal_state);
    Node abstract_goal_node(abstract_goal_state, 0, 0);

    ClosedIterator closed_it = closed.find(&abstract_goal_node);
    if (closed_it != closed.end() && !closed_it->second) {
      return std::max(closed_it->first->get_g(), epsilon);
    }

    Node *result = resume_search(next_level, abstract_goal_state);
    if (result == NULL) {
      std::cerr << "whoops, infinite heuristic estimate!" << std::endl;
      assert(false);  // for the domains I am running on, there should
                      // never be an infinite heuristic estimate.
    }
    assert(closed.find(&abstract_goal_node) != closed.end());
    assert(!closed.find(&abstract_goal_node)->second);

    return std::max(result->get_g(), epsilon);
  }

  Node * resume_search(const unsigned level, const State &goal_state)
  {
    assert(domain.is_valid_level(level));

    // Dummy goal node, for hash table lookup.
    Node goal_node(goal_state, 0, 0);
    ClosedIterator closed_it = closed.find(&goal_node);

    if (closed_it != closed.end() &&!closed_it->second)
      return closed_it->first;

    std::vector<Node *> children;

    // A*-ish code ahead
    while (!open[level].empty()) {
#ifdef OUTPUT_SEARCH_PROGRESS
      if (get_num_expanded() % 1000000 == 0) {
        std::cerr << get_num_expanded() << " total nodes expanded" << std::endl
                  << get_num_generated() << " total nodes generated" << std::endl;
        dump_open_sizes(std::cerr);
        dump_closed_sizes(std::cerr);
      }
#endif

      Node *n = open[level].top();
      assert(closed.find(n) != closed.end());
      assert(closed.find(n)->second);
      assert(open[level].valid_item_pointer(*closed.find(n)->second));
      open[level].pop();

      closed[n] = boost::none;

      if (level % 2 == 0)
        domain.compute_successors(*n, children);
      else
        domain.compute_predecessors(*n, children);
      num_expanded[level] += 1;
      num_generated[level] += children.size();

      for (unsigned child_idx = 0; child_idx < children.size(); child_idx += 1) {
        process_child(level, children[child_idx]);
      }

      if (n->get_state() == goal_state)
        return n;
    } /* end while */

    return NULL;
  }

  void process_child(const unsigned level, Node *child)
  {
    assert(open[level].size() <= closed.size());

    child->set_h(heuristic(level, child->get_state()));

    ClosedIterator closed_it = closed.find(child);
    if (closed_it == closed.end()) {
      // The child has not been generated before.
      closed[child] = open[level].push(child);
    }
    else if (closed_it->second && child->get_f() < closed_it->first->get_f()) {
      // A worse version of the child is in the open list.
      open[level].erase(*closed_it->second);  // knock out the old
                                              // one from the open
                                              // list

      domain.free_node(closed_it->first);     // free the old,
                                              // worse copy
      closed.erase(closed_it);

      closed[child] = open[level].push(child);  // insert better version of child
    }
    else {
      // The child has either already been expanded, or is worse
      // than the version in the open list.
      domain.free_node(child);
    }
  }

  void initialize()
  {
    for (unsigned level = 0; level <= Domain::num_abstraction_levels; level += 1) {
      num_generated[level] += 1;
      State start = level % 2 == 0
                      ? domain.get_start_state()
                      : domain.get_goal_state();
      State goal = level % 2 == 0
                      ? domain.get_goal_state()
                      : domain.get_start_state();
      Node *start_node = domain.create_node(domain.abstract(level, start),
                                            0,
                                            0,
                                            NULL);
      closed[start_node] = open[level].push(start_node);
      abstract_goals[level] = goal;
    }
  }

  void dump_open_sizes(std::ostream &o) const
  {
    o << "open sizes: " << std::endl;
    for (unsigned level = 0; level < hierarchy_height; level += 1)
      o << "  " << level << ": " << open[level].size() << std::endl;
  }

  void dump_closed_sizes(std::ostream &o) const
  {
    o << "closed size: " << closed.size() << std::endl;
  }
};

#endif /* !_SWITCHBACK_HPP_ */
<commit_msg>Cleanup code in Switchback destructor.<commit_after>#ifndef _SWITCHBACK_HPP_
#define _SWITCHBACK_HPP_

#include <vector>

#include <boost/array.hpp>
#include <boost/none.hpp>
#include <boost/optional.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/unordered_map.hpp>
#include <boost/utility.hpp>

#include "search/BucketPriorityQueue.hpp"
#include "search/Constants.hpp"
#include "util/PointerOps.hpp"

template <
  class Domain,
  class Node
  >
class Switchback : boost::noncopyable
{
private:
  typedef typename Node::Cost Cost;
  typedef typename Node::State State;

  typedef BucketPriorityQueue<Node> Open;
  typedef boost::optional<typename Open::ItemPointer> MaybeItemPointer;

  typedef boost::unordered_map<
    Node *,
    MaybeItemPointer,
    PointerHash<Node>,
    PointerEq<Node>,
    boost::fast_pool_allocator< std::pair<Node * const, MaybeItemPointer> >
    > Closed;

  typedef typename Closed::iterator ClosedIterator;
  typedef typename Closed::const_iterator ClosedConstIterator;

private:
  const static unsigned hierarchy_height = Domain::num_abstraction_levels + 1;

  const Node *goal;
  bool searched;

  Domain &domain;

  boost::array<unsigned, hierarchy_height> num_expanded;
  boost::array<unsigned, hierarchy_height> num_generated;

  boost::array<Open, hierarchy_height> open;
  Closed closed;

  boost::array<State, hierarchy_height> abstract_goals;

public:
  Switchback(Domain &domain)
    : goal(NULL)
    , searched(false)
    , domain(domain)
    , num_expanded()
    , num_generated()
    , open()
    , closed(INITIAL_CLOSED_SET_SIZE)
    , abstract_goals()
  {
    num_expanded.assign(0);
    num_generated.assign(0);
    initialize();
  }

  ~Switchback()
  {
    for (ClosedIterator closed_it = closed.begin();
         closed_it != closed.end();
         ++closed_it) {
      domain.free_node(closed_it->first);
    }
  }

  void search()
  {
    if (searched)
      return;
    searched = true;

    goal = resume_search(0, domain.get_goal_state());
  }

  const Node * get_goal() const
  {
    std::cerr << "final open/closed sizes:" << std::endl;
    dump_open_sizes(std::cerr);
    dump_closed_sizes(std::cerr);

    return goal;
  }

  const Domain & get_domain() const
  {
    return domain;
  }

  unsigned get_num_generated() const
  {
    unsigned sum = 0;
    for (unsigned i = 0; i < hierarchy_height; i += 1)
      sum += num_generated[i];

    return sum;
  }

  unsigned get_num_generated(const unsigned level) const
  {
    return num_generated[level];
  }

  unsigned get_num_expanded() const
  {
    unsigned sum = 0;
    for (unsigned i = 0; i < hierarchy_height; i += 1)
      sum += num_expanded[i];

    return sum;
  }

  unsigned get_num_expanded(const unsigned level) const
  {
    return num_expanded[level];
  }

private:
  Cost heuristic(const unsigned level, const State &goal_state)
  {
    assert(domain.is_valid_level(level));

    if (goal_state == abstract_goals[level])
      return 0;

    const Cost epsilon = domain.get_epsilon(goal_state);

    if (level == Domain::num_abstraction_levels)
      return epsilon;

    // Need to create a dummy goal node to look up in the hash table.
    // This smells of bad design!
    const unsigned next_level = level + 1;
    const State abstract_goal_state = domain.abstract(next_level, goal_state);
    Node abstract_goal_node(abstract_goal_state, 0, 0);

    ClosedIterator closed_it = closed.find(&abstract_goal_node);
    if (closed_it != closed.end() && !closed_it->second) {
      return std::max(closed_it->first->get_g(), epsilon);
    }

    Node *result = resume_search(next_level, abstract_goal_state);
    if (result == NULL) {
      std::cerr << "whoops, infinite heuristic estimate!" << std::endl;
      assert(false);  // for the domains I am running on, there should
                      // never be an infinite heuristic estimate.
    }
    assert(closed.find(&abstract_goal_node) != closed.end());
    assert(!closed.find(&abstract_goal_node)->second);

    return std::max(result->get_g(), epsilon);
  }

  Node * resume_search(const unsigned level, const State &goal_state)
  {
    assert(domain.is_valid_level(level));

    // Dummy goal node, for hash table lookup.
    Node goal_node(goal_state, 0, 0);
    ClosedIterator closed_it = closed.find(&goal_node);

    if (closed_it != closed.end() &&!closed_it->second)
      return closed_it->first;

    std::vector<Node *> children;

    // A*-ish code ahead
    while (!open[level].empty()) {
#ifdef OUTPUT_SEARCH_PROGRESS
      if (get_num_expanded() % 1000000 == 0) {
        std::cerr << get_num_expanded() << " total nodes expanded" << std::endl
                  << get_num_generated() << " total nodes generated" << std::endl;
        dump_open_sizes(std::cerr);
        dump_closed_sizes(std::cerr);
      }
#endif

      Node *n = open[level].top();
      assert(closed.find(n) != closed.end());
      assert(closed.find(n)->second);
      assert(open[level].valid_item_pointer(*closed.find(n)->second));
      open[level].pop();

      closed[n] = boost::none;

      if (level % 2 == 0)
        domain.compute_successors(*n, children);
      else
        domain.compute_predecessors(*n, children);
      num_expanded[level] += 1;
      num_generated[level] += children.size();

      for (unsigned child_idx = 0; child_idx < children.size(); child_idx += 1) {
        process_child(level, children[child_idx]);
      }

      if (n->get_state() == goal_state)
        return n;
    } /* end while */

    return NULL;
  }

  void process_child(const unsigned level, Node *child)
  {
    assert(open[level].size() <= closed.size());

    child->set_h(heuristic(level, child->get_state()));

    ClosedIterator closed_it = closed.find(child);
    if (closed_it == closed.end()) {
      // The child has not been generated before.
      closed[child] = open[level].push(child);
    }
    else if (closed_it->second && child->get_f() < closed_it->first->get_f()) {
      // A worse version of the child is in the open list.
      open[level].erase(*closed_it->second);  // knock out the old
                                              // one from the open
                                              // list

      domain.free_node(closed_it->first);     // free the old,
                                              // worse copy
      closed.erase(closed_it);

      closed[child] = open[level].push(child);  // insert better version of child
    }
    else {
      // The child has either already been expanded, or is worse
      // than the version in the open list.
      domain.free_node(child);
    }
  }

  void initialize()
  {
    for (unsigned level = 0; level <= Domain::num_abstraction_levels; level += 1) {
      num_generated[level] += 1;
      State start = level % 2 == 0
                      ? domain.get_start_state()
                      : domain.get_goal_state();
      State goal = level % 2 == 0
                      ? domain.get_goal_state()
                      : domain.get_start_state();
      Node *start_node = domain.create_node(domain.abstract(level, start),
                                            0,
                                            0,
                                            NULL);
      closed[start_node] = open[level].push(start_node);
      abstract_goals[level] = goal;
    }
  }

  void dump_open_sizes(std::ostream &o) const
  {
    o << "open sizes: " << std::endl;
    for (unsigned level = 0; level < hierarchy_height; level += 1)
      o << "  " << level << ": " << open[level].size() << std::endl;
  }

  void dump_closed_sizes(std::ostream &o) const
  {
    o << "closed size: " << closed.size() << std::endl;
  }
};

#endif /* !_SWITCHBACK_HPP_ */
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "dlgpreferences.h"
#include "dlglistindexedfiles.h"
#include "simplesearchgui.h"
#include "searchtabs.h"
#include "socketclient.h"
#include <QtGui/QListWidget>
#include <QtGui/QListWidgetItem>
#include <QtGui/QLineEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QStackedWidget>
#include <QtGui/QLabel>
#include <QtGui/QPushButton>
#include <QtGui/QFileDialog>
#include <QtGui/QComboBox>
#include <QtGui/QMenu>
#include <QtGui/QMenuBar>
#include <QtGui/QAction>
#include <QtCore/QString>
#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QTimer>
#include <string>
#include <map>
#include <vector>
using namespace std;

SimpleSearchGui::SimpleSearchGui (QWidget * parent, Qt::WFlags flags)
    : QMainWindow (parent, flags)
{
    mainview = new QStackedWidget();

    QWidget* statuswidget = new QWidget();
    QVBoxLayout *statuslayout = new QVBoxLayout;
    statusview = new QLabel();
    statusview->setAlignment(Qt::AlignTop);
    statusview->setMargin(25);
    indexing = false;
    running = false;
    starting = true;
    indexeddirs = new QListWidget();
    adddir = new QPushButton("add directory");
    removedir = new QPushButton("remove directory");
    toggleindexing = new QPushButton("start indexing");
    toggledaemon = new QPushButton("stop daemon");
    statuslayout->addWidget(statusview);
    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->addWidget(toggledaemon);
    hlayout->addWidget(toggleindexing);
    statuslayout->addLayout(hlayout);
/*    vector<string> backends = ClientInterface::getBackEnds();
    if (backends.size() > 1) {
        backendsList = new QComboBox();
        for (uint i = 0; i< backends.size(); ++i) {
            QString backend = backends[i].c_str();
            backendsList->insertItem(i, backend);
        }
        statuslayout->addWidget(backendsList);
    } else {*/
        backendsList = 0;
//    }
    statuslayout->addWidget(indexeddirs);
    hlayout = new QHBoxLayout;
    hlayout->addWidget(adddir);
    hlayout->addWidget(removedir);
    statuslayout->addLayout(hlayout);
    statuswidget->setLayout(statuslayout);

    tabs = new SearchTabs();
    tabs->addTab("kde", "kde");
    tabs->addTab("msg", "mimetype:message/*");
    tabs->addTab("irc", "path:*konversation*log");
    tabs->addTab("mail", "mimetype:text/x-mail");
    tabs->addTab("audio", "mimetype:audio/*");
    tabs->addTab("other",
        "-kde -mimetype:message/* -mimetype:text/x-mail -mimetype:audio/*");
    tabs->addTab("all", "");
    mainview->addWidget(tabs);
    mainview->addWidget(statuswidget);
    asyncstrigi.updateStatus();
    mainview->setCurrentIndex(1);

    queryfield = new QLineEdit();
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(mainview);
    layout->addWidget(queryfield);

    centralview = new QWidget();
    centralview->setLayout(layout);
    setCentralWidget(centralview);

    createActions();
    createMenus();

    connect(queryfield, SIGNAL(textChanged(const QString&)),
        this, SLOT(query(const QString&)));
    connect(toggleindexing, SIGNAL(clicked()),
        this, SLOT(toggleIndexing()));
    connect(toggledaemon, SIGNAL(clicked()),
        this, SLOT(toggleDaemon()));
    connect(adddir, SIGNAL(clicked()),
        this, SLOT(addDirectory()));
    connect(removedir, SIGNAL(clicked()),
        this, SLOT(removeDirectory()));
    queryfield->setFocus(Qt::ActiveWindowFocusReason);

    socketfile = getenv("HOME");
    socketfile += "/.strigi/socket";

    connect (&asyncstrigi,SIGNAL(statusUpdated(const QMap<QString, QString>& )),
        this, SLOT(updateStatus(const QMap<QString, QString>& )));
//    connect (&strigi, SIGNAL (socketError(Qt4StrigiClient::Mode)), this, SLOT (socketError(Qt4StrigiClient::Mode)));

    QTimer *timer = new QTimer(this);
//    connect(timer, SIGNAL(timeout()), &asyncstrigi, SLOT(updateStatus()));
//    timer->start(2000);
    asyncstrigi.updateStatus();
}
void
SimpleSearchGui::createMenus() {
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(fileExitAct);

    editMenu = menuBar()->addMenu(tr("&Edit"));
    editMenu->addAction(editPreferenceAct);
    editMenu->addAction(editListIndexedFilesAct);
}
void
SimpleSearchGui::createActions() {
    fileExitAct = new QAction(tr("&Exit"), this);
    fileExitAct->setShortcut(tr("Ctrl+Q"));
    fileExitAct->setStatusTip(tr("Quit the program"));
    connect(fileExitAct, SIGNAL(triggered()), this, SLOT(close()));

    editPreferenceAct = new QAction(tr("Edit Preferences"), this);
    editPreferenceAct->setStatusTip(tr("Edit program preferences"));
    connect(editPreferenceAct, SIGNAL(triggered()), this, SLOT(editPreferences()));

    editListIndexedFilesAct = new QAction(tr("List indexed files"), this);
    editListIndexedFilesAct->setStatusTip(tr("Show files indexed by strigi"));
    connect(editListIndexedFilesAct, SIGNAL(triggered()), this, SLOT(editListIndexedFiles()));
}
void
SimpleSearchGui::query(const QString& item) {
    if (item.length()) {
        tabs->setQuery(item);
    }
    QString query = item.trimmed();
    if (query.length() == 0) {
        asyncstrigi.updateStatus();
        mainview->setCurrentIndex(1);
    } else {
        mainview->setCurrentIndex(0);
    }
}
void
SimpleSearchGui::updateStatus(const QMap<QString, QString>& s) {
    static bool first = true;
    static bool attemptedstart = false;
    if (!first && !statusview->isVisible()) return;
    first = false;
    QMap<QString, QString> status (s);
    if (status.size() == 0) {
        running = false;
        editListIndexedFilesAct->setEnabled(false);
        /*if (!attemptedstart) {
            status["Status"] = "Starting daemon";
            startDaemon();
            attemptedstart = true;
        } else {*/
            status["Status"] = "Daemon is not running";
        //}
    } else {
        attemptedstart = true;
        starting = false;
        running = true;
        editListIndexedFilesAct->setEnabled(true);
        if (indexeddirs->count() == 0) {
            updateDirectories();
        }
    }
    toggleindexing->setEnabled(running);
    adddir->setEnabled(running);
    removedir->setEnabled(running);
    queryfield->setEnabled(running);
    toggledaemon->setText((running)?"stop daemon":"start daemon");
    toggledaemon->setEnabled(true);
    if (backendsList) {
        backendsList->setEnabled(!running);
    }
    bool idxng = status["Status"] == "indexing";
    if (idxng != indexing) {
        indexing = idxng;
        toggleindexing->setText((indexing)?"stop indexing":"start indexing");
    }

    QMap<QString,QString>::const_iterator i;
    QString text;
    for (i = status.begin(); i != status.end(); ++i) {
        text += i.key();
        text += ":\t";
        text += i.value();
        text += '\n';
    }
    statusview->setText(text);
}
void
SimpleSearchGui::startDaemon() {
    toggledaemon->setEnabled(false);
    starting = true;
    // try to start the daemon
    QFileInfo exe = QCoreApplication::applicationDirPath()
    + "/../../daemon/strigidaemon";
    QStringList args;
    if (backendsList) {
        args += backendsList->currentText();
    }
    if (exe.exists()) {
        // start not installed version
        QProcess::startDetached(exe.absoluteFilePath(), args);
    } else {
        exe = QCoreApplication::applicationDirPath()+"/strigidaemon";
        if (exe.exists()) {
            QProcess::startDetached(exe.absoluteFilePath(), args);
        } else {
            // start installed version
            QProcess::startDetached("strigidaemon");
        }
    }
}
void
SimpleSearchGui::toggleDaemon() {
    if (running) {
        SocketClient client;
        client.setSocketName(socketfile.c_str());
        client.stopDaemon();
        indexeddirs->clear();
    } else {
        startDaemon();
    }
}
void
SimpleSearchGui::toggleIndexing() {
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    if (indexing) {
        client.stopIndexing();
    } else {
        client.startIndexing();
    }
}
void
SimpleSearchGui::addDirectory() {
    // open file dialog
    QString dir = QFileDialog::getExistingDirectory (this);
    if (dir.size() <= 0) return;
    for (int i=0; i<indexeddirs->count(); ++i) {
        QString text = indexeddirs->item(i)->text();
        if (dir.startsWith(text)) {
            return;
        }
        if (text.startsWith(dir)) {
            indexeddirs->takeItem(i);
            i = 0;
        }
    }
    indexeddirs->addItem(dir);
    setDirectories();
}
void
SimpleSearchGui::removeDirectory() {
    int i = indexeddirs->currentRow();
    if (i == -1) return;
    indexeddirs->takeItem(i);
    setDirectories();
}
void
SimpleSearchGui::setDirectories() {
    set<string> s;
    for (int i=0; i<indexeddirs->count(); ++i) {
        QString text = indexeddirs->item(i)->text();
        s.insert((const char*)text.toUtf8());
    }
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    client.setIndexedDirectories(s);
    updateDirectories();
}
void
SimpleSearchGui::updateDirectories() {
    indexeddirs->clear();
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    set<string> s = client.getIndexedDirectories();
    indexeddirs->clear();
    set<string>::const_iterator i;
    for (i = s.begin(); i != s.end(); ++i) {
        QString dir(QString::fromUtf8(i->c_str()));
        indexeddirs->addItem(dir);
    }
}
void
SimpleSearchGui::editPreferences() {
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    multimap<int,string> rules = client.getFilteringRules();

    DlgPreferences* dlg = new DlgPreferences (running, &rules);
    dlg->exec();

    delete dlg;

    //update filtering rules
    client.setFilteringRules( rules);
}
void
SimpleSearchGui::editListIndexedFiles() {
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    set<string> files = client.getIndexedFiles();

    DlgListIndexedFiles dlg (files);
    dlg.exec();
}

<commit_msg>Reinstate the periodic status update. It too useful to remove.<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "dlgpreferences.h"
#include "dlglistindexedfiles.h"
#include "simplesearchgui.h"
#include "searchtabs.h"
#include "socketclient.h"
#include <QtGui/QListWidget>
#include <QtGui/QListWidgetItem>
#include <QtGui/QLineEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QStackedWidget>
#include <QtGui/QLabel>
#include <QtGui/QPushButton>
#include <QtGui/QFileDialog>
#include <QtGui/QComboBox>
#include <QtGui/QMenu>
#include <QtGui/QMenuBar>
#include <QtGui/QAction>
#include <QtCore/QString>
#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QTimer>
#include <string>
#include <map>
#include <vector>
using namespace std;

SimpleSearchGui::SimpleSearchGui (QWidget * parent, Qt::WFlags flags)
    : QMainWindow (parent, flags)
{
    mainview = new QStackedWidget();

    QWidget* statuswidget = new QWidget();
    QVBoxLayout *statuslayout = new QVBoxLayout;
    statusview = new QLabel();
    statusview->setAlignment(Qt::AlignTop);
    statusview->setMargin(25);
    indexing = false;
    running = false;
    starting = true;
    indexeddirs = new QListWidget();
    adddir = new QPushButton("add directory");
    removedir = new QPushButton("remove directory");
    toggleindexing = new QPushButton("start indexing");
    toggledaemon = new QPushButton("stop daemon");
    statuslayout->addWidget(statusview);
    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->addWidget(toggledaemon);
    hlayout->addWidget(toggleindexing);
    statuslayout->addLayout(hlayout);
/*    vector<string> backends = ClientInterface::getBackEnds();
    if (backends.size() > 1) {
        backendsList = new QComboBox();
        for (uint i = 0; i< backends.size(); ++i) {
            QString backend = backends[i].c_str();
            backendsList->insertItem(i, backend);
        }
        statuslayout->addWidget(backendsList);
    } else {*/
        backendsList = 0;
//    }
    statuslayout->addWidget(indexeddirs);
    hlayout = new QHBoxLayout;
    hlayout->addWidget(adddir);
    hlayout->addWidget(removedir);
    statuslayout->addLayout(hlayout);
    statuswidget->setLayout(statuslayout);

    tabs = new SearchTabs();
    tabs->addTab("kde", "kde");
    tabs->addTab("msg", "mimetype:message/*");
    tabs->addTab("irc", "path:*konversation*log");
    tabs->addTab("mail", "mimetype:text/x-mail");
    tabs->addTab("audio", "mimetype:audio/*");
    tabs->addTab("other",
        "-kde -mimetype:message/* -mimetype:text/x-mail -mimetype:audio/*");
    tabs->addTab("all", "");
    mainview->addWidget(tabs);
    mainview->addWidget(statuswidget);
    asyncstrigi.updateStatus();
    mainview->setCurrentIndex(1);

    queryfield = new QLineEdit();
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(mainview);
    layout->addWidget(queryfield);

    centralview = new QWidget();
    centralview->setLayout(layout);
    setCentralWidget(centralview);

    createActions();
    createMenus();

    connect(queryfield, SIGNAL(textChanged(const QString&)),
        this, SLOT(query(const QString&)));
    connect(toggleindexing, SIGNAL(clicked()),
        this, SLOT(toggleIndexing()));
    connect(toggledaemon, SIGNAL(clicked()),
        this, SLOT(toggleDaemon()));
    connect(adddir, SIGNAL(clicked()),
        this, SLOT(addDirectory()));
    connect(removedir, SIGNAL(clicked()),
        this, SLOT(removeDirectory()));
    queryfield->setFocus(Qt::ActiveWindowFocusReason);

    socketfile = getenv("HOME");
    socketfile += "/.strigi/socket";

    connect (&asyncstrigi,SIGNAL(statusUpdated(const QMap<QString, QString>& )),
        this, SLOT(updateStatus(const QMap<QString, QString>& )));
//    connect (&strigi, SIGNAL (socketError(Qt4StrigiClient::Mode)), this, SLOT (socketError(Qt4StrigiClient::Mode)));

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), &asyncstrigi, SLOT(updateStatus()));
    timer->start(2000);
    asyncstrigi.updateStatus();
}
void
SimpleSearchGui::createMenus() {
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(fileExitAct);

    editMenu = menuBar()->addMenu(tr("&Edit"));
    editMenu->addAction(editPreferenceAct);
    editMenu->addAction(editListIndexedFilesAct);
}
void
SimpleSearchGui::createActions() {
    fileExitAct = new QAction(tr("&Exit"), this);
    fileExitAct->setShortcut(tr("Ctrl+Q"));
    fileExitAct->setStatusTip(tr("Quit the program"));
    connect(fileExitAct, SIGNAL(triggered()), this, SLOT(close()));

    editPreferenceAct = new QAction(tr("Edit Preferences"), this);
    editPreferenceAct->setStatusTip(tr("Edit program preferences"));
    connect(editPreferenceAct, SIGNAL(triggered()), this, SLOT(editPreferences()));

    editListIndexedFilesAct = new QAction(tr("List indexed files"), this);
    editListIndexedFilesAct->setStatusTip(tr("Show files indexed by strigi"));
    connect(editListIndexedFilesAct, SIGNAL(triggered()), this, SLOT(editListIndexedFiles()));
}
void
SimpleSearchGui::query(const QString& item) {
    if (item.length()) {
        tabs->setQuery(item);
    }
    QString query = item.trimmed();
    if (query.length() == 0) {
        asyncstrigi.updateStatus();
        mainview->setCurrentIndex(1);
    } else {
        mainview->setCurrentIndex(0);
    }
}
void
SimpleSearchGui::updateStatus(const QMap<QString, QString>& s) {
    static bool first = true;
    static bool attemptedstart = false;
    if (!first && !statusview->isVisible()) return;
    first = false;
    QMap<QString, QString> status (s);
    if (status.size() == 0) {
        running = false;
        editListIndexedFilesAct->setEnabled(false);
        /*if (!attemptedstart) {
            status["Status"] = "Starting daemon";
            startDaemon();
            attemptedstart = true;
        } else {*/
            status["Status"] = "Daemon is not running";
        //}
    } else {
        attemptedstart = true;
        starting = false;
        running = true;
        editListIndexedFilesAct->setEnabled(true);
        if (indexeddirs->count() == 0) {
            updateDirectories();
        }
    }
    toggleindexing->setEnabled(running);
    adddir->setEnabled(running);
    removedir->setEnabled(running);
    queryfield->setEnabled(running);
    toggledaemon->setText((running)?"stop daemon":"start daemon");
    toggledaemon->setEnabled(true);
    if (backendsList) {
        backendsList->setEnabled(!running);
    }
    bool idxng = status["Status"] == "indexing";
    if (idxng != indexing) {
        indexing = idxng;
        toggleindexing->setText((indexing)?"stop indexing":"start indexing");
    }

    QMap<QString,QString>::const_iterator i;
    QString text;
    for (i = status.begin(); i != status.end(); ++i) {
        text += i.key();
        text += ":\t";
        text += i.value();
        text += '\n';
    }
    statusview->setText(text);
}
void
SimpleSearchGui::startDaemon() {
    toggledaemon->setEnabled(false);
    starting = true;
    // try to start the daemon
    QFileInfo exe = QCoreApplication::applicationDirPath()
    + "/../../daemon/strigidaemon";
    QStringList args;
    if (backendsList) {
        args += backendsList->currentText();
    }
    if (exe.exists()) {
        // start not installed version
        QProcess::startDetached(exe.absoluteFilePath(), args);
    } else {
        exe = QCoreApplication::applicationDirPath()+"/strigidaemon";
        if (exe.exists()) {
            QProcess::startDetached(exe.absoluteFilePath(), args);
        } else {
            // start installed version
            QProcess::startDetached("strigidaemon");
        }
    }
}
void
SimpleSearchGui::toggleDaemon() {
    if (running) {
        SocketClient client;
        client.setSocketName(socketfile.c_str());
        client.stopDaemon();
        indexeddirs->clear();
    } else {
        startDaemon();
    }
}
void
SimpleSearchGui::toggleIndexing() {
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    if (indexing) {
        client.stopIndexing();
    } else {
        client.startIndexing();
    }
}
void
SimpleSearchGui::addDirectory() {
    // open file dialog
    QString dir = QFileDialog::getExistingDirectory (this);
    if (dir.size() <= 0) return;
    for (int i=0; i<indexeddirs->count(); ++i) {
        QString text = indexeddirs->item(i)->text();
        if (dir.startsWith(text)) {
            return;
        }
        if (text.startsWith(dir)) {
            indexeddirs->takeItem(i);
            i = 0;
        }
    }
    indexeddirs->addItem(dir);
    setDirectories();
}
void
SimpleSearchGui::removeDirectory() {
    int i = indexeddirs->currentRow();
    if (i == -1) return;
    indexeddirs->takeItem(i);
    setDirectories();
}
void
SimpleSearchGui::setDirectories() {
    set<string> s;
    for (int i=0; i<indexeddirs->count(); ++i) {
        QString text = indexeddirs->item(i)->text();
        s.insert((const char*)text.toUtf8());
    }
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    client.setIndexedDirectories(s);
    updateDirectories();
}
void
SimpleSearchGui::updateDirectories() {
    indexeddirs->clear();
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    set<string> s = client.getIndexedDirectories();
    indexeddirs->clear();
    set<string>::const_iterator i;
    for (i = s.begin(); i != s.end(); ++i) {
        QString dir(QString::fromUtf8(i->c_str()));
        indexeddirs->addItem(dir);
    }
}
void
SimpleSearchGui::editPreferences() {
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    multimap<int,string> rules = client.getFilteringRules();

    DlgPreferences* dlg = new DlgPreferences (running, &rules);
    dlg->exec();

    delete dlg;

    //update filtering rules
    client.setFilteringRules( rules);
}
void
SimpleSearchGui::editListIndexedFiles() {
    SocketClient client;
    client.setSocketName(socketfile.c_str());
    set<string> files = client.getIndexedFiles();

    DlgListIndexedFiles dlg (files);
    dlg.exec();
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppPresence.h"
#include "QXmppUtils.h"
#include <QtDebug>
#include <QDomElement>
#include <QXmlStreamWriter>
#include "QXmppConstants.h"

QXmppPresence::QXmppPresence(QXmppPresence::Type type,
                             const QXmppPresence::Status& status)
    : QXmppStanza(), m_type(type), m_status(status)
{

}

QXmppPresence::~QXmppPresence()
{

}

QXmppPresence::Type QXmppPresence::type() const
{
    return m_type;
}

void QXmppPresence::setType(QXmppPresence::Type type)
{
    m_type = type;
}

const QXmppPresence::Status& QXmppPresence::status() const
{
    return m_status;
}

QXmppPresence::Status& QXmppPresence::status()
{
    return m_status;
}

void QXmppPresence::setStatus(const QXmppPresence::Status& status)
{
    m_status = status;
}

void QXmppPresence::parse(const QDomElement &element)
{
    QXmppStanza::parse(element);

    setTypeFromStr(element.attribute("type"));
    m_status.parse(element);

    QXmppElementList extensions;
    QDomElement xElement = element.firstChildElement();
    m_vCardUpdateType = VCardUpdateNone;
    while(!xElement.isNull())
    {
        // XEP-0153: vCard-Based Avatars
        if(xElement.namespaceURI() == ns_vcard_update)
        {
            QDomElement photoElement = xElement.firstChildElement("photo");
            if(!photoElement.isNull())
            {
                m_photoHash = QByteArray::fromHex(photoElement.text().toAscii());
                if(m_photoHash.isEmpty())
                    m_vCardUpdateType = PhotoNotAdvertized;
                else
                    m_vCardUpdateType = PhotoAdvertised;
            }
            else
            {
                m_photoHash = QByteArray();
                m_vCardUpdateType = PhotoNotReady;
            }
        }
        // XEP-0115: Entity Capabilities
        else if(xElement.tagName() == "c" && xElement.namespaceURI() == ns_capabilities)
        {
            m_capabilityNode = xElement.attribute("node");
            m_capabilityVer = QByteArray::fromBase64(xElement.attribute("ver").toAscii());
            m_capabilityHash = xElement.attribute("hash");
            m_capabilityExt = xElement.attribute("ext").split(" ", QString::SkipEmptyParts);
        }
        else if (xElement.tagName() == "error")
        {
        }
        else if (xElement.tagName() == "show")
        {
        }
        else if (xElement.tagName() == "status")
        {
        }
        else if (xElement.tagName() == "priority")
        {
        }
        else
        {
            // other extensions
            extensions << QXmppElement(xElement);
        }
        xElement = xElement.nextSiblingElement();
    }
    setExtensions(extensions);
}

void QXmppPresence::toXml(QXmlStreamWriter *xmlWriter) const
{
    xmlWriter->writeStartElement("presence");
    helperToXmlAddAttribute(xmlWriter,"xml:lang", lang());
    helperToXmlAddAttribute(xmlWriter,"id", id());
    helperToXmlAddAttribute(xmlWriter,"to", to());
    helperToXmlAddAttribute(xmlWriter,"from", from());
    helperToXmlAddAttribute(xmlWriter,"type", getTypeStr());
    m_status.toXml(xmlWriter);

    error().toXml(xmlWriter);

    // XEP-0153: vCard-Based Avatars
    if(m_vCardUpdateType != VCardUpdateNone)
    {
        xmlWriter->writeStartElement("x");
        helperToXmlAddAttribute(xmlWriter, "xmlns", ns_vcard_update);
        switch(m_vCardUpdateType)
        {
        case PhotoNotAdvertized:
            helperToXmlAddTextElement(xmlWriter, "photo", "");
            break;
        case PhotoAdvertised:
            helperToXmlAddTextElement(xmlWriter, "photo", m_photoHash.toHex());
            break;
        case PhotoNotReady:
            break;
        default:
            break;
        }
        xmlWriter->writeEndElement();
    }

    if(!m_capabilityNode.isEmpty() && !m_capabilityVer.isEmpty()
        && !m_capabilityHash.isEmpty())
    {
        xmlWriter->writeStartElement("c");
        helperToXmlAddAttribute(xmlWriter, "xmlns", ns_capabilities);
        helperToXmlAddAttribute(xmlWriter, "hash", m_capabilityHash);
        helperToXmlAddAttribute(xmlWriter, "node", m_capabilityNode);
        helperToXmlAddAttribute(xmlWriter, "ver", m_capabilityVer.toBase64());
        xmlWriter->writeEndElement();
    }

    foreach (const QXmppElement &extension, extensions())
        extension.toXml(xmlWriter);

    xmlWriter->writeEndElement();
}

QString QXmppPresence::getTypeStr() const
{
    QString text;
    switch(m_type)
    {
    case QXmppPresence::Error:
        text = "error";
        break;
    case QXmppPresence::Available:
        // no type-attribute if available
        text = "";
        break;
    case QXmppPresence::Unavailable:
        text = "unavailable";
        break;
    case QXmppPresence::Subscribe:
        text = "subscribe";
        break;
    case QXmppPresence::Subscribed:
        text = "subscribed";
        break;
    case QXmppPresence::Unsubscribe:
        text = "unsubscribe";
        break;
    case QXmppPresence::Unsubscribed:
        text = "unsubscribed";
        break;
    case QXmppPresence::Probe:
        text = "probe";
        break;
    default:
        qWarning("QXmppPresence::getTypeStr() invalid type %d", (int)m_type);
        break;
    }
    return text;
}

void QXmppPresence::setTypeFromStr(const QString& str)
{
    QXmppPresence::Type type;
    if(str == "error")
    {
        type = QXmppPresence::Error;
        setType(type);
        return;
    }
    else if(str == "unavailable")
    {
        type = QXmppPresence::Unavailable;
        setType(type);
        return;
    }
    else if(str == "subscribe")
    {
        type = QXmppPresence::Subscribe;
        setType(type);
        return;
    }
    else if(str == "subscribed")
    {
        type = QXmppPresence::Subscribed;
        setType(type);
        return;
    }
    else if(str == "unsubscribe")
    {
        type = QXmppPresence::Unsubscribe;
        setType(type);
        return;
    }
    else if(str == "unsubscribed")
    {
        type = QXmppPresence::Unsubscribed;
        setType(type);
        return;
    }
    else if(str == "probe")
    {
        type = QXmppPresence::Probe;
        setType(type);
        return;
    }
    else if(str == "")
    {
        type = QXmppPresence::Available;
        setType(type);
        return;
    }
    else
    {
        type = static_cast<QXmppPresence::Type>(-1);
        qWarning("QXmppPresence::setTypeFromStr() invalid input string type: %s",
                 qPrintable(str));
        setType(type);
        return;
    }
}

QXmppPresence::Status::Status(QXmppPresence::Status::Type type,
                             const QString statusText, int priority) :
                                m_type(type),
                                m_statusText(statusText), m_priority(priority)
{
}

QXmppPresence::Status::Type QXmppPresence::Status::type() const
{
    return m_type;
}

void QXmppPresence::Status::setType(QXmppPresence::Status::Type type)
{
    m_type = type;
}

void QXmppPresence::Status::setTypeFromStr(const QString& str)
{
    // there is no keyword for Offline

    QXmppPresence::Status::Type type;
    if(str == "")   // not type-attribute means online
    {
        type = QXmppPresence::Status::Online;
        setType(type);
        return;
    }
    else if(str == "away")
    {
        type = QXmppPresence::Status::Away;
        setType(type);
        return;
    }
    else if(str == "xa")
    {
        type = QXmppPresence::Status::XA;
        setType(type);
        return;
    }
    else if(str == "dnd")
    {
        type = QXmppPresence::Status::DND;
        setType(type);
        return;
    }
    else if(str == "chat")
    {
        type = QXmppPresence::Status::Chat;
        setType(type);
        return;
    }
    else
    {
        type = static_cast<QXmppPresence::Status::Type>(-1);
        qWarning("QXmppPresence::Status::setTypeFromStr() invalid input string type %s",
            qPrintable(str));
        setType(type);
    }
}

QString QXmppPresence::Status::getTypeStr() const
{
    QString text;
    switch(m_type)
    {
    case QXmppPresence::Status::Online:
        // no type-attribute if available
        text = "";
        break;
    case QXmppPresence::Status::Offline:
        text = "";
        break;
    case QXmppPresence::Status::Away:
        text = "away";
        break;
    case QXmppPresence::Status::XA:
        text = "xa";
        break;
    case QXmppPresence::Status::DND:
        text = "dnd";
        break;
    case QXmppPresence::Status::Chat:
        text = "chat";
        break;
    default:
        qWarning("QXmppPresence::Status::getTypeStr() invalid type %d",
                 (int)m_type);
        break;
    }
    return text;
}

QString QXmppPresence::Status::statusText() const
{
    return m_statusText;
}

void QXmppPresence::Status::setStatusText(const QString& str)
{
    m_statusText = str;
}

int QXmppPresence::Status::priority() const
{
    return m_priority;
}

void QXmppPresence::Status::setPriority(int priority)
{
    m_priority = priority;
}

void QXmppPresence::Status::parse(const QDomElement &element)
{
    setTypeFromStr(element.firstChildElement("show").text());
    m_statusText = element.firstChildElement("status").text();
    m_priority = element.firstChildElement("priority").text().toInt();
}

void QXmppPresence::Status::toXml(QXmlStreamWriter *xmlWriter) const
{
    const QString show = getTypeStr();
    if (!show.isEmpty())
        helperToXmlAddTextElement(xmlWriter, "show", getTypeStr());
    if (!m_statusText.isEmpty())
        helperToXmlAddTextElement(xmlWriter, "status", m_statusText);
    if (m_priority != 0)
        helperToXmlAddNumberElement(xmlWriter, "priority", m_priority);
}

QByteArray QXmppPresence::photoHash() const
{
    return m_photoHash;
}

void QXmppPresence::setPhotoHash(const QByteArray& photoHash)
{
    m_photoHash = photoHash;
}

QXmppPresence::VCardUpdateType QXmppPresence::vCardUpdateType()
{
    return m_vCardUpdateType;
}

void QXmppPresence::setVCardUpdateType(VCardUpdateType type)
{
    m_vCardUpdateType = type;
}

/// XEP-0115: Entity Capabilities
QString QXmppPresence::capabilityHash()
{
    return m_capabilityHash;
}

/// XEP-0115: Entity Capabilities
void QXmppPresence::setCapabilityHash(const QString& hash)
{
    m_capabilityHash = hash;
}

/// XEP-0115: Entity Capabilities
QString QXmppPresence::capabilityNode()
{
    return m_capabilityNode;
}

/// XEP-0115: Entity Capabilities
void QXmppPresence::setCapabilityNode(const QString& node)
{
    m_capabilityNode = node;
}

/// XEP-0115: Entity Capabilities
QByteArray QXmppPresence::capabilityVer()
{
    return m_capabilityVer;
}

/// XEP-0115: Entity Capabilities
void QXmppPresence::setCapabilityVer(const QByteArray& ver)
{
    m_capabilityVer = ver;
}

/// Legacy XEP-0115: Entity Capabilities
QStringList QXmppPresence::capabilityExt()
{
    return m_capabilityExt;
}

/// \cond

QXmppPresence::Type QXmppPresence::getType() const
{
    return m_type;
}

const QXmppPresence::Status& QXmppPresence::getStatus() const
{
    return m_status;
}

QXmppPresence::Status& QXmppPresence::getStatus()
{
    return m_status;
}

QXmppPresence::Status::Type QXmppPresence::Status::getType() const
{
    return m_type;
}

QString QXmppPresence::Status::getStatusText() const
{
    return m_statusText;
}

int QXmppPresence::Status::getPriority() const
{
    return m_priority;
}

/// \endcond
<commit_msg>initialise QXmppPresence::m_vCardUpdateType (Closes: #82)<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppPresence.h"
#include "QXmppUtils.h"
#include <QtDebug>
#include <QDomElement>
#include <QXmlStreamWriter>
#include "QXmppConstants.h"

QXmppPresence::QXmppPresence(QXmppPresence::Type type,
                             const QXmppPresence::Status& status)
    : QXmppStanza(),
    m_type(type),
    m_status(status),
    m_vCardUpdateType(VCardUpdateNone)
{

}

QXmppPresence::~QXmppPresence()
{

}

QXmppPresence::Type QXmppPresence::type() const
{
    return m_type;
}

void QXmppPresence::setType(QXmppPresence::Type type)
{
    m_type = type;
}

const QXmppPresence::Status& QXmppPresence::status() const
{
    return m_status;
}

QXmppPresence::Status& QXmppPresence::status()
{
    return m_status;
}

void QXmppPresence::setStatus(const QXmppPresence::Status& status)
{
    m_status = status;
}

void QXmppPresence::parse(const QDomElement &element)
{
    QXmppStanza::parse(element);

    setTypeFromStr(element.attribute("type"));
    m_status.parse(element);

    QXmppElementList extensions;
    QDomElement xElement = element.firstChildElement();
    m_vCardUpdateType = VCardUpdateNone;
    while(!xElement.isNull())
    {
        // XEP-0153: vCard-Based Avatars
        if(xElement.namespaceURI() == ns_vcard_update)
        {
            QDomElement photoElement = xElement.firstChildElement("photo");
            if(!photoElement.isNull())
            {
                m_photoHash = QByteArray::fromHex(photoElement.text().toAscii());
                if(m_photoHash.isEmpty())
                    m_vCardUpdateType = PhotoNotAdvertized;
                else
                    m_vCardUpdateType = PhotoAdvertised;
            }
            else
            {
                m_photoHash = QByteArray();
                m_vCardUpdateType = PhotoNotReady;
            }
        }
        // XEP-0115: Entity Capabilities
        else if(xElement.tagName() == "c" && xElement.namespaceURI() == ns_capabilities)
        {
            m_capabilityNode = xElement.attribute("node");
            m_capabilityVer = QByteArray::fromBase64(xElement.attribute("ver").toAscii());
            m_capabilityHash = xElement.attribute("hash");
            m_capabilityExt = xElement.attribute("ext").split(" ", QString::SkipEmptyParts);
        }
        else if (xElement.tagName() == "error")
        {
        }
        else if (xElement.tagName() == "show")
        {
        }
        else if (xElement.tagName() == "status")
        {
        }
        else if (xElement.tagName() == "priority")
        {
        }
        else
        {
            // other extensions
            extensions << QXmppElement(xElement);
        }
        xElement = xElement.nextSiblingElement();
    }
    setExtensions(extensions);
}

void QXmppPresence::toXml(QXmlStreamWriter *xmlWriter) const
{
    xmlWriter->writeStartElement("presence");
    helperToXmlAddAttribute(xmlWriter,"xml:lang", lang());
    helperToXmlAddAttribute(xmlWriter,"id", id());
    helperToXmlAddAttribute(xmlWriter,"to", to());
    helperToXmlAddAttribute(xmlWriter,"from", from());
    helperToXmlAddAttribute(xmlWriter,"type", getTypeStr());
    m_status.toXml(xmlWriter);

    error().toXml(xmlWriter);

    // XEP-0153: vCard-Based Avatars
    if(m_vCardUpdateType != VCardUpdateNone)
    {
        xmlWriter->writeStartElement("x");
        helperToXmlAddAttribute(xmlWriter, "xmlns", ns_vcard_update);
        switch(m_vCardUpdateType)
        {
        case PhotoNotAdvertized:
            helperToXmlAddTextElement(xmlWriter, "photo", "");
            break;
        case PhotoAdvertised:
            helperToXmlAddTextElement(xmlWriter, "photo", m_photoHash.toHex());
            break;
        case PhotoNotReady:
            break;
        default:
            break;
        }
        xmlWriter->writeEndElement();
    }

    if(!m_capabilityNode.isEmpty() && !m_capabilityVer.isEmpty()
        && !m_capabilityHash.isEmpty())
    {
        xmlWriter->writeStartElement("c");
        helperToXmlAddAttribute(xmlWriter, "xmlns", ns_capabilities);
        helperToXmlAddAttribute(xmlWriter, "hash", m_capabilityHash);
        helperToXmlAddAttribute(xmlWriter, "node", m_capabilityNode);
        helperToXmlAddAttribute(xmlWriter, "ver", m_capabilityVer.toBase64());
        xmlWriter->writeEndElement();
    }

    foreach (const QXmppElement &extension, extensions())
        extension.toXml(xmlWriter);

    xmlWriter->writeEndElement();
}

QString QXmppPresence::getTypeStr() const
{
    QString text;
    switch(m_type)
    {
    case QXmppPresence::Error:
        text = "error";
        break;
    case QXmppPresence::Available:
        // no type-attribute if available
        text = "";
        break;
    case QXmppPresence::Unavailable:
        text = "unavailable";
        break;
    case QXmppPresence::Subscribe:
        text = "subscribe";
        break;
    case QXmppPresence::Subscribed:
        text = "subscribed";
        break;
    case QXmppPresence::Unsubscribe:
        text = "unsubscribe";
        break;
    case QXmppPresence::Unsubscribed:
        text = "unsubscribed";
        break;
    case QXmppPresence::Probe:
        text = "probe";
        break;
    default:
        qWarning("QXmppPresence::getTypeStr() invalid type %d", (int)m_type);
        break;
    }
    return text;
}

void QXmppPresence::setTypeFromStr(const QString& str)
{
    QXmppPresence::Type type;
    if(str == "error")
    {
        type = QXmppPresence::Error;
        setType(type);
        return;
    }
    else if(str == "unavailable")
    {
        type = QXmppPresence::Unavailable;
        setType(type);
        return;
    }
    else if(str == "subscribe")
    {
        type = QXmppPresence::Subscribe;
        setType(type);
        return;
    }
    else if(str == "subscribed")
    {
        type = QXmppPresence::Subscribed;
        setType(type);
        return;
    }
    else if(str == "unsubscribe")
    {
        type = QXmppPresence::Unsubscribe;
        setType(type);
        return;
    }
    else if(str == "unsubscribed")
    {
        type = QXmppPresence::Unsubscribed;
        setType(type);
        return;
    }
    else if(str == "probe")
    {
        type = QXmppPresence::Probe;
        setType(type);
        return;
    }
    else if(str == "")
    {
        type = QXmppPresence::Available;
        setType(type);
        return;
    }
    else
    {
        type = static_cast<QXmppPresence::Type>(-1);
        qWarning("QXmppPresence::setTypeFromStr() invalid input string type: %s",
                 qPrintable(str));
        setType(type);
        return;
    }
}

QXmppPresence::Status::Status(QXmppPresence::Status::Type type,
                             const QString statusText, int priority) :
                                m_type(type),
                                m_statusText(statusText), m_priority(priority)
{
}

QXmppPresence::Status::Type QXmppPresence::Status::type() const
{
    return m_type;
}

void QXmppPresence::Status::setType(QXmppPresence::Status::Type type)
{
    m_type = type;
}

void QXmppPresence::Status::setTypeFromStr(const QString& str)
{
    // there is no keyword for Offline

    QXmppPresence::Status::Type type;
    if(str == "")   // not type-attribute means online
    {
        type = QXmppPresence::Status::Online;
        setType(type);
        return;
    }
    else if(str == "away")
    {
        type = QXmppPresence::Status::Away;
        setType(type);
        return;
    }
    else if(str == "xa")
    {
        type = QXmppPresence::Status::XA;
        setType(type);
        return;
    }
    else if(str == "dnd")
    {
        type = QXmppPresence::Status::DND;
        setType(type);
        return;
    }
    else if(str == "chat")
    {
        type = QXmppPresence::Status::Chat;
        setType(type);
        return;
    }
    else
    {
        type = static_cast<QXmppPresence::Status::Type>(-1);
        qWarning("QXmppPresence::Status::setTypeFromStr() invalid input string type %s",
            qPrintable(str));
        setType(type);
    }
}

QString QXmppPresence::Status::getTypeStr() const
{
    QString text;
    switch(m_type)
    {
    case QXmppPresence::Status::Online:
        // no type-attribute if available
        text = "";
        break;
    case QXmppPresence::Status::Offline:
        text = "";
        break;
    case QXmppPresence::Status::Away:
        text = "away";
        break;
    case QXmppPresence::Status::XA:
        text = "xa";
        break;
    case QXmppPresence::Status::DND:
        text = "dnd";
        break;
    case QXmppPresence::Status::Chat:
        text = "chat";
        break;
    default:
        qWarning("QXmppPresence::Status::getTypeStr() invalid type %d",
                 (int)m_type);
        break;
    }
    return text;
}

QString QXmppPresence::Status::statusText() const
{
    return m_statusText;
}

void QXmppPresence::Status::setStatusText(const QString& str)
{
    m_statusText = str;
}

int QXmppPresence::Status::priority() const
{
    return m_priority;
}

void QXmppPresence::Status::setPriority(int priority)
{
    m_priority = priority;
}

void QXmppPresence::Status::parse(const QDomElement &element)
{
    setTypeFromStr(element.firstChildElement("show").text());
    m_statusText = element.firstChildElement("status").text();
    m_priority = element.firstChildElement("priority").text().toInt();
}

void QXmppPresence::Status::toXml(QXmlStreamWriter *xmlWriter) const
{
    const QString show = getTypeStr();
    if (!show.isEmpty())
        helperToXmlAddTextElement(xmlWriter, "show", getTypeStr());
    if (!m_statusText.isEmpty())
        helperToXmlAddTextElement(xmlWriter, "status", m_statusText);
    if (m_priority != 0)
        helperToXmlAddNumberElement(xmlWriter, "priority", m_priority);
}

QByteArray QXmppPresence::photoHash() const
{
    return m_photoHash;
}

void QXmppPresence::setPhotoHash(const QByteArray& photoHash)
{
    m_photoHash = photoHash;
}

QXmppPresence::VCardUpdateType QXmppPresence::vCardUpdateType()
{
    return m_vCardUpdateType;
}

void QXmppPresence::setVCardUpdateType(VCardUpdateType type)
{
    m_vCardUpdateType = type;
}

/// XEP-0115: Entity Capabilities
QString QXmppPresence::capabilityHash()
{
    return m_capabilityHash;
}

/// XEP-0115: Entity Capabilities
void QXmppPresence::setCapabilityHash(const QString& hash)
{
    m_capabilityHash = hash;
}

/// XEP-0115: Entity Capabilities
QString QXmppPresence::capabilityNode()
{
    return m_capabilityNode;
}

/// XEP-0115: Entity Capabilities
void QXmppPresence::setCapabilityNode(const QString& node)
{
    m_capabilityNode = node;
}

/// XEP-0115: Entity Capabilities
QByteArray QXmppPresence::capabilityVer()
{
    return m_capabilityVer;
}

/// XEP-0115: Entity Capabilities
void QXmppPresence::setCapabilityVer(const QByteArray& ver)
{
    m_capabilityVer = ver;
}

/// Legacy XEP-0115: Entity Capabilities
QStringList QXmppPresence::capabilityExt()
{
    return m_capabilityExt;
}

/// \cond

QXmppPresence::Type QXmppPresence::getType() const
{
    return m_type;
}

const QXmppPresence::Status& QXmppPresence::getStatus() const
{
    return m_status;
}

QXmppPresence::Status& QXmppPresence::getStatus()
{
    return m_status;
}

QXmppPresence::Status::Type QXmppPresence::Status::getType() const
{
    return m_type;
}

QString QXmppPresence::Status::getStatusText() const
{
    return m_statusText;
}

int QXmppPresence::Status::getPriority() const
{
    return m_priority;
}

/// \endcond
<|endoftext|>


<commit_before>#include "debug.h"
#include <stdio.h>
#include <stdarg.h>
#include "timeops.h"
#include <pthread.h>
#include "cmm_thread.h"

#ifdef CMM_DEBUG
static bool debugging = true;

void set_debugging(bool value)
{
    debugging = value;
}

static void vdbgprintf(bool plain, const char *fmt, va_list ap)
{
    if (!plain) {
        struct timeval now;
        TIME(now);
        fprintf(stderr, "[%lu.%06lu][%d][%s] ",
                now.tv_sec, now.tv_usec, getpid(),
#ifdef CMM_UNIT_TESTING
                "(unit testing)"
#else
                get_thread_name()
#endif
                );
    }

    vfprintf(stderr, fmt, ap);
}

void dbgprintf(const char *fmt, ...)
{
    if (debugging) {
        va_list ap;
        va_start(ap, fmt);
        vdbgprintf(false, fmt, ap);
        va_end(ap);
    }
}

void dbgprintf_plain(const char *fmt, ...)
{
    if (debugging) {
        va_list ap;
        va_start(ap, fmt);
        vdbgprintf(true, fmt, ap);
        va_end(ap);
    }
}
#endif
<commit_msg>The dbgprintfs should no longer get split among multiple lines now.<commit_after>#include "debug.h"
#include <stdio.h>
#include <stdarg.h>
#include "timeops.h"
#include <pthread.h>
#include "cmm_thread.h"
#include <sstream>
#include <string>
#include <iomanip>
using std::ostringstream; using std::string;
using std::setw; using std::setfill;

#ifdef CMM_DEBUG
static bool debugging = true;

void set_debugging(bool value)
{
    debugging = value;
}

static void vdbgprintf(bool plain, const char *fmt, va_list ap)
{
    ostringstream stream;
    if (!plain) {
        struct timeval now;
        TIME(now);
        stream << "[" << now.tv_sec << "." << setw(6) << setfill('0') << now.tv_usec << "]";
        stream << "[" << getpid() << "]";
        stream << "[";
#ifdef CMM_UNIT_TESTING
        stream << "(unit testing)";
#else
        stream << get_thread_name();
#endif
        stream << "] ";
    }

    string fmtstr(stream.str());
    fmtstr += fmt;

    vfprintf(stderr, fmtstr.c_str(), ap);
}

void dbgprintf(const char *fmt, ...)
{
    if (debugging) {
        va_list ap;
        va_start(ap, fmt);
        vdbgprintf(false, fmt, ap);
        va_end(ap);
    }
}

void dbgprintf_plain(const char *fmt, ...)
{
    if (debugging) {
        va_list ap;
        va_start(ap, fmt);
        vdbgprintf(true, fmt, ap);
        va_end(ap);
    }
}
#endif
<|endoftext|>