Author Topic: PCL: SaveFileDialog is removing .csv extension and replacing with .*  (Read 10647 times)

Offline Nocturnal

  • PixInsight Jedi Council Member
  • *******
  • Posts: 2727
    • http://www.carpephoton.com

Hi,

the following worked fine in earlier PCL versions and on XP32:

Code: [Select]
void ProfileInterface::SaveToCSV()
{
SaveFileDialog theDialog;
FileFilter theFilter;
theFilter.AddExtension(".csv");
theFilter.AddExtension(".txt");

theDialog.SetCaption("Select a file name to save the CSV to");
//theDialog.Filters() = theFilter;
if (theDialog.Execute()) {
File theCSV(theDialog.FileName(), FileMode::Write|FileMode::Create);
               // do something with the file

Now I get an error dialog when the File object is created. Say I enter file name test.csv it'll tell me it can't create file test.* . I use native dialogs on Vista 64. This used to work fine on XP32 with a previous version of PCL but I haven't tried there with the current PCL.

Any ideas?
Best,

    Sander
---
Edge HD 1100
QHY-8 for imaging, IMG0H mono for guiding, video cameras for occulations
ASI224, QHY5L-IIc
HyperStar3
WO-M110ED+FR-III/TRF-2008
Takahashi EM-400
PIxInsight, DeepSkyStacker, PHD, Nebulosity

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Hi Sander,

Congratulations on another nice tool! Great work!  8)

Strange problem. Two questions:

- Do you have the "hide extensions for known file types" option enabled in the Windows Explorer?

- Do you have a "*.*" or "*" filter item, along with ".csv" and ".txt"?
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Nocturnal

  • PixInsight Jedi Council Member
  • *******
  • Posts: 2727
    • http://www.carpephoton.com
Hi Juan,

extensions are shown for all file types and I type the full path name in the dialog (ie. test.csv). The filedialog has no filter items at all as you can see in my code snippet. It's been a while since I worked on it so I assume I tried to add filters but couldn't get them to work so I commented it out.
Best,

    Sander
---
Edge HD 1100
QHY-8 for imaging, IMG0H mono for guiding, video cameras for occulations
ASI224, QHY5L-IIc
HyperStar3
WO-M110ED+FR-III/TRF-2008
Takahashi EM-400
PIxInsight, DeepSkyStacker, PHD, Nebulosity

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Quote
The filedialog has no filter items at all

This is the problem. You actually need at least one file filter with native dialogs. Uncomment:

Code: [Select]
//theDialog.Filters() = theFilter;
and your FileDialog should work without problems. Let me know if this is true.

Anyway, I have fixed this problem for PI 1.5.5 (a really last-minute improvement; you guys will kill me if you don't stop pointing out things that don't work before I can release  ;D ). In PI 1.5.5, FileDialog behaves well even with no file filters, although at least one filter should normally be defined in most situations.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Nocturnal

  • PixInsight Jedi Council Member
  • *******
  • Posts: 2727
    • http://www.carpephoton.com
Hi,

that doesn't work as there's no = operator.

Code: [Select]
>Compiling...
1>ProfileInterface.cpp
1>..\ProfileInterface.cpp(1270) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'pcl::FileFilter' (or there is no acceptable conversion)
1>        c:\pcl64\include\pcl/Array.h(508): could be 'pcl::Array<T> &pcl::Array<T>::operator =(const pcl::Array<T> &)'
1>        with
1>        [
1>            T=pcl::FileFilter
1>        ]
1>        while trying to match the argument list '(pcl::FileDialog::filter_container, pcl::FileFilter)'

I looked at the docs but I don't see how to give the filter object to the dialog.
Best,

    Sander
---
Edge HD 1100
QHY-8 for imaging, IMG0H mono for guiding, video cameras for occulations
ASI224, QHY5L-IIc
HyperStar3
WO-M110ED+FR-III/TRF-2008
Takahashi EM-400
PIxInsight, DeepSkyStacker, PHD, Nebulosity

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Ok, try this way:

Code: [Select]
FileFilter csvFilter;
csvFilter.SetDescription( "CSV files" );
csvFilter.AddExtension( ".csv" );

FileFilter txtFilter;
txtFilter.SetDescription( "Plain text files" );
txtFilter.AddExtension( ".txt" );

SaveFileDialog theDialog;
theDialog.Filters().Add( csvFilter );
theDialog.Filters().Add( txtFilter );

if ( theDialog.Execute() )
{
   File theCSV( theDialog.FileName(), FileMode::Write|FileMode::Create);
   // do something with the file
   // ...
}
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Nocturnal

  • PixInsight Jedi Council Member
  • *******
  • Posts: 2727
    • http://www.carpephoton.com
Unfortunately now PI (1.5.5) crashes when I hit the 'execute' method:

Code: [Select]
void ProfileInterface::SaveToCSV()
{
FileFilter csvFilter;
csvFilter.SetDescription( "CSV files" );
csvFilter.AddExtension( ".csv" );

FileFilter txtFilter;
txtFilter.SetDescription( "Plain text files" );
txtFilter.AddExtension( ".txt" );

SaveFileDialog theDialog;
theDialog.Filters().Add( csvFilter );
theDialog.Filters().Add( txtFilter );
theDialog.SetCaption("Select a file name to save the CSV to");
if (theDialog.Execute()) {
File theCSV(theDialog.FileName(), FileMode::Write|FileMode::Create);
Best,

    Sander
---
Edge HD 1100
QHY-8 for imaging, IMG0H mono for guiding, video cameras for occulations
ASI224, QHY5L-IIc
HyperStar3
WO-M110ED+FR-III/TRF-2008
Takahashi EM-400
PIxInsight, DeepSkyStacker, PHD, Nebulosity

Offline Nocturnal

  • PixInsight Jedi Council Member
  • *******
  • Posts: 2727
    • http://www.carpephoton.com
Code: [Select]
The thread 'Win64 Thread' (0x1bd8) has exited with code 0 (0x0).
The thread 'Win64 Thread' (0x1490) has exited with code 0 (0x0).
The thread 'RPC Callback Thread' (0xf60) has exited with code 0 (0x0).
First-chance exception at 0x7782619d in PixInsight.exe: Microsoft C++ exception: pcl::FatalError at memory location 0x002a8b18..
First-chance exception at 0x7782619d in PixInsight.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7782619d in PixInsight.exe: Microsoft C++ exception: pcl::FatalError at memory location 0x002a8b18..
First-chance exception at 0x7782619d in PixInsight.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7782619d in PixInsight.exe: Microsoft C++ exception: pcl::FatalError at memory location 0x002a8b18..
First-chance exception at 0x7782619d in PixInsight.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7782619d in PixInsight.exe: Microsoft C++ exception: pcl::FatalError at memory location 0x002a8b18..
Qt has caught an exception thrown from an event handler. Throwing
exceptions from an event handler is not supported in Qt. You must
reimplement QApplication::notify() and catch all exceptions there.

Best,

    Sander
---
Edge HD 1100
QHY-8 for imaging, IMG0H mono for guiding, video cameras for occulations
ASI224, QHY5L-IIc
HyperStar3
WO-M110ED+FR-III/TRF-2008
Takahashi EM-400
PIxInsight, DeepSkyStacker, PHD, Nebulosity

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
Hi Sander,

This happens because you have redefined __PCL_DIAGNOSTICS_LEVEL to something different from zero. PCL diagnostics code works well in general, but there are some small errors as the one you've discovered. This is a precondition failed in the following member function of Allocator:

Code: [Select]
   void Allocator::Deallocate( T* p )
   {
      PCL_PRECONDITION( p != 0 )
      this->DeallocateBlock( (void*)p );
   }

The precondition signals that a zero pointer has been passed to Allocator::Deallocate(), which is a formal error. However, there's no problem because DeallocateBlock() (as reimplemented by pcl::StandardAllocator) protects itself from this contingency. I'll investigate where this null pointer deallocation attempt comes from; thanks for catching it.

To avoid these problems, just don't use diagnostics code (don't redefine __PCL_DIAGNOSTICS_LEVEL) and everything should work fine.

I have prepared a small example to test PCL file dialogs. It is a modified version of SandBox:

Modified SandBoxInterface.h:
Code: [Select]
#ifndef __SandboxInterface_h
#define __SandboxInterface_h

#include <pcl/ProcessingInterface.h>

#include <pcl/Sizer.h>
#include <pcl/PushButton.h>
#include <pcl/Edit.h>
#include <pcl/TextBox.h>

#include "SandboxInstance.h"

namespace pcl
{

class SandboxInterface : public ProcessingInterface
{
public:

   SandboxInterface();
   virtual ~SandboxInterface();

   virtual IsoString Id() const;
   virtual uint32 Version() const;
   virtual const char** IconImageXPM() const;

   virtual void ApplyInstance() const;
   virtual void ResetInstance();

   virtual bool Launch( const MetaProcess&, const ProcessImplementation*, bool& dynamic, unsigned& /*flags*/ );

   virtual ProcessImplementation* NewProcess() const;

   virtual bool ValidateProcess( const ProcessImplementation&, String& whyNot ) const;
   virtual bool RequiresInstanceValidation() const;

   virtual bool ImportProcess( const ProcessImplementation& );

private:

   SandboxInstance instance;

   struct GUIData
   {
      GUIData( SandboxInterface& );

      VerticalSizer     Global_Sizer;

         PushButton        TestSaveFileDialog_PushButton;
         Edit              TestSaveFileDialog_Edit;
         PushButton        TestOpenFileDialog_PushButton;
         Edit              TestOpenFileDialog_Edit;
         PushButton        TestOpenFilesDialog_PushButton;
         TextBox           TestOpenFilesDialog_TextBox;
   };

   GUIData* GUI;

   void UpdateControls();

   // Event Handlers

   void __ItemClicked( Button& sender, bool checked );

   friend struct GUIData;
};

// ----------------------------------------------------------------------------

PCL_BEGIN_LOCAL
extern SandboxInterface* TheSandboxInterface;
PCL_END_LOCAL

// ----------------------------------------------------------------------------

} // pcl

#endif   // __SandboxInterface_h

Modified SandBoxInterface.cpp:
Code: [Select]
#include "SandboxInterface.h"
#include "SandboxProcess.h"
#include "SandboxParameters.h"

#include <pcl/FileDialog.h>

namespace pcl
{

// ----------------------------------------------------------------------------

SandboxInterface* TheSandboxInterface = 0;

// ----------------------------------------------------------------------------

SandboxInterface::SandboxInterface() :
ProcessingInterface(), instance( TheSandboxProcess ), GUI( 0 )
{
   TheSandboxInterface = this;
}

SandboxInterface::~SandboxInterface()
{
   if ( GUI != 0 )
      delete GUI, GUI = 0;
}

IsoString SandboxInterface::Id() const
{
   return "Sandbox";
}

uint32 SandboxInterface::Version() const
{
   return 0x100; // required
}

const char** SandboxInterface::IconImageXPM() const
{
   return 0; // SandboxIcon_XPM; ---> put a nice icon here
}

void SandboxInterface::ApplyInstance() const
{
   instance.LaunchOnCurrentView();
}

void SandboxInterface::ResetInstance()
{
   SandboxInstance defaultInstance( TheSandboxProcess );
   ImportProcess( defaultInstance );
}

bool SandboxInterface::Launch( const MetaProcess& P, const ProcessImplementation*, bool& dynamic, unsigned& /*flags*/ )
{
   // ### Deferred initialization
   if ( GUI == 0 )
   {
      GUI = new GUIData( *this );
      SetWindowTitle( "Sandbox" );
      UpdateControls();
   }

   dynamic = false;
   return &P == TheSandboxProcess;
}

ProcessImplementation* SandboxInterface::NewProcess() const
{
   return new SandboxInstance( instance );
}

bool SandboxInterface::ValidateProcess( const ProcessImplementation& p, String& whyNot ) const
{
   const SandboxInstance* r = dynamic_cast<const SandboxInstance*>( &p );
   if ( r == 0 )
   {
      whyNot = "Not a Sandbox instance.";
      return false;
   }

   whyNot.Empty();
   return true;
}

bool SandboxInterface::RequiresInstanceValidation() const
{
   return true;
}

bool SandboxInterface::ImportProcess( const ProcessImplementation& p )
{
   instance.Assign( p );
   UpdateControls();
   return true;
}

// ----------------------------------------------------------------------------

void SandboxInterface::UpdateControls()
{
}

// ----------------------------------------------------------------------------

static void SetCSVFiltersHelper( FileDialog& dialog )
{
   FileFilter csvFilter;
   csvFilter.SetDescription( "CSV files" );
   csvFilter.AddExtension( ".csv" );

   FileFilter txtFilter;
   txtFilter.SetDescription( "Plain text files" );
   txtFilter.AddExtension( ".txt" );

   dialog.Filters().Add( csvFilter );
   dialog.Filters().Add( txtFilter );
}

void SandboxInterface::__ItemClicked( Button& sender, bool checked )
{
   if ( sender == GUI->TestSaveFileDialog_PushButton )
   {
      SaveFileDialog theDialog;
      theDialog.SetCaption( "Select a file name to save the CSV to" );
      SetCSVFiltersHelper( theDialog );

      if ( theDialog.Execute() )
         GUI->TestSaveFileDialog_Edit.SetText( theDialog.FileName() );
   }
   else if ( sender == GUI->TestOpenFileDialog_PushButton )
   {
      OpenFileDialog theDialog;
      theDialog.SetCaption( "Select a CSV or plain text file to open" );
      SetCSVFiltersHelper( theDialog );

      if ( theDialog.Execute() )
         GUI->TestOpenFileDialog_Edit.SetText( theDialog.FileName() );
   }
   else if ( sender == GUI->TestOpenFilesDialog_PushButton )
   {
      OpenFileDialog theDialog;
      theDialog.SetCaption( "Select a set of CSV or plain text files to open" );
      theDialog.EnableMultipleSelections();
      SetCSVFiltersHelper( theDialog );

      if ( theDialog.Execute() )
      {
         String fileNames;
         for ( StringList::const_iterator i = theDialog.FileNames().Begin();
               i != theDialog.FileNames().End();
               ++i )
         {
            fileNames += *i;
            fileNames += '\n';
         }

         fileNames += "<beg>"; // to scroll the TextBox to the beginning

         GUI->TestOpenFilesDialog_TextBox.SetText( fileNames );
      }
   }
}

// ----------------------------------------------------------------------------

SandboxInterface::GUIData::GUIData( SandboxInterface& w )
{
   TestSaveFileDialog_PushButton.SetText( "Test SaveFileDialog" );
   TestSaveFileDialog_PushButton.OnClick( (pcl::Button::click_event_handler)&SandboxInterface::__ItemClicked, w );

   TestSaveFileDialog_Edit.SetReadOnly();
   TestSaveFileDialog_Edit.SetMinWidth( 400 );

   TestOpenFileDialog_PushButton.SetText( "Test OpenFileDialog - Single Selection" );
   TestOpenFileDialog_PushButton.OnClick( (pcl::Button::click_event_handler)&SandboxInterface::__ItemClicked, w );

   TestOpenFileDialog_Edit.SetReadOnly();
   TestOpenFileDialog_Edit.SetMinWidth( 400 );

   TestOpenFilesDialog_PushButton.SetText( "Test OpenFileDialog - Multiple Selections" );
   TestOpenFilesDialog_PushButton.OnClick( (pcl::Button::click_event_handler)&SandboxInterface::__ItemClicked, w );

   TestOpenFilesDialog_TextBox.SetReadOnly();
   TestOpenFilesDialog_TextBox.SetMinSize( 400, 200 );

   //

   Global_Sizer.SetMargin( 8 );
   Global_Sizer.SetSpacing( 6 );
   Global_Sizer.Add( TestSaveFileDialog_PushButton );
   Global_Sizer.Add( TestSaveFileDialog_Edit );
   Global_Sizer.Add( TestOpenFileDialog_PushButton );
   Global_Sizer.Add( TestOpenFileDialog_Edit );
   Global_Sizer.Add( TestOpenFilesDialog_PushButton );
   Global_Sizer.Add( TestOpenFilesDialog_TextBox );

   w.SetSizer( Global_Sizer );
   w.AdjustToContents();
}

// ----------------------------------------------------------------------------

} // pcl
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Nocturnal

  • PixInsight Jedi Council Member
  • *******
  • Posts: 2727
    • http://www.carpephoton.com
Hi Juan,

I hope you'll fix the problem soon because I really need to have __PCL_DIAGNOSTICS_LEVEL defined. As a novice PCL programmer I need all the help I can get. I recommend you enable it for your debug builds. "Eating your own dog food" as we call it here. Built in assertions are a necessity but they are only helpful if they're being used, right?

I'll recompile without __PCL_DIAGNOSTICS_LEVEL defined for now but please note the fixing of this bug in the next release notes so I can re-enable it.
Best,

    Sander
---
Edge HD 1100
QHY-8 for imaging, IMG0H mono for guiding, video cameras for occulations
ASI224, QHY5L-IIc
HyperStar3
WO-M110ED+FR-III/TRF-2008
Takahashi EM-400
PIxInsight, DeepSkyStacker, PHD, Nebulosity

Offline Nocturnal

  • PixInsight Jedi Council Member
  • *******
  • Posts: 2727
    • http://www.carpephoton.com
Re: PCL: SaveFileDialog is removing .csv extension and replacing with .*
« Reply #10 on: 2009 September 16 18:42:04 »
Hi Juan,

I'm trying to compile my Profile module and still stumbling on this PCL_DIAGNOSTICS problem. Could you please confirm that you'll fix this issue in the next PCL release? PCL_DIAGNOSTICS is an essential tool for PCL development IMO. Developing with it disabled is like driving without seat belts. Only the steering wheel to stop you from flying out of the car.
Best,

    Sander
---
Edge HD 1100
QHY-8 for imaging, IMG0H mono for guiding, video cameras for occulations
ASI224, QHY5L-IIc
HyperStar3
WO-M110ED+FR-III/TRF-2008
Takahashi EM-400
PIxInsight, DeepSkyStacker, PHD, Nebulosity