Upgrading win32cpp.

Added a lock around sqlite3_prepare_v2 to fix SQLite bug when interrupting.
MetadataFilterView filtering starting to work.
Altered the indexer status a bit.
This commit is contained in:
Daniel Önnerby 2008-05-16 08:21:45 +00:00
parent 767409e346
commit 5631f10064
25 changed files with 246 additions and 90 deletions

View File

@ -40,7 +40,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="./include/;./include/sqlite/"
PreprocessorDefinitions="BOOST_ALL_NO_LIB;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;THREADSAFE"
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;SQLITE_THREADSAFE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
@ -105,7 +105,7 @@
InlineFunctionExpansion="2"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="./include/;./include/sqlite/"
PreprocessorDefinitions="BOOST_ALL_NO_LIB;WIN32;_CRT_SECURE_NO_DEPRECATE;THREADSAFE"
PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;SQLITE_THREADSAFE"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
PrecompiledHeaderThrough="pch.hpp"

View File

@ -69,10 +69,16 @@ utfstring Indexer::GetStatus(){
sStatus = boost::str( boost::utfformat(UTF("Counting files: %1%"))%this->iNOFFiles );
break;
case 2:
sStatus = boost::str( boost::utfformat(UTF("Indexing: %.3d"))%(this->iProgress*100)) + UTF("%");
sStatus = boost::str( boost::utfformat(UTF("Indexing: %.2f"))%(this->iProgress*100)) + UTF("%");
break;
case 3:
sStatus = boost::str( boost::utfformat(UTF("Cleaning up: %.3d"))%(this->iProgress*100)) + UTF("%");
sStatus = boost::str( boost::utfformat(UTF("Removing old files: %.2f"))%(this->iProgress*100)) + UTF("%");
break;
case 4:
sStatus = UTF("Cleaning up.");
break;
case 5:
sStatus = UTF("Optimizing.");
break;
}
return sStatus;
@ -192,6 +198,7 @@ void Indexer::Synchronize(){
{
boost::mutex::scoped_lock oLock(this->oProgressMutex);
this->iStatus = 1;
this->iProgress = 0.0;
}
for(int i(0);i<aPaths.size();++i){
@ -203,6 +210,7 @@ void Indexer::Synchronize(){
{
boost::mutex::scoped_lock oLock(this->oProgressMutex);
this->iStatus = 2;
this->iProgress = 0.0;
}
for(int i(0);i<aPaths.size();++i){
@ -214,7 +222,7 @@ void Indexer::Synchronize(){
{
boost::mutex::scoped_lock oLock(this->oProgressMutex);
this->iProgress = 1.0;
this->iProgress = 0.0;
this->iStatus = 3;
}
@ -222,9 +230,24 @@ void Indexer::Synchronize(){
if(!this->Restarted() && !this->Exit()){
this->SyncDelete(aPathIds);
}
{
// Cleanup status
boost::mutex::scoped_lock oLock(this->oProgressMutex);
this->iProgress = 0.0;
this->iStatus = 4;
}
if(!this->Restarted() && !this->Exit()){
this->SyncCleanup();
}
{
// Optimize status
boost::mutex::scoped_lock oLock(this->oProgressMutex);
this->iProgress = 0.0;
this->iStatus = 5;
}
if(!this->Restarted() && !this->Exit()){
this->SyncOptimize();
}
@ -484,6 +507,7 @@ void Indexer::SyncDelete(std::vector<DBINT> aPaths){
while( stmt.Step()==db::ReturnCode::Row && !this->Exit() && !this->Restarted() ){
// Check to see if file still exists
bool bRemove(true);
utfstring sFolder = stmt.ColumnTextUTF(1);

View File

@ -160,9 +160,14 @@ int Connection::Close(){
//////////////////////////////////////////
int Connection::Execute(const char* sql){
sqlite3_stmt *stmt = NULL;
if(sqlite3_prepare_v2(this->connection,sql,-1,&stmt,NULL)!=SQLITE_OK){
sqlite3_finalize(stmt);
return ReturnCode::Error;
// Prepaire seems to give errors when interrupted
{
boost::mutex::scoped_lock lock(this->mutex);
if(sqlite3_prepare_v2(this->connection,sql,-1,&stmt,NULL)!=SQLITE_OK){
sqlite3_finalize(stmt);
return ReturnCode::Error;
}
}
// Execute the statement
@ -193,9 +198,12 @@ int Connection::Execute(const char* sql){
//////////////////////////////////////////
int Connection::Execute(const wchar_t* sql){
sqlite3_stmt *stmt = NULL;
if(sqlite3_prepare16_v2(this->connection,sql,-1,&stmt,NULL)!=SQLITE_OK){
sqlite3_finalize(stmt);
return ReturnCode::Error;
{
boost::mutex::scoped_lock lock(this->mutex);
if(sqlite3_prepare16_v2(this->connection,sql,-1,&stmt,NULL)!=SQLITE_OK){
sqlite3_finalize(stmt);
return ReturnCode::Error;
}
}
// Execute the statement
@ -280,6 +288,8 @@ sqlite3_stmt *Connection::GetCachedStatement(const char* sql){
StatementCache::iterator stmt = this->cachedStatements.find(sql);
if(stmt==this->cachedStatements.end()){
boost::mutex::scoped_lock lock(this->mutex);
int err = sqlite3_prepare_v2(this->connection,sql,-1,&newStmt,NULL);
/* #ifdef _DEBUG
if(err!=0){
@ -325,5 +335,6 @@ void Connection::ReturnCachedStatement(const char* sql,sqlite3_stmt *stmt){
///Interrupts the current running statement(s)
//////////////////////////////////////////
void Connection::Interrupt(){
boost::mutex::scoped_lock lock(this->mutex);
sqlite3_interrupt(this->connection);
}

View File

@ -43,6 +43,7 @@
#include <map>
#include <boost/utility.hpp>
#include <boost/thread/mutex.hpp>
namespace musik{ namespace core{ namespace db{
@ -85,6 +86,8 @@ namespace musik{ namespace core{ namespace db{
sqlite3 *connection;
boost::mutex mutex;
};

View File

@ -53,6 +53,7 @@ using namespace musik::core::db;
///database Connection
//////////////////////////////////////////
Statement::Statement(const char* sql,Connection &connection) : connection(&connection),stmt(NULL){
boost::mutex::scoped_lock lock(connection.mutex);
int err = sqlite3_prepare_v2(this->connection->connection,sql,-1,&this->stmt,NULL);
/* #ifdef _DEBUG
if(err!=0){

View File

@ -65,7 +65,7 @@ using namespace musik::cube;
// Connect the local library to the
this->LibraryCallbackTimer.ConnectToWindow(&mainWindow);
this->LibraryCallbackTimer.OnTimout.connect(this,&MainWindowController::QueryQueueLoop);
this->LibraryCallbackTimer.OnTimeout.connect(this,&MainWindowController::QueryQueueLoop);
musik::core::LibraryFactory::GetCurrentLibrary()->OnQueryQueueStart.connect(this,&MainWindowController::QueryQueueStart);
musik::core::LibraryFactory::GetCurrentLibrary()->OnQueryQueueEnd.connect(this,&MainWindowController::QueryQueueEnd);

View File

@ -57,6 +57,7 @@ using namespace musik::cube;
: listView(listView)
, metadataKey(metadataKey)
, parent(browseController)
, selectionDisabled(false)
{
this->metadataKeyA = musik::core::ConvertUTF8(this->metadataKey);
this->model.reset(new MetadataFilterModel(this));
@ -69,27 +70,31 @@ using namespace musik::cube;
void MetadataFilterController::OnSelectionChanged(ListView* listView)
{
win32cpp::ListView::RowIndexList selectedRows(this->listView.SelectedRows());
if(!this->selectionDisabled){
win32cpp::ListView::RowIndexList selectedRows(this->listView.SelectedRows());
musik::core::MetadataValueVector &metadata = ((MetadataFilterModel*)this->model.get())->metadata;
musik::core::MetadataValueVector &metadata = ((MetadataFilterModel*)this->model.get())->metadataFiltered;
this->parent->selectionQuery.ClearMetadata(this->metadataKeyA.c_str());
bool firstRowSelected(false);
for(win32cpp::ListView::RowIndexList::iterator row=selectedRows.begin();row!=selectedRows.end() && !firstRowSelected;++row){
if((*row)==0){
firstRowSelected = true;
}else{
this->parent->selectionQuery.SelectMetadata(this->metadataKeyA.c_str(),metadata[(*row)-1]->id);
}
}
// Check if first row is selected, then clear the list
if(firstRowSelected){
this->parent->selectionQuery.ClearMetadata(this->metadataKeyA.c_str());
}
this->parent->SendQuery();
bool firstRowSelected(false);
for(win32cpp::ListView::RowIndexList::iterator row=selectedRows.begin();row!=selectedRows.end() && !firstRowSelected;++row){
if((*row)==0){
firstRowSelected = true;
}else{
if((*row)<=metadata.size()){
this->parent->selectionQuery.SelectMetadata(this->metadataKeyA.c_str(),metadata[(*row)-1]->id);
}
}
}
// Check if first row is selected, then clear the list
if(firstRowSelected){
this->parent->selectionQuery.ClearMetadata(this->metadataKeyA.c_str());
}
this->parent->SendQuery();
}
}
void MetadataFilterController::OnViewCreated(Window* window)
@ -124,6 +129,18 @@ void MetadataFilterController::OnResized(Window* window, Size size)
void MetadataFilterController::OnChar(Window* window,VirtualKeyCode keyCode, KeyEventFlags keyFlags){
if(keyCode){
win32cpp::RedrawLock drawLock(window);
this->selectionDisabled=true;
((MetadataFilterModel*)this->model.get())->OnChar((wchar_t)keyCode);
this->selectionDisabled=false;
this->OnSelectionChanged(&this->listView);
}
}
void MetadataFilterController::SelectAllFiltered(int rows){
std::vector<int> selectRows;
for(int i(1);i<rows;++i){
selectRows.push_back(i);
}
this->listView.SelectRows(selectRows);
}

View File

@ -61,6 +61,7 @@ private:
public:
/*ctor*/ MetadataFilterController(ListView& listView, const uistring& metdataKey,BrowseController *browseController);
void SelectAllFiltered(int rows);
protected:
void OnViewCreated(Window* window);
@ -68,6 +69,7 @@ protected:
void OnSelectionChanged(ListView* listView);
void OnChar(Window* window,VirtualKeyCode keyCode, KeyEventFlags keyFlags);
uistring currentFilter;
friend class MetadataFilterModel;
@ -78,6 +80,8 @@ protected:
ListView& listView;
ModelRef model;
ColumnRef mainColumn;
bool selectionDisabled;
};
//////////////////////////////////////////////////////////////////////////////

View File

@ -91,8 +91,12 @@ void MetadataFilterModel::OnMetadata(musik::core::MetadataValueVector* me
}
void MetadataFilterModel::OnChar(wchar_t key){
/* if(key){
this->filter += key;
if(key){
if(key==8){
this->filter.resize(this->filter.size()-1);
}else{
this->filter += key;
}
// Lets filter
this->metadataFiltered.clear();
@ -103,5 +107,8 @@ void MetadataFilterModel::OnChar(wchar_t key){
}
}
this->SetRowCount(0);
this->SetRowCount(this->metadataFiltered.size()+1);*/
this->SetRowCount(this->metadataFiltered.size()+1);
this->controller->SelectAllFiltered(this->metadataFiltered.size()+1);
}

View File

@ -67,7 +67,7 @@ void SettingsController::OnViewCreated(Window* window)
this->settingsView.removePathButton->Pressed.connect(this,&SettingsController::OnRemovePath);
this->libraryStatusTimer.ConnectToWindow(&this->settingsView);
this->libraryStatusTimer.OnTimout.connect(this,&SettingsController::OnLibraryStatus);
this->libraryStatusTimer.OnTimeout.connect(this,&SettingsController::OnLibraryStatus);
this->libraryStatusTimer.Start();
this->syncPathController.reset(new musik::cube::settings::SyncPathController(*this->settingsView.pathList,this));

View File

@ -77,6 +77,7 @@ void TracklistController::OnViewCreated(Window* window)
this->AddColumn(_T("Artist"),"visual_artist", 100);
this->AddColumn(_T("Album"),"album", 100);
this->AddColumn(_T("Genre"),"visual_genre", 75);
this->AddColumn(_T("Duration"),"duration", 50);
this->AddColumn(_T("BPM"),"bpm", 75);
int itemHeight = listView->RowHeight();
@ -85,6 +86,7 @@ void TracklistController::OnViewCreated(Window* window)
listView->EnableStripedBackground(true);
listView->SetModel(this->model);
listView->RowActivated.connect(this, &TracklistController::OnRowActivated);
listView->Resized.connect( this, &TracklistController::OnResized);
}
void TracklistController::OnRowActivated(ListView* listView, int row)
@ -122,3 +124,12 @@ void TracklistController::OnTracklistInfo(UINT64 tracks,UINT64 duration,UINT64 f
}
}
}
void TracklistController::OnResized(Window* window, Size size){
int rows = size.height/this->view.listView->RowHeight();
TracklistModel* model = (TracklistModel*)this->model.get();
if(model && rows>10 && rows<100){
model->tracklist->HintNumberOfRows(rows);
}
}

View File

@ -69,7 +69,7 @@ public: /*ctor*/ TracklistController(
musik::core::tracklist::Standard::Ptr tracklist = musik::core::tracklist::Standard::Ptr());
protected: void OnViewCreated(Window* window);
protected: void OnResized(Size size);
protected: void OnResized(Window* window,Size size);
protected: void OnRowActivated(ListView* listView, int row);
protected: void AddColumn(const utfchar *name, const char *metakey, int size);

View File

@ -102,7 +102,7 @@ void TransportController::OnViewCreated(Window* window)
this->playbackSliderTimer.ConnectToWindow(this->transportView.playbackSlider);
this->playbackSliderTimer.OnTimout.connect(this, &TransportController::OnPlaybackSliderTimerTimedOut);
this->playbackSliderTimer.OnTimeout.connect(this, &TransportController::OnPlaybackSliderTimerTimedOut);
}
void TransportController::OnViewResized(Window* window, Size size)

View File

@ -149,4 +149,4 @@ private: // instance data
//////////////////////////////////////////////////////////////////////////////
} // musik::cube::win32cpp
} // win32cpp

View File

@ -987,6 +987,34 @@ int ListView::SelectedRow()
return this->selectedRowIndex;
}
void ListView::SelectRows(const std::vector<int>& indices)
{
std::vector<int>::const_iterator it = indices.begin();
for ( ; it != indices.end(); it++)
{
ListView_SetItemState(this->Handle(), *it, LVIS_FOCUSED | LVIS_SELECTED, LVIS_SELECTED);
}
}
void ListView::SelectRow(int index)
{
ListView_SetItemState(this->Handle(), index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_SELECTED);
}
void ListView::DeselectRows(const std::vector<int>& indices)
{
std::vector<int>::const_iterator it = indices.begin();
for ( ; it != indices.end(); it++)
{
ListView_SetItemState(this->Handle(), *it, 0, LVIS_SELECTED);
}
}
void ListView::DeselectRow(int index)
{
ListView_SetItemState(this->Handle(), index, 0, LVIS_SELECTED);
}
void ListView::SetHotCell(int rowIndex, ColumnRef column)
{
bool rowChanged = false, columnChanged = false;

View File

@ -169,6 +169,10 @@ public: // methods
ColumnRef HotColumn() const;
RowIndexList SelectedRows();
int SelectedRow();
void SelectRows(const std::vector<int>& indices);
void SelectRow(int index);
void DeselectRows(const std::vector<int>& indices);
void DeselectRow(int index);
protected: // methods
virtual HWND Create(Window* parent);

View File

@ -194,4 +194,4 @@ private: // instance data
//////////////////////////////////////////////////////////////////////////////
} // musik::cube::win32cpp
} // win32cpp

View File

@ -71,4 +71,4 @@ protected: // methods
//////////////////////////////////////////////////////////////////////////////
} // musik::cube::win32cpp
} // win32cpp

View File

@ -99,21 +99,6 @@ HWND ProgressBar::Create(Window* parent)
LRESULT ProgressBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
WORD notifyHeader = HIWORD(wParam);
switch (notifyHeader)
{
/*case EN_CHANGE:
this->OnChanged();
return 0; // 0 = processed*/
}
}
break;
}
return this->DefaultWindowProc(message, wParam, lParam);
}
@ -162,10 +147,9 @@ void ProgressBar::StartMarquee(bool set, unsigned int delay)
///The minimum value (unsigned)
///\param max
///The maximum value (unsigned)
DWORD ProgressBar::SetRange(unsigned int min, unsigned int max)
void ProgressBar::SetRange(unsigned int min, unsigned int max)
{
DWORD prevrange = this->SendMessage(PBM_SETRANGE, 0, MAKELPARAM(min,max));
return prevrange;
this->SendMessage(PBM_SETRANGE, 0, MAKELPARAM(min,max));
}
///\brief

View File

@ -63,7 +63,7 @@ public: // constructors, methods
void SetSmoothStyle();
void SetVerticalStyle();
void StartMarquee(bool set, unsigned int delay);
DWORD SetRange(unsigned int min, unsigned int max);
void SetRange(unsigned int min, unsigned int max);
void SetPos(int pos);
void SetStepIncrement(int inc);
void Step();

View File

@ -130,4 +130,4 @@ WindowType* TabView::AddTab(const uistring& tabTitle, WindowType* window)
//////////////////////////////////////////////////////////////////////////////
} // musik::cube::win32cpp
} // win32cpp

View File

@ -1,42 +1,93 @@
//////////////////////////////////////////////////////////////////////////////
//
// License Agreement:
//
// The following are Copyright © 2007, Daniel Önnerby
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.hpp"
#include "Timer.hpp"
//////////////////////////////////////////////////////////////////////////////
using namespace win32cpp;
Timer::Timer(unsigned int timeout) : timeout(timeout), wnd(NULL) {
//////////////////////////////////////////////////////////////////////////////
Timer::Timer(unsigned int timeout)
: timeout(timeout)
, wnd(NULL)
{
static unsigned int staticTimerCounter(0);
++staticTimerCounter;
this->timerId = staticTimerCounter;
this->timerId = staticTimerCounter;
}
Timer::~Timer(void){
Timer::~Timer(void)
{
}
void Timer::ConnectToWindow(win32cpp::Window *window){
void Timer::ConnectToWindow(win32cpp::Window *window)
{
this->wnd = window->Handle();
window->TimerTimeout.connect(this, &Timer::OnTimerMsg);
window->TimerTimeout.connect(this, &Timer::OnTimerTimeout);
}
bool Timer::Start(){
if(SetTimer(this->wnd,this->timerId,this->timeout,NULL)==NULL)
bool Timer::Start()
{
if (::SetTimer(this->wnd, this->timerId, this->timeout, NULL) == NULL)
{
return false;
}
return true;
}
bool Timer::Stop(){
if(KillTimer(this->wnd,this->timerId)==NULL)
bool Timer::Stop()
{
if (::KillTimer(this->wnd, this->timerId) == NULL)
{
return false;
}
return true;
}
void Timer::OnTimerMsg(unsigned int timeoutId){
if(this->timerId==timeoutId){
this->OnTimout();
void Timer::OnTimerTimeout(unsigned int timeoutId)
{
if (this->timerId == timeoutId)
{
this->OnTimeout();
}
}

View File

@ -40,30 +40,41 @@
#include <sigslot/sigslot.h>
#include <win32cpp/Window.hpp>
//////////////////////////////////////////////////////////////////////////////
namespace win32cpp {
class Timer : public sigslot::has_slots<>{
public:
Timer(unsigned int timeout);
~Timer(void);
void ConnectToWindow(win32cpp::Window *window);
//////////////////////////////////////////////////////////////////////////////
bool Start();
bool Stop();
class Timer : public EventHandler
{
public: // types
typedef sigslot::signal0<> TimeoutEvent;
typedef sigslot::signal0<> TimeoutEvent;
TimeoutEvent OnTimout;
public: // events
TimeoutEvent OnTimeout;
private:
unsigned int timerId;
unsigned int timeout;
HWND wnd;
public: // ctor, dtor
Timer(unsigned timeout);
~Timer();
void OnTimerMsg(unsigned int timeoutId);
};
public: // methods
void ConnectToWindow(Window *window);
bool Start();
bool Stop();
typedef boost::shared_ptr<win32cpp::Timer> TimerPtr;
private: // methods
void OnTimerTimeout(unsigned int timeoutId);
}
private: // instance data
unsigned timerId;
unsigned timeout;
HWND wnd;
};
//////////////////////////////////////////////////////////////////////////////
} // namespace
//////////////////////////////////////////////////////////////////////////////

View File

@ -79,7 +79,7 @@ public: /*ctor*/ Trackbar(
public: // methods
void SetRange(short minValue, short maxValue);
int Range() const { return this->maxValue - this->minValue; }
short Range() { return this->maxValue - this->minValue; }
int MinValue() const { return this->minValue; }
int MaxValue() const { return this->maxValue; }
void SetTickFrequency(short tickFrequency = 0);

View File

@ -83,4 +83,4 @@ typedef sigslot::has_slots<> EventHandler;
//////////////////////////////////////////////////////////////////////////////
} // namespace musik::cube::win32cpp
} // namespace win32cpp