From 926f5ddfbee702ef829083dae06d0e3dc40744c2 Mon Sep 17 00:00:00 2001 From: shatty Date: Sat, 16 Aug 2003 00:57:12 +0000 Subject: [PATCH] version 1.0 of Jonas Sundstrom's ZipOMatic app/add-on git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4282 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/Jamfile | 1 + src/add-ons/tracker/Jamfile | 4 + .../tracker/zipomatic/GenericThread.cpp | 386 +++++++++++++++++ src/add-ons/tracker/zipomatic/GenericThread.h | 83 ++++ src/add-ons/tracker/zipomatic/Jamfile | 19 + src/add-ons/tracker/zipomatic/ZipOMatic.cpp | 187 +++++++++ src/add-ons/tracker/zipomatic/ZipOMatic.h | 28 ++ .../tracker/zipomatic/ZipOMatic.icons.rdef | 59 +++ src/add-ons/tracker/zipomatic/ZipOMatic.rdef | 12 + .../tracker/zipomatic/ZipOMatic.version.rdef | 20 + .../tracker/zipomatic/ZipOMaticActivity.cpp | 232 +++++++++++ .../tracker/zipomatic/ZipOMaticActivity.h | 42 ++ .../tracker/zipomatic/ZipOMaticMisc.cpp | 47 +++ src/add-ons/tracker/zipomatic/ZipOMaticMisc.h | 24 ++ .../tracker/zipomatic/ZipOMaticSettings.cpp | 140 +++++++ .../tracker/zipomatic/ZipOMaticSettings.h | 36 ++ .../tracker/zipomatic/ZipOMaticView.cpp | 87 ++++ src/add-ons/tracker/zipomatic/ZipOMaticView.h | 31 ++ .../tracker/zipomatic/ZipOMaticWindow.cpp | 328 +++++++++++++++ .../tracker/zipomatic/ZipOMaticWindow.h | 46 +++ .../tracker/zipomatic/ZipOMaticZipper.cpp | 388 ++++++++++++++++++ .../tracker/zipomatic/ZipOMaticZipper.h | 61 +++ 22 files changed, 2261 insertions(+) create mode 100644 src/add-ons/tracker/Jamfile create mode 100644 src/add-ons/tracker/zipomatic/GenericThread.cpp create mode 100644 src/add-ons/tracker/zipomatic/GenericThread.h create mode 100644 src/add-ons/tracker/zipomatic/Jamfile create mode 100644 src/add-ons/tracker/zipomatic/ZipOMatic.cpp create mode 100644 src/add-ons/tracker/zipomatic/ZipOMatic.h create mode 100644 src/add-ons/tracker/zipomatic/ZipOMatic.icons.rdef create mode 100644 src/add-ons/tracker/zipomatic/ZipOMatic.rdef create mode 100644 src/add-ons/tracker/zipomatic/ZipOMatic.version.rdef create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticActivity.h create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticMisc.cpp create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticMisc.h create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticSettings.cpp create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticSettings.h create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticView.cpp create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticView.h create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticWindow.h create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticZipper.cpp create mode 100644 src/add-ons/tracker/zipomatic/ZipOMaticZipper.h diff --git a/src/add-ons/Jamfile b/src/add-ons/Jamfile index 1f7cf846eb..e214f479be 100644 --- a/src/add-ons/Jamfile +++ b/src/add-ons/Jamfile @@ -84,4 +84,5 @@ SubInclude OBOS_TOP src add-ons media ; SubInclude OBOS_TOP src add-ons print ; SubInclude OBOS_TOP src add-ons translators ; SubInclude OBOS_TOP src add-ons decorators ; +SubInclude OBOS_TOP src add-ons tracker ; diff --git a/src/add-ons/tracker/Jamfile b/src/add-ons/tracker/Jamfile new file mode 100644 index 0000000000..a9a22572f0 --- /dev/null +++ b/src/add-ons/tracker/Jamfile @@ -0,0 +1,4 @@ +SubDir OBOS_TOP src add-ons tracker ; + +SubInclude OBOS_TOP src add-ons tracker zipomatic ; + diff --git a/src/add-ons/tracker/zipomatic/GenericThread.cpp b/src/add-ons/tracker/zipomatic/GenericThread.cpp new file mode 100644 index 0000000000..3006520817 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/GenericThread.cpp @@ -0,0 +1,386 @@ +// license: public domain +// authors: jonas.sundstrom@kirilla.com + +#include + +GenericThread::GenericThread(const char * a_thread_name, int32 a_priority, BMessage * a_message) + : + m_thread_data_store (a_message), + m_thread_id (spawn_thread (private_thread_function, a_thread_name, a_priority, this)), + m_execute_unit (create_sem(1, "m_execute_unit")), + m_quit_requested (false), + m_thread_is_paused (false) +{ + if (m_thread_data_store == NULL) + m_thread_data_store = new BMessage(); +} + +GenericThread::~GenericThread() +{ + kill_thread(m_thread_id); + + delete_sem(m_execute_unit); +} + +status_t +GenericThread::ThreadFunction (void) +{ + status_t status = B_OK; + + status = ThreadStartup(); // Subclass and override this function + if (status != B_OK) + { + ThreadStartupFailed (status); + return (status); + // is this the right thing to do? + } + + while(1) + { + if (HasQuitBeenRequested()) + { + status = ThreadShutdown(); // Subclass and override this function + if (status != B_OK) + { + ThreadShutdownFailed (status); + return (status); + // what do we do? + } + + delete this; // destructor + } + + BeginUnit(); + + status = ExecuteUnit(); // Subclass and override + + if (status != B_OK) + ExecuteUnitFailed (status); // Subclass and override + + EndUnit(); + } + + return (B_OK); +} + +status_t +GenericThread::ThreadStartup (void) +{ + // This function is virtual. + // Subclass and override this function. + + return B_OK; +} + + +status_t +GenericThread::ExecuteUnit (void) +{ + // This function is virtual. + + // You would normally subclass and override this function + // as it will provide you with Pause and Quit functionality + // thanks to the unit management done by GenericThread::ThreadFunction() + + return B_OK; +} + +status_t +GenericThread::ThreadShutdown (void) +{ + // This function is virtual. + // Subclass and override this function. + + return B_OK; +} + +void +GenericThread::ThreadStartupFailed (status_t a_status) +{ + // This function is virtual. + // Subclass and override this function. + + Quit(); +} + +void +GenericThread::ExecuteUnitFailed (status_t a_status) +{ + // This function is virtual. + // Subclass and override this function. + + Quit(); +} + +void +GenericThread::ThreadShutdownFailed (status_t a_status) +{ + // This function is virtual. + // Subclass and override this function. + + // (is this good default behaviour?) +} + +status_t +GenericThread::Start (void) +{ + status_t status = B_OK; + + if (IsPaused()) + { + status = release_sem (m_execute_unit); + if (status != B_OK) + return status; + + m_thread_is_paused = false; + } + + status = resume_thread (m_thread_id); + + return status; +} + +int32 +GenericThread::private_thread_function (void * a_simple_thread_ptr) +{ + status_t status = B_OK; + + status = ((GenericThread *) a_simple_thread_ptr)-> ThreadFunction(); + + return (status); +} + +BMessage * +GenericThread::GetDataStore (void) +{ + return (m_thread_data_store); +} + +void +GenericThread::SetDataStore (BMessage * a_message) +{ + m_thread_data_store = a_message; +} + +status_t +GenericThread::Pause (bool a_do_block, bigtime_t a_timeout) +{ + status_t status = B_OK; + + if (a_do_block) + status = acquire_sem(m_execute_unit); + // thread will wait on semaphore + else + status = acquire_sem_etc(m_execute_unit, 1, B_RELATIVE_TIMEOUT, a_timeout); + // thread will timeout + + if (status == B_OK) + { + m_thread_is_paused = true; + return (B_OK); + } + + return status; +} + +void +GenericThread::Quit (void) +{ + m_quit_requested = true; +} + +bool +GenericThread::HasQuitBeenRequested (void) +{ + return (m_quit_requested); +} + +bool +GenericThread::IsPaused (void) +{ + return (m_thread_is_paused); +} + +status_t +GenericThread::Suspend (void) +{ + return (suspend_thread(m_thread_id)); +} + +status_t +GenericThread::Resume (void) +{ + release_sem(m_execute_unit); // to counteract Pause() + m_thread_is_paused = false; + + return (resume_thread(m_thread_id)); // to counteract Suspend() +} + +status_t +GenericThread::Kill (void) +{ + return (kill_thread(m_thread_id)); +} + +void +GenericThread::ExitWithReturnValue (status_t a_return_value) +{ + exit_thread(a_return_value); +} + +status_t +GenericThread::SetExitCallback (void (*a_callback)(void*), void * a_data) +{ + return (on_exit_thread(a_callback, a_data)); +} + +status_t +GenericThread::WaitForThread (status_t * a_exit_value) +{ + return (wait_for_thread(m_thread_id, a_exit_value)); +} + +status_t +GenericThread::Rename (char * a_name) +{ + return (rename_thread(m_thread_id, a_name)); +} + +status_t +GenericThread::SendData (int32 a_code, void * a_buffer, size_t a_buffer_size) +{ + return (send_data(m_thread_id, a_code, a_buffer, a_buffer_size)); +} + +int32 +GenericThread::ReceiveData (thread_id * a_sender, void * a_buffer, size_t a_buffer_size) +{ + return (receive_data(a_sender, a_buffer, a_buffer_size)); +} + +bool +GenericThread::HasData (void) +{ + return (has_data(m_thread_id)); +} + +status_t +GenericThread::SetPriority (int32 a_new_priority) +{ + return (set_thread_priority(m_thread_id, a_new_priority)); +} + +void +GenericThread::Snooze (bigtime_t a_microseconds) +{ + Suspend(); + snooze(a_microseconds); + Resume(); +} + +void +GenericThread::SnoozeUntil (bigtime_t a_microseconds, int a_timebase) +{ + Suspend(); + snooze_until(a_microseconds, a_timebase); + Resume(); +} + +status_t +GenericThread::GetInfo (thread_info * a_thread_info) +{ + return (get_thread_info(m_thread_id, a_thread_info)); +} + +thread_id +GenericThread::GetThread (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.thread); +} + +team_id +GenericThread::GetTeam (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.team); +} + +char * +GenericThread::GetName (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.name); +} + +thread_state +GenericThread::GetState (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.state); +} + +sem_id +GenericThread::GetSemaphore (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.sem); +} + +int32 +GenericThread::GetPriority (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.priority); +} + +bigtime_t +GenericThread::GetUserTime (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.user_time); +} + +bigtime_t +GenericThread::GetKernelTime (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.kernel_time); +} + +void * +GenericThread::GetStackBase (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.stack_base); +} + +void * +GenericThread::GetStackEnd (void) +{ + thread_info t_thread_info; + GetInfo (& t_thread_info); + return (t_thread_info.stack_end); +} + +void +GenericThread::BeginUnit (void) +{ + acquire_sem(m_execute_unit); // thread can not be paused until it releases semaphore +} + +void +GenericThread::EndUnit (void) +{ + release_sem(m_execute_unit); // thread can now be paused +} + diff --git a/src/add-ons/tracker/zipomatic/GenericThread.h b/src/add-ons/tracker/zipomatic/GenericThread.h new file mode 100644 index 0000000000..3a2d8c698b --- /dev/null +++ b/src/add-ons/tracker/zipomatic/GenericThread.h @@ -0,0 +1,83 @@ +#ifndef __GENERIC_THREAD_H__ +#define __GENERIC_THREAD_H__ + +#include +#include + +class GenericThread +{ + public: + GenericThread (const char * a_thread_name = "generic_thread", int32 a_priority = B_NORMAL_PRIORITY, BMessage * a_message = NULL); + virtual ~GenericThread (void); + + BMessage * GetDataStore (void); + void SetDataStore (BMessage * a_message); + + status_t Start (void); + status_t Pause (bool a_do_block = TRUE, bigtime_t a_timeout = 0); + void Quit (void); + bool IsPaused (void); + bool HasQuitBeenRequested (void); + + status_t Suspend (void); + status_t Resume (void); + status_t Kill (void); + + void ExitWithReturnValue (status_t a_return_value); + status_t SetExitCallback (void (* a_callback)(void *), void * a_data); + status_t WaitForThread (status_t * a_exit_value); + + status_t Rename (char * a_name); + + status_t SendData (int32 a_code, void * a_buffer, size_t a_buffer_size); + int32 ReceiveData (thread_id * a_sender, void * a_buffer, size_t a_buffer_size); + bool HasData (void); + + status_t SetPriority (int32 a_new_priority); + + void Snooze (bigtime_t a_microseconds); + void SnoozeUntil (bigtime_t a_microseconds, int a_timebase = B_SYSTEM_TIMEBASE); + + + status_t GetInfo (thread_info * a_thread_info); + thread_id GetThread (void); + team_id GetTeam (void); + char * GetName (void); + thread_state GetState (void); + sem_id GetSemaphore (void); + int32 GetPriority (void); + bigtime_t GetUserTime (void); + bigtime_t GetKernelTime (void); + void * GetStackBase (void); + void * GetStackEnd (void); + + protected: + + virtual status_t ThreadFunction (void); + virtual status_t ThreadStartup (void); + virtual status_t ExecuteUnit (void); + virtual status_t ThreadShutdown (void); + + virtual void ThreadStartupFailed (status_t a_status); + virtual void ExecuteUnitFailed (status_t a_status); + virtual void ThreadShutdownFailed (status_t a_status); + + void BeginUnit (void); // acquire m_execute_cycle + void EndUnit (void); // release m_execute_cycle + + BMessage * m_thread_data_store; + + private: + + static status_t private_thread_function (void * a_simple_thread_ptr); + + thread_id m_thread_id; + + sem_id m_execute_unit; // acq./relase within tread_function.. For Pause() + + bool m_quit_requested; + bool m_thread_is_paused; + +}; + +#endif diff --git a/src/add-ons/tracker/zipomatic/Jamfile b/src/add-ons/tracker/zipomatic/Jamfile new file mode 100644 index 0000000000..5f5a89738c --- /dev/null +++ b/src/add-ons/tracker/zipomatic/Jamfile @@ -0,0 +1,19 @@ +SubDir OBOS_TOP src add-ons tracker zipomatic ; + +AddResources ZipOMatic-Z : + ZipOMatic.rdef ZipOMatic.icons.rdef ZipOMatic.version.rdef + ; + +App ZipOMatic-Z : + GenericThread.cpp + ZipOMatic.cpp + ZipOMaticActivity.cpp + ZipOMaticMisc.cpp + ZipOMaticSettings.cpp + ZipOMaticView.cpp + ZipOMaticWindow.cpp + ZipOMaticZipper.cpp + ; +MakeLocate ZipOMatic-Z : [ FDirName $(OBOS_ADDON_DIR) Tracker ] ; + +LinkSharedOSLibs ZipOMatic-Z : be tracker ; diff --git a/src/add-ons/tracker/zipomatic/ZipOMatic.cpp b/src/add-ons/tracker/zipomatic/ZipOMatic.cpp new file mode 100644 index 0000000000..350c54327c --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMatic.cpp @@ -0,0 +1,187 @@ +// license: public domain +// authors: jonas.sundstrom@kirilla.com + +#include +#include +#include + +#include +#include +#include + +extern "C" void +process_refs(entry_ref dir_ref, BMessage * msg, void *) +{ + msg->AddRef("dir_ref", & dir_ref); + + status_t status = B_OK; + type_code ref_type = B_REF_TYPE; + int32 ref_count = 0; + + status = msg->GetInfo("refs", & ref_type, & ref_count); + if (status != B_OK || ref_count < 1) + be_roster->Launch (ZIPOMATIC_APP_SIG); + else + be_roster->Launch (ZIPOMATIC_APP_SIG, msg ); +} + +int main() +{ + ZipOMatic app; + app.Run(); + + return (0); +} + +ZipOMatic::ZipOMatic (void) + : BApplication (ZIPOMATIC_APP_SIG), + m_got_refs (false) +{ + PRINT(("ZipOMatic::ZipOMatic()\n")); + + // void +} + +ZipOMatic::~ZipOMatic (void) +{ + PRINT(("ZipOMatic::~ZipOMatic()\n")); + + fflush(stdout); +} + +void +ZipOMatic::RefsReceived (BMessage * a_message) +{ + PRINT(("ZipOMatic::RefsReceived()\n")); + + if (IsLaunching()) + m_got_refs = true; + + BMessage * msg = new BMessage (* a_message); + + UseExistingOrCreateNewWindow(msg); +} + +void +ZipOMatic::ReadyToRun (void) +{ + PRINT(("ZipOMatic::ReadyToRun()\n")); + + if (m_got_refs) + { + // nothing - wait on window(s) to finish + } + else + UseExistingOrCreateNewWindow(); +} + +void +ZipOMatic::MessageReceived (BMessage * a_message) +{ + PRINT(("ZipOMatic::MessageReceived()\n")); + + switch(a_message->what) + { + case ZIPPO_WINDOW_QUIT: + + snooze (200000); + if (CountWindows() == 0) + Quit(); + break; + + case B_SILENT_RELAUNCH: + + SilentRelaunch(); + break; + + default: BApplication::MessageReceived(a_message); break; + } + +} + +bool +ZipOMatic::QuitRequested (void) +{ + // intelligent (?) closing of the windows + // + // overriding BApplication::QuitRequested(); + + if (CountWindows() <= 0) + return true; + + BList window_list (5); + int32 window_count = 0; + BWindow * window; + + // build list of windows + while (1) + { + window = WindowAt(window_count++); + if (window == NULL) + break; + + window_list.AddItem(window); + } + + // ask windows to quit + while (1) + { + window = (BWindow *) window_list.RemoveItem(int32(0)); + if (window == NULL) + break; + + if (window->Lock()) + { + window->PostMessage(B_QUIT_REQUESTED); + window->Unlock(); + } + } + + PRINT(("CountWindows(): %ld\n", CountWindows())); + + if (CountWindows() <= 0) + return true; + + return false; // default: stay alive +} + +void +ZipOMatic::SilentRelaunch (void) +{ + UseExistingOrCreateNewWindow(); +} + +void +ZipOMatic::UseExistingOrCreateNewWindow (BMessage * a_message) +{ + int32 window_count = 0; + ZippoWindow * window; + bool found_non_busy_window = false; + + while (1) + { + window = dynamic_cast(WindowAt(window_count++)); + if (window == NULL) + break; + + if (window->Lock()) + { + if (! window->IsZipping()) + { + found_non_busy_window = true; + if (a_message != NULL) + window->PostMessage(a_message); + window->Activate(); + window->Unlock(); + break; + } + window->Unlock(); + } + } + + if (! found_non_busy_window) + { + ZippoWindow * m_window = new ZippoWindow(a_message); + m_window->Show(); + } +} diff --git a/src/add-ons/tracker/zipomatic/ZipOMatic.h b/src/add-ons/tracker/zipomatic/ZipOMatic.h new file mode 100644 index 0000000000..57f4845ebb --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMatic.h @@ -0,0 +1,28 @@ +#ifndef _ZIPOMATIC_H_ +#define _ZIPOMATIC_H_ + +#include +#include + +class ZipOMatic : public BApplication +{ +public: + ZipOMatic (void); + ~ZipOMatic (void); + + virtual void ReadyToRun (void); + virtual void RefsReceived (BMessage * a_message); + virtual void MessageReceived (BMessage * a_message); + virtual bool QuitRequested (void); + + void SilentRelaunch (void); + void UseExistingOrCreateNewWindow (BMessage * a_message = NULL); + +private: + + bool m_got_refs; + + +}; + +#endif // _ZIPOMATIC_H_ diff --git a/src/add-ons/tracker/zipomatic/ZipOMatic.icons.rdef b/src/add-ons/tracker/zipomatic/ZipOMatic.icons.rdef new file mode 100644 index 0000000000..4cd4d2e3ab --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMatic.icons.rdef @@ -0,0 +1,59 @@ +/* +** ZipOMatic.icons.rdef +** +*/ + +resource large_icon array { + $"FFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFF00FAFAFAFA0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFF00FAFAFAFAFAFA5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFF00FAFAFAFAFA5D5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFF003FF9F9FA5D5D5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFF007D3FF9F9F95D5D5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFF007D7D3FF9F9F95D5D5D00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FF003F3F7D3FF9F9F95D5D5D00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFF00F93F3FF9F9F95D5D5D0000D9D90000FFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFF00F9F93FF9F9F95D5D7D7D7D0000D9D90000FFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFF00F9F9F9F9F93F3F7D7D7D00D9D9D9D9D90000FFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFF00F9F9F9F9F9F93F7D00D9D9D9D9D9D900D90000FFFFFFFFFFFFFFFF" + $"FFFFFFFF00F9F9F9F9F9F90000D9D900D9D9D900D9D9D9D90000FFFFFFFFFFFF" + $"FFFFFFFFFF00F9F9F9F900D9D9D9D900D9D900D9D9D9D9D9D9D90000FFFFFFFF" + $"FFFFFFFF00D900F90000000000000000D900D9D9D9D9D9D9D9D9D9D900FFFFFF" + $"FFFFFF00D9D9D900D9000000D9D9000000D9D9D9D9D9D9D9D9D9D9D9D900FFFF" + $"FFFF00D9D9D9D9D9D900D9D90000D900000000000000D9D9D9D9D9D9D9D900FF" + $"FF00D9D9D9D9D9D9D9D9000000D9000000D9D9D9D9D900D9D9D9D9D9D98300FF" + $"FF00D9D9D9D9D9D9D9D9D9D9D900D9D90000D9D90000D9D9D9D9D9D9838300FF" + $"00D9D9D9D9D9D9D9D9D9D9D900D9D900D900000000D9D9D9D9D9D983838300FF" + $"00D9D9D9D9D9D9D9D9D9D900D9D9D900D9D9D9D9D90000D9D9D98383838300FF" + $"00D9D9D9D9D9D9D9D9D900D9D9D9D9D9D9D9D9D9D9D9D900008383838300FFFF" + $"FF00D9D9D9D9D9D9D900D9D9D9D9D9D9D9D9D9D9D9D9D9D90083838300FFFFFF" + $"FFFF0000D9D9D9D9D901D9D9D9D9D9D9D9D9D9D9D9D9D98300838300FFFFFFFF" + $"FFFFFFFF0000D9D9D901D9D9D9D9D9D9D9D9D9D9D9D98383008300FFFFFFFFFF" + $"FFFFFFFFFFFF0000D900D9D9D9D9D9D9D9D9D9D9D98383830000FFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFF0000D9D9D9D9D9D9D9D9D9D98383838300FFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFF0000D9D9D9D9D9D9D98383838301FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF0000D9D9D9D98383838301FFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFF0000D9D983830100FFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +}; + +resource mini_icon array { + $"FFFFFFFF000000FFFFFFFFFFFFFFFFFF" + $"FFFFFF00FAFA5D00FFFFFFFFFFFFFFFF" + $"FFFF003F3F3F5D00FFFFFFFFFFFFFFFF" + $"FFFF003FF9F95D0000FFFFFFFFFFFFFF" + $"FF00003FF9F95D00D90000FFFFFFFFFF" + $"007D003FF9F95D7D00D9000000FFFFFF" + $"3F00F9F9F9F93F008300D9D9D90000FF" + $"3F0000F9F9F90000000000D9D9D98300" + $"00D9D900F900000083D9D900D93F8300" + $"00D93FD900830000000000D93F838300" + $"00D9D9D9D900D900D9D9D901008300FF" + $"0000D9D9003FD900D9D93F830000FFFF" + $"FFFF000000D9D93FD93F838300FFFFFF" + $"FFFFFFFF0000D9D9D9838301FFFFFFFF" + $"FFFFFFFFFFFF0000D98301FFFFFFFFFF" + $"FFFFFFFFFFFFFFFF0000FFFFFFFFFFFF" +}; + diff --git a/src/add-ons/tracker/zipomatic/ZipOMatic.rdef b/src/add-ons/tracker/zipomatic/ZipOMatic.rdef new file mode 100644 index 0000000000..6636bd30e5 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMatic.rdef @@ -0,0 +1,12 @@ +/* +** ZipOMatic.rdef +** +*/ + +resource app_signature "application/x-vnd.obos.zip-o-matic"; + +resource app_flags 0x00000000; + +resource file_types message { + "types" = "application/octet-stream" +}; diff --git a/src/add-ons/tracker/zipomatic/ZipOMatic.version.rdef b/src/add-ons/tracker/zipomatic/ZipOMatic.version.rdef new file mode 100644 index 0000000000..178c8ca12f --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMatic.version.rdef @@ -0,0 +1,20 @@ +/* +** ZipOMatic.version.rdef +** +*/ + +resource app_version { + + major = 1, + middle = 0, + minor = 0, + + /* 0 = development 1 = alpha 2 = beta + 3 = gamma 4 = golden master 5 = final */ + variety = 0, + + internal = 1, + + short_info = "R1.0.0d1", + long_info = "OpenBeOS 1.0.0d1 ©2003 OpenBeOS Project" +}; diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp new file mode 100644 index 0000000000..7a85cc7400 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp @@ -0,0 +1,232 @@ +// license: public domain +// authors: jonas.sundstrom@kirilla.com + +#include + +Activity::Activity (BRect a_rect, const char * a_name, uint32 a_resizing_mode, uint32 a_flags) +: BBox (a_rect, a_name, a_resizing_mode, a_flags), + m_is_running (false), + m_barberpole_bitmap (NULL) +{ + m_pattern.data[0] = 0x0f; + m_pattern.data[1] = 0x1e; + m_pattern.data[2] = 0x3c; + m_pattern.data[3] = 0x78; + m_pattern.data[4] = 0xf0; + m_pattern.data[5] = 0xe1; + m_pattern.data[6] = 0xc3; + m_pattern.data[7] = 0x87; + + CreateBitmap(); +}; + +Activity::~Activity() +{ + // subviews are deleted by superclass + + delete m_barberpole_bitmap; +} + +void +Activity::Start() +{ + m_is_running = true; + Window()->SetPulseRate(100000); + SetFlags(Flags() | B_PULSE_NEEDED); + SetViewColor(B_TRANSPARENT_COLOR); + Invalidate(); +} + +void +Activity::Pause() +{ + Window()->SetPulseRate(500000); + SetFlags(Flags() & (~ B_PULSE_NEEDED)); + Invalidate(); +} + +void +Activity::Stop() +{ + m_is_running = false; + Window()->SetPulseRate(500000); + SetFlags(Flags() & (~ B_PULSE_NEEDED)); + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + Invalidate(); +} + +bool +Activity::IsRunning() +{ + return m_is_running; +} + +void +Activity::Pulse() +{ + uchar tmp = m_pattern.data[7]; + + for (int j = 7; j > 0; --j) + { + m_pattern.data[j] = m_pattern.data[j-1]; + } + + m_pattern.data[0] = tmp; + + DrawIntoBitmap(); + + Invalidate(); +} + +void +Activity::Draw(BRect a_rect) +{ + if (IsRunning()) + { + // draw BBox outline + BBox::Draw(a_rect); + SetDrawingMode(B_OP_COPY); + DrawBitmap(m_barberpole_bitmap); + } + else + { + BBox::Draw(a_rect); + + float string_width = StringWidth("Drop files to zip."); + float view_width = Bounds().Width(); + + MovePenTo ((view_width/2)-(string_width/2),12); + DrawString("Drop files to zip."); + } +} + +void Activity::DrawIntoBitmap (void) +{ + if (m_barberpole_bitmap->Lock()) + { + BRect a_rect = m_barberpole_bitmap->Bounds(); + + m_barberpole_bitmap_view->SetDrawingMode(B_OP_COPY); + + rgb_color color; + color.red = 0; + color.green = 0; + color.blue = 200; + color.alpha = 255; + m_barberpole_bitmap_view->SetHighColor(color); + + // draw the pole + a_rect.InsetBy(2,2); + m_barberpole_bitmap_view->FillRect(a_rect, m_pattern); + + // draw frame + + // left + color.red = 150; + color.green = 150; + color.blue = 150; + m_barberpole_bitmap_view->SetHighColor(color); + BPoint point_a = m_barberpole_bitmap->Bounds().LeftTop(); + BPoint point_b = m_barberpole_bitmap->Bounds().LeftBottom(); + point_b.y -= 1; + m_barberpole_bitmap_view->StrokeLine(point_a, point_b); + point_a.x += 1; + point_b.x += 1; + point_b.y -= 1; + m_barberpole_bitmap_view->StrokeLine(point_a, point_b); + + // top + m_barberpole_bitmap_view->SetDrawingMode(B_OP_OVER); + m_barberpole_bitmap_view->SetHighColor(color); + point_a = m_barberpole_bitmap->Bounds().LeftTop(); + point_b = m_barberpole_bitmap->Bounds().RightTop(); + point_b.x -= 1; + m_barberpole_bitmap_view->StrokeLine(point_a, point_b); + point_a.y += 1; + point_b.y += 1; + point_b.x -= 1; + m_barberpole_bitmap_view->StrokeLine(point_a, point_b); + + // right + color.red = 255; + color.green = 255; + color.blue = 255; + m_barberpole_bitmap_view->SetHighColor(color); + point_a = m_barberpole_bitmap->Bounds().RightTop(); + point_b = m_barberpole_bitmap->Bounds().RightBottom(); + m_barberpole_bitmap_view->StrokeLine(point_a, point_b); + point_a.y += 1; + point_a.x -= 1; + point_b.x -= 1; + m_barberpole_bitmap_view->StrokeLine(point_a, point_b); + + // bottom + m_barberpole_bitmap_view->SetHighColor(color); + point_a = m_barberpole_bitmap->Bounds().LeftBottom(); + point_b = m_barberpole_bitmap->Bounds().RightBottom(); + m_barberpole_bitmap_view->StrokeLine(point_a, point_b); + point_a.x += 1; + point_a.y -= 1; + point_b.y -= 1; + m_barberpole_bitmap_view->StrokeLine(point_a, point_b); + + // some blending + color.red = 150; + color.green = 150; + color.blue = 150; + m_barberpole_bitmap_view->SetHighColor(color); + m_barberpole_bitmap_view->SetDrawingMode(B_OP_SUBTRACT); + m_barberpole_bitmap_view->StrokeRect(a_rect); + + a_rect.InsetBy(1,1); + LightenBitmapHighColor(& color); + m_barberpole_bitmap_view->StrokeRect(a_rect); + + a_rect.InsetBy(1,1); + LightenBitmapHighColor(& color); + m_barberpole_bitmap_view->StrokeRect(a_rect); + + a_rect.InsetBy(1,1); + LightenBitmapHighColor(& color); + m_barberpole_bitmap_view->StrokeRect(a_rect); + + a_rect.InsetBy(1,1); + LightenBitmapHighColor(& color); + m_barberpole_bitmap_view->StrokeRect(a_rect); + + m_barberpole_bitmap_view->Flush(); + } + + m_barberpole_bitmap->Unlock(); +} + +void Activity::LightenBitmapHighColor (rgb_color * a_color) +{ + a_color->red -= 30; + a_color->green -= 30; + a_color->blue -= 30; + + m_barberpole_bitmap_view->SetHighColor(* a_color); +} + +void Activity::CreateBitmap (void) +{ + BRect barberpole_rect = Bounds(); + m_barberpole_bitmap = new BBitmap(barberpole_rect, B_CMAP8, true); + m_barberpole_bitmap_view = new BView(Bounds(), "buffer", B_FOLLOW_NONE, 0); + m_barberpole_bitmap->AddChild(m_barberpole_bitmap_view); +} + +void Activity::FrameMoved (BPoint a_point) +{ + delete m_barberpole_bitmap; + CreateBitmap(); + Invalidate(); +} + +void Activity::FrameResized (float a_width, float a_height) +{ + delete m_barberpole_bitmap; + CreateBitmap(); + Invalidate(); +} diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticActivity.h b/src/add-ons/tracker/zipomatic/ZipOMaticActivity.h new file mode 100644 index 0000000000..9848105487 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticActivity.h @@ -0,0 +1,42 @@ +#ifndef _ACTIVITY_H_ +#define _ACTIVITY_H_ + +#include + +#include +#include +#include +#include + +class Activity : public BBox +{ + public: + Activity (BRect a_rect, const char * a_name, uint32 a_resizing_mode, + uint32 a_flags); + ~Activity (); + + void Start (); + void Pause (); + void Stop (); + bool IsRunning (); + virtual void Pulse (); + virtual void Draw (BRect a_draw); + virtual void FrameMoved (BPoint a_point); + virtual void FrameResized (float a_width, float a_height); + + protected: + void CreateBitmap (void); + void LightenBitmapHighColor (rgb_color * a_color); + void DrawIntoBitmap (void); + + bool m_is_running; + pattern m_pattern; + + BBitmap * m_barberpole_bitmap; + BView * m_barberpole_bitmap_view; + + private: + +}; + +#endif diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticMisc.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticMisc.cpp new file mode 100644 index 0000000000..4f24ffbec4 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticMisc.cpp @@ -0,0 +1,47 @@ +// license: public domain +// authors: jonas.sundstrom@kirilla.com + +#include + +#include + +status_t +find_and_create_directory (directory_which a_which, BVolume * a_volume, const char * a_relative_path, BPath * a_full_path) +{ + status_t status = B_OK; + BPath path; + mode_t mask = 0; + + status = find_directory (a_which, & path, true, a_volume); // create = true + + if (status != B_OK) + return status; + + if (a_relative_path != NULL) + { + path.Append(a_relative_path); + + mask = umask (0); + umask (mask); + + status = create_directory (path.Path(), mask); + if (status != B_OK) + return status; + } + + if (a_full_path != NULL) + { + status = a_full_path->SetTo(path.Path()); + if (status != B_OK) + return status; + } + + return B_OK; +} + +void +error_message (const char * a_text, int32 a_status) +{ + PRINT(("%s: %s\n", a_text, strerror(a_status))); +} + diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticMisc.h b/src/add-ons/tracker/zipomatic/ZipOMaticMisc.h new file mode 100644 index 0000000000..d975239237 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticMisc.h @@ -0,0 +1,24 @@ +#ifndef __ZIPOMATIC_MISC__ +#define __ZIPOMATIC_MISC__ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ZIPOMATIC_APP_SIG "application/x-vnd.obos.zip-o-matic" +#define ZIPOMATIC_APP_NAME "ZipOMatic" + +#define ZIPPO_WINDOW_QUIT 'winq' + +status_t find_and_create_directory (directory_which a_which, BVolume * a_volume = NULL, const char * a_relative_path = NULL, BPath * a_full_path = NULL); + +void error_message (const char * a_text, int32 a_status); + +#endif // __ZIPOMATIC_MISC__ + diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticSettings.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticSettings.cpp new file mode 100644 index 0000000000..bcfa50797a --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticSettings.cpp @@ -0,0 +1,140 @@ +// license: public domain +// authors: jonas.sundstrom@kirilla.com + +// +// TODO: proper locking <<--------- +// + +#include + +#include +#include +#include +#include +#include + +#include +#include + +ZippoSettings::ZippoSettings() +: BMessage (), + m_volume (), + m_base_dir (B_USER_SETTINGS_DIRECTORY), + m_relative_path (), + m_settings_filename () +{ + PRINT(("ZippoSettings()\n")); +} + +ZippoSettings::ZippoSettings(BMessage a_message) +: BMessage (a_message), + m_volume (), + m_base_dir (B_USER_SETTINGS_DIRECTORY), + m_relative_path (), + m_settings_filename () +{ + PRINT(("ZippoSettings(a_message)\n")); +} + +ZippoSettings::~ZippoSettings() +{ + m_volume.Unset(); +} + +status_t +ZippoSettings::SetTo (const char * a_settings_filename, + BVolume * a_volume, + directory_which a_base_dir, + const char * a_relative_path) +{ + status_t status = B_OK; + + // copy to members + m_base_dir = a_base_dir; + m_relative_path = a_relative_path; + m_settings_filename = a_settings_filename; + + // sanity check + if (a_volume == NULL) + { + BVolumeRoster volume_roster; + volume_roster.GetBootVolume(& m_volume); + } + else + m_volume = *(a_volume); + + status = m_volume.InitCheck(); + if (status != B_OK) + return status; + + // InitCheck + return InitCheck(); +} + +status_t +ZippoSettings::InitCheck (void) +{ + BFile settings_file; + + return GetSettingsFile (& settings_file, B_READ_ONLY | B_CREATE_FILE); +} + +status_t +ZippoSettings::GetSettingsFile (BFile * a_settings_file, uint32 a_openmode) +{ + status_t status = B_OK; + BPath settings_path; + + status = find_and_create_directory(m_base_dir, & m_volume, m_relative_path.String(), & settings_path); + if (status != B_OK) + return status; + + status = settings_path.Append (m_settings_filename.String()); + if (status != B_OK) + return status; + + status = a_settings_file->SetTo (settings_path.Path(), a_openmode); + if (status != B_OK) + return status; + + return B_OK; +} + +status_t +ZippoSettings::ReadSettings (void) +{ + PRINT(("ZippoSettings::ReadSettings()\n")); + + status_t status = B_OK; + BFile settings_file; + + status = GetSettingsFile (& settings_file, B_READ_ONLY); + if (status != B_OK) + return status; + + status = Unflatten(& settings_file); + if (status != B_OK) + return status; + + return B_OK; +} + +status_t +ZippoSettings::WriteSettings (void) +{ + PRINT(("ZippoSettings::WriteSettings()\n")); + + status_t status = B_OK; + BFile settings_file; + + status = GetSettingsFile (& settings_file, B_WRITE_ONLY | B_ERASE_FILE); + if (status != B_OK) + return status; + + status = Flatten(& settings_file); + if (status != B_OK) + return status; + + return B_OK; +} + diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticSettings.h b/src/add-ons/tracker/zipomatic/ZipOMaticSettings.h new file mode 100644 index 0000000000..d1574bd9e6 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticSettings.h @@ -0,0 +1,36 @@ +#ifndef __ZIPPO_SETTINGS_H__ +#define __ZIPPO_SETTINGS_H__ + +#include +#include +#include + +class ZippoSettings : public BMessage +{ +public: + ZippoSettings (); + ZippoSettings (BMessage a_message); + ~ZippoSettings (); + + status_t SetTo (const char * a_settings_filename, + BVolume * a_volume = NULL, + directory_which a_base_dir = B_USER_SETTINGS_DIRECTORY, + const char * a_relative_path = NULL); + + status_t InitCheck (void); + + status_t ReadSettings (); + status_t WriteSettings (); + +private: + + status_t GetSettingsFile (BFile * a_settings_file, uint32 a_openmode); + + BVolume m_volume; + directory_which m_base_dir; + BString m_relative_path; + BString m_settings_filename; + +}; + +#endif // __ZIPPO_SETTINGS_H__ diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticView.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticView.cpp new file mode 100644 index 0000000000..188496a4b7 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticView.cpp @@ -0,0 +1,87 @@ +// license: public domain +// authors: jonas.sundstrom@kirilla.com + +#include +#include + +ZippoView::ZippoView (BRect a_rect) +: BBox (a_rect, "zipomatic_view", B_FOLLOW_ALL, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, + B_PLAIN_BORDER), + m_stop_button (NULL) +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + // "Stop" button + BRect button_rect (a_rect.right-82, a_rect.bottom-32, a_rect.right-12, a_rect.bottom-12); + m_stop_button = new BButton(button_rect,"stop_button","Stop", new BMessage(B_QUIT_REQUESTED), B_FOLLOW_RIGHT); + m_stop_button->SetEnabled(false); + AddChild(m_stop_button); + + // activity view + BRect activity_rect (a_rect.left+14, a_rect.top+15, a_rect.right-15, a_rect.top+31); + m_activity_view = new Activity (activity_rect, "activity_view", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS); + AddChild(m_activity_view); + + // text views + BRect archive_rect (a_rect.left+14, a_rect.top+30, a_rect.right-15, a_rect.top+47); + m_archive_name_view = new BStringView (archive_rect, "archive_text", " ", B_FOLLOW_LEFT_RIGHT); + AddChild (m_archive_name_view); + + BRect ouput_rect (a_rect.left+14, a_rect.top+47, a_rect.right-15, a_rect.top+66); + m_zip_output_view = new BStringView (ouput_rect, "output_text", " ", B_FOLLOW_LEFT_RIGHT); + AddChild (m_zip_output_view); + +} + +void ZippoView::Draw (BRect a_update_rect) +{ + BBox::Draw(a_update_rect); + // fBox->DrawBitmap(fIconBitmap,BPoint(178,26)); + + const rgb_color grey_accent = {128,128,128,255}; + const rgb_color darker_grey = {108,108,108,255}; + const rgb_color plain_white = {255,255,255,255}; + const rgb_color deep_black = {255,255,255,255}; + + // "preflet" bottom, right grey accent lines + + SetHighColor(grey_accent); + + StrokeLine (BPoint(Bounds().right, Bounds().top), + BPoint(Bounds().right, Bounds().bottom)); + + StrokeLine (BPoint(Bounds().left, Bounds().bottom), + BPoint(Bounds().right, Bounds().bottom)); + + // divider + SetHighColor(darker_grey); + StrokeLine (BPoint(Bounds().left+15, Bounds().top+71), + BPoint(Bounds().right-16, Bounds().top+71)); + + SetHighColor(plain_white); + StrokeLine (BPoint(Bounds().left+15, Bounds().top+72), + BPoint(Bounds().right-16, Bounds().top+72)); + + // text + SetHighColor(deep_black); + + +} + +void ZippoView::AllAttached (void) +{ + +} + +void ZippoView::FrameMoved (BPoint a_point) +{ + Invalidate(); +} + +void ZippoView::FrameResized (float a_width, float a_height) +{ + Invalidate(); +} + + diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticView.h b/src/add-ons/tracker/zipomatic/ZipOMaticView.h new file mode 100644 index 0000000000..9e26c8e8cc --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticView.h @@ -0,0 +1,31 @@ +#ifndef __ZIPPO_VIEW_H__ +#define __ZIPPO_VIEW_H__ + +#include +#include +#include + +class Activity; + +class ZippoView : public BBox +{ + public: + ZippoView (BRect frame); + + virtual void Draw (BRect frame); + virtual void AllAttached (void); + virtual void FrameMoved (BPoint a_point); + virtual void FrameResized (float a_width, float a_height); + + BButton * m_stop_button; + Activity * m_activity_view; + + BStringView * m_archive_name_view; + BStringView * m_zip_output_view; + + private: + + +}; + +#endif // __ZIPPO_VIEW_H__ diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp new file mode 100644 index 0000000000..dff3485b95 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp @@ -0,0 +1,328 @@ +// license: public domain +// authors: jonas.sundstrom@kirilla.com + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +ZippoWindow::ZippoWindow(BMessage * a_message) +: BWindow(BRect(200,200,430,310), "Zip-O-Matic", B_TITLED_WINDOW, B_NOT_V_RESIZABLE), // | B_NOT_ZOOMABLE), + m_zippo_settings (), + m_zipper_thread (NULL), + m_got_refs_at_window_startup (false), + m_zipping_was_stopped (false), + m_alert_invoker_message (new BMessage ('alrt')), + m_alert_window_invoker (new BInvoker (m_alert_invoker_message, NULL, this)) +{ + PRINT(("ZippoWindow()\n")); + +// Settings + status_t status = B_OK; + + status = m_zippo_settings.SetTo("ZipOMatic.msg"); + if (status != B_OK) + error_message("ZippoWindow() - m_zippo_settings.SetTo()", status); + + status = m_zippo_settings.InitCheck(); + if (status != B_OK) + error_message("ZippoWindow() - m_zippo_settings.InitCheck()", status); + +// Interface + zippoview = new ZippoView(Bounds()); + + AddChild (zippoview); + + SetSizeLimits(Bounds().Width(), 15000, Bounds().Height(), Bounds().Height()); + +// Settings, (on-screen location of window) + ReadSettings(); + +// Start zipper thread + if (a_message != NULL) + { + m_got_refs_at_window_startup = true; + StartZipping (a_message); + } +} + +ZippoWindow::~ZippoWindow() +{ + PRINT(("ZippoWindow::~ZippoWindow()\n")); + + //delete m_alert_invoker_message; + delete m_alert_window_invoker; + + // anything left to clean up? +} + +void +ZippoWindow::MessageReceived (BMessage * a_message) +{ + switch(a_message->what) + { + + case B_REFS_RECEIVED: + StartZipping (a_message); + break; + + case B_SIMPLE_DATA: + if (IsZipping()) + { + a_message->what = B_REFS_RECEIVED; + be_app_messenger.SendMessage(a_message); + } + else + StartZipping (a_message); + break; + + case 'exit': // thread has finished (finished, quit, killed, we don't know) + // reset window state + { + m_zipper_thread = NULL; + zippoview->m_activity_view->Stop(); + zippoview->m_archive_name_view->SetText(" "); + if (m_zipping_was_stopped) + zippoview->m_zip_output_view->SetText("Stopped"); + else + zippoview->m_zip_output_view->SetText("Archive created OK"); + + CloseWindowOrKeepOpen(); + break; + } + + case 'exrr': // thread has finished + // reset window state + + m_zipper_thread = NULL; + zippoview->m_activity_view->Stop(); + zippoview->m_archive_name_view->SetText(""); + zippoview->m_zip_output_view->SetText("Error creating archive"); + //CloseWindowOrKeepOpen(); + break; + + case 'strt': + { + BString archive_filename; + if (a_message->FindString("archive_filename", & archive_filename) == B_OK) + zippoview->m_archive_name_view->SetText(archive_filename.String()); + break; + } + + case 'outp': + { + BString zip_output; + if (a_message->FindString("zip_output", & zip_output) == B_OK) + zippoview->m_zip_output_view->SetText(zip_output.String()); + break; + } + + case 'alrt': + { + int32 which_button = -1; + if (a_message->FindInt32("which", & which_button) == B_OK) + if (which_button == 0) + StopZipping(); + else + { + if (m_zipper_thread != NULL) + m_zipper_thread->ResumeExternalZip(); + + zippoview->m_activity_view->Start(); + } + break; + } + + default: BWindow::MessageReceived(a_message); break; + } +} + +bool +ZippoWindow::QuitRequested (void) +{ + PRINT(("ZippoWindow::QuitRequested()\n")); + + if (m_zipper_thread == NULL) + { + WriteSettings(); + be_app_messenger.SendMessage(ZIPPO_WINDOW_QUIT); + return true; + } + else + { + if (m_zipper_thread != NULL) + m_zipper_thread->SuspendExternalZip(); + + zippoview->m_activity_view->Pause(); + + BAlert * quit_requester = new BAlert ("Stop or Continue", "Are you sure you want to " + "stop creating this archive?", "Stop", "Continue", + NULL, B_WIDTH_AS_USUAL, B_INFO_ALERT); + quit_requester->Go(m_alert_window_invoker); + return false; + } +} + +status_t +ZippoWindow::ReadSettings (void) +{ + status_t status = B_OK; + + status = m_zippo_settings.InitCheck(); + if (status != B_OK) + error_message("m_zippo_settings.InitCheck()", status); + + status = m_zippo_settings.ReadSettings(); + if (status != B_OK) + error_message("m_zippo_settings.ReadSettings()", status); + + BRect window_rect; + + status = m_zippo_settings.FindRect("window_rect", & window_rect); + if (status != B_OK) + { + error_message("m_settings_message->FindRect(window_rect)", status); + return status; + } + + ResizeTo (window_rect.Width(), window_rect.Height()); + MoveTo (window_rect.LeftTop()); + + return B_OK; +} + +status_t +ZippoWindow::WriteSettings (void) +{ + status_t status = B_OK; + + status = m_zippo_settings.InitCheck(); + if (status != B_OK) + error_message("m_zippo_settings.InitCheck()", status); + + status = m_zippo_settings.MakeEmpty(); + if (status != B_OK) + error_message("m_zippo_settings.MakeEmpty()", status); + + status = m_zippo_settings.AddRect("window_rect", Frame()); + if (status != B_OK) + { + error_message("m_settings_message->AddRect(window_rect)", status); + return status; + } + + status = m_zippo_settings.WriteSettings(); + if (status != B_OK) + { + error_message("m_zippo_settings.WriteSettings()", status); + return status; + } + + + return B_OK; +} + +void +ZippoWindow::StartZipping (BMessage * a_message) +{ + PRINT(("ZippoWindow::StartZipping()\n")); + + zippoview->m_stop_button->SetEnabled(true); + zippoview->m_activity_view->Start(); + + m_zipper_thread = new ZipperThread (a_message, this); + m_zipper_thread->Start(); + + m_zipping_was_stopped = false; +} + +void +ZippoWindow::StopZipping (void) +{ + PRINT(("ZippoWindow::StopZipping()\n")); + + m_zipping_was_stopped = true; + + zippoview->m_stop_button->SetEnabled(false); + + zippoview->m_activity_view->Stop(); + + m_zipper_thread->InterruptExternalZip(); + m_zipper_thread->Quit(); + + status_t status = B_OK; + m_zipper_thread->WaitForThread (& status); + m_zipper_thread = NULL; + + zippoview->m_archive_name_view->SetText(" "); + zippoview->m_zip_output_view->SetText("Stopped"); + + CloseWindowOrKeepOpen(); +} + +bool +ZippoWindow::IsZipping (void) +{ + if (m_zipper_thread == NULL) + return false; + else + return true; +} + +void +ZippoWindow::CloseWindowOrKeepOpen (void) +{ + if (m_got_refs_at_window_startup) + PostMessage(B_QUIT_REQUESTED); +} + +void +ZippoWindow::Zoom (BPoint origin, float width, float height) +{ + /* + float archive_name_view_preferred_width; + float zip_output_view_preferred_width; + float throw_away_height; + zippoview->GetPreferredSize(& archive_name_view_preferred_width, & throw_away_height); + zippoview->GetPreferredSize(& zip_output_view_preferred_width, & throw_away_height); + */ + + // BStringView::GetPreferredSize appears to be broken, + // so we have to use BView::StringWidth() instead + + if (IsZipping()) + { + float archive_name_view_preferred_width = zippoview->StringWidth(zippoview->m_archive_name_view->Text()); + float zip_output_view_preferred_width = zippoview->StringWidth(zippoview->m_zip_output_view->Text()); + + float the_wide_string; + + if (zip_output_view_preferred_width > archive_name_view_preferred_width) + the_wide_string = zip_output_view_preferred_width; + else + the_wide_string = archive_name_view_preferred_width; + + ResizeTo(the_wide_string, Bounds().Height()); + } + else + { + ResizeTo(230,110); + } +} + diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticWindow.h b/src/add-ons/tracker/zipomatic/ZipOMaticWindow.h new file mode 100644 index 0000000000..9382a817ab --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticWindow.h @@ -0,0 +1,46 @@ +#ifndef __ZIPPO_WINDOW_H__ +#define __ZIPPO_WINDOW_H__ + +#include +#include +#include +#include +#include + +#include +class ZippoView; +class ZipperThread; + +class ZippoWindow : public BWindow +{ +public: + ZippoWindow (BMessage * a_message = NULL); + ~ZippoWindow (void); + virtual void MessageReceived (BMessage * a_message); + virtual bool QuitRequested (void); + virtual void Zoom (BPoint origin, float width, float height); + + bool IsZipping (void); + +private: + + status_t ReadSettings (void); + status_t WriteSettings (void); + + void StartZipping (BMessage * a_message); + void StopZipping (void); + + void CloseWindowOrKeepOpen (void); + + ZippoView * zippoview; + ZippoSettings m_zippo_settings; + ZipperThread * m_zipper_thread; + + bool m_got_refs_at_window_startup; + bool m_zipping_was_stopped; + + BMessage * m_alert_invoker_message; + BInvoker * m_alert_window_invoker; +}; + +#endif // __ZIPPO_WINDOW_H__ diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticZipper.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticZipper.cpp new file mode 100644 index 0000000000..71224f14b0 --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticZipper.cpp @@ -0,0 +1,388 @@ +// license: public domain +// authors: jonas.sundstrom@kirilla.com +// +// exception: ZipperThread::PipeCommand() +// written by Peter Folk, published in the BeDevTalk mailinglist FAQ +// License unknown, most likely public domain + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +const char * ZipperThreadName = "ZipperThread"; + + +ZipperThread::ZipperThread (BMessage * a_refs_message, BWindow * a_window) +: GenericThread(ZipperThreadName, B_NORMAL_PRIORITY, a_refs_message), + m_window (a_window), + m_window_messenger (new BMessenger(NULL, a_window)), + m_zip_process_thread_id (-1), + m_std_in (-1), + m_std_out (-1), + m_std_err (-1), + m_zip_output (NULL), + m_zip_output_string (), + m_zip_output_buffer (new char [4096]) +{ + PRINT(("ZipperThread()\n")); + + m_thread_data_store = new BMessage (* a_refs_message); // leak? + // prevents bug with B_SIMPLE_DATA + // (drag&drop messages) +} + +ZipperThread::~ZipperThread() +{ + delete m_window_messenger; + delete [] m_zip_output_buffer; +} + +status_t +ZipperThread::ThreadStartup (void) +{ + PRINT(("ZipperThread::ThreadStartup()\n")); + + // init + status_t status = B_OK; + entry_ref ref; + entry_ref last_ref; + bool same_folder = true; + + BString zip_archive_filename = "Archive.zip"; + + // do all refs have the same parent dir? + type_code ref_type = B_REF_TYPE; + int32 ref_count = 0; + + status = m_thread_data_store->GetInfo("refs", & ref_type, & ref_count); + if (status != B_OK) + return status; + + for (int index = 0; index < ref_count ; index++) + { + m_thread_data_store->FindRef("refs", index, & ref); + + if (index > 0) + { + BEntry entry (& ref); + if (entry.IsSymLink()) + { + entry.SetTo(& ref, true); + entry_ref target; + entry.GetRef(& target); + if (last_ref.directory != target.directory) + { + same_folder = false; + break; + } + } + else + if (last_ref.directory != ref.directory) + { + same_folder = false; + break; + } + } + last_ref = ref; + } + + // change active dir + if (same_folder) + { + BEntry entry (& last_ref); + BPath path; + entry.GetParent(& entry); + entry.GetPath(& path); + chdir(path.Path()); + } + else + { + BPath path; + if (find_directory(B_DESKTOP_DIRECTORY, & path) == B_OK) + chdir (path.Path()); + } + + // archive filename + if (ref_count == 1) + { + zip_archive_filename = last_ref.name; + zip_archive_filename += ".zip"; + } + + int32 argc = ref_count + 3; + const char ** argv = new const char * [argc + 1]; + + argv[0] = strdup("/bin/zip"); + argv[1] = strdup("-ry"); + argv[2] = strdup(zip_archive_filename.String()); + + + // files to zip + for (int ref_index = 0; ref_index < ref_count ; ref_index++) + { + m_thread_data_store->FindRef("refs", ref_index, & ref); + + if (same_folder) + { + argv[3 + ref_index] = strdup(ref.name); // just the file name + } + else + { + BPath path (& ref); + BString file = path.Path(); + argv[3 + ref_index] = strdup(path.Path()); // full path + } + } + + argv[argc] = NULL; + + m_zip_process_thread_id = PipeCommand (argc, argv, m_std_in, m_std_out, m_std_err); + + delete [] argv; + + if (m_zip_process_thread_id < 0) + return (m_zip_process_thread_id); + + resume_thread (m_zip_process_thread_id); + + m_zip_output = fdopen (m_std_out, "r"); + + zip_archive_filename.Prepend("Creating archive: "); + + SendMessageToWindow ('strt', "archive_filename", zip_archive_filename.String()); + SendMessageToWindow ('outp', "zip_output", "Preparing to archive"); + + PRINT(("\n")); + + return B_OK; +} + +status_t +ZipperThread::ExecuteUnit (void) +{ + //PRINT(("ZipperThread::ExecuteUnit()\n")); + + // read output from /bin/zip + // send it to window + + char * output_string; + output_string = fgets(m_zip_output_buffer , 4096-1, m_zip_output); + + if (output_string == NULL) + { + return EOF; + } + else + { + char * new_line_ptr = strrchr(output_string, '\n'); + if (new_line_ptr != NULL) + *new_line_ptr = '\0'; + + if (! strncmp(" a", m_zip_output_buffer, 3)) + { + m_zip_output_buffer[2] = 'A'; + SendMessageToWindow ('outp', "zip_output", output_string + 2); + } + else if (! strncmp("up", m_zip_output_buffer, 2)) + { + m_zip_output_buffer[0] = 'U'; + SendMessageToWindow ('outp', "zip_output", output_string); + } + else + { + SendMessageToWindow ('outp', "zip_output", output_string); + } + } + + return B_OK; +} + +status_t +ZipperThread::ThreadShutdown (void) +{ + PRINT(("ZipperThread::ThreadShutdown()\n")); + + close(m_std_in); + close(m_std_out); + close(m_std_err); + + return B_OK; +} + +void +ZipperThread::ThreadStartupFailed (status_t a_status) +{ + error_message("ZipperThread::ThreadStartupFailed() \n", a_status); + + Quit(); +} + +void +ZipperThread::ExecuteUnitFailed (status_t a_status) +{ + error_message("ZipperThread::ExecuteUnitFailed() \n", a_status); + + + if (a_status == EOF) + { + // thread has finished, been quit or killed, we don't know + SendMessageToWindow ('exit'); + } + else + { + // explicit error - communicate error to Window + SendMessageToWindow ('exrr'); + } + + Quit(); +} + +void +ZipperThread::ThreadShutdownFailed (status_t a_status) +{ + error_message("ZipperThread::ThreadShutdownFailed() \n", a_status); +} + + +void +ZipperThread::MakeShellSafe (BString * a_string) +{ + a_string->CharacterEscape("\"$`", '\\'); + a_string->Prepend("\""); + a_string->Append("\""); +} + +status_t +ZipperThread::ProcessRefs (BMessage * msg) +{ + + return B_OK; +} + +thread_id +ZipperThread::PipeCommand (int argc, const char **argv, int & in, int & out, int & err, const char **envp) +{ + // This function written by Peter Folk + // and published in the BeDevTalk FAQ + // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209 + + // Save current FDs + int old_in = dup(0); + int old_out = dup(1); + int old_err = dup(2); + + int filedes[2]; + + /* Create new pipe FDs as stdin, stdout, stderr */ + pipe(filedes); dup2(filedes[0],0); close(filedes[0]); + in=filedes[1]; // Write to in, appears on cmd's stdin + pipe(filedes); dup2(filedes[1],1); close(filedes[1]); + out=filedes[0]; // Read from out, taken from cmd's stdout + pipe(filedes); dup2(filedes[1],2); close(filedes[1]); + err=filedes[0]; // Read from err, taken from cmd's stderr + + // "load" command. + thread_id ret = load_image(argc, argv, envp); + // thread ret is now suspended. + + PRINT(("load_image() thread_id: %ld\n", ret)); + + // Restore old FDs + close(0); dup(old_in); close(old_in); + close(1); dup(old_out); close(old_out); + close(2); dup(old_err); close(old_err); + + /* Theoretically I should do loads of error checking, but + the calls aren't very likely to fail, and that would + muddy up the example quite a bit. YMMV. */ + + return ret; +} + +void +ZipperThread::SendMessageToWindow (uint32 a_msg_what, const char * a_string_name, const char * a_string_value) +{ + BMessage msg (a_msg_what); + + if (! (a_string_name == NULL || a_string_value == NULL)) + msg.AddString(a_string_name, a_string_value); + + m_window_messenger->SendMessage(& msg); +} + +status_t +ZipperThread::SuspendExternalZip (void) +{ + PRINT(("ZipperThread::SuspendExternalZip()\n")); + + status_t status = B_OK; + thread_info zip_thread_info; + status = get_thread_info (m_zip_process_thread_id, & zip_thread_info); + BString thread_name = zip_thread_info.name; + + if (status == B_OK && thread_name == "zip") + return suspend_thread (m_zip_process_thread_id); + else + return status; +} + +status_t +ZipperThread::ResumeExternalZip (void) +{ + PRINT(("ZipperThread::ResumeExternalZip()\n")); + + status_t status = B_OK; + thread_info zip_thread_info; + status = get_thread_info (m_zip_process_thread_id, & zip_thread_info); + BString thread_name = zip_thread_info.name; + + if (status == B_OK && thread_name == "zip") + return resume_thread (m_zip_process_thread_id); + else + return status; +} + +status_t +ZipperThread::InterruptExternalZip (void) +{ + PRINT(("ZipperThread::InterruptExternalZip()\n")); + + status_t status = B_OK; + thread_info zip_thread_info; + status = get_thread_info (m_zip_process_thread_id, & zip_thread_info); + BString thread_name = zip_thread_info.name; + + if (status == B_OK && thread_name == "zip") + { + status = B_OK; + status = send_signal (m_zip_process_thread_id, SIGINT); + WaitOnExternalZip(); + return status; + } + else + return status; +} + +status_t +ZipperThread::WaitOnExternalZip (void) +{ + PRINT(("ZipperThread::WaitOnExternalZip()\n")); + + status_t status = B_OK; + thread_info zip_thread_info; + status = get_thread_info (m_zip_process_thread_id, & zip_thread_info); + BString thread_name = zip_thread_info.name; + + if (status == B_OK && thread_name == "zip") + return wait_for_thread (m_zip_process_thread_id, & status); + else + return status; +} diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticZipper.h b/src/add-ons/tracker/zipomatic/ZipOMaticZipper.h new file mode 100644 index 0000000000..3560ac9c0c --- /dev/null +++ b/src/add-ons/tracker/zipomatic/ZipOMaticZipper.h @@ -0,0 +1,61 @@ +#ifndef __ZIPOMATIC_ZIPPER_H__ +#define __ZIPOMATIC_ZIPPER_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include + +extern const char * ZipperThreadName; + +class ZipperThread : public GenericThread +{ +public: + ZipperThread (BMessage * a_refs_message, BWindow * a_window); + ~ZipperThread (); + + status_t SuspendExternalZip (void); + status_t ResumeExternalZip (void); + status_t InterruptExternalZip (void); + status_t WaitOnExternalZip (void); + +private: + + virtual status_t ThreadStartup (void); + virtual status_t ExecuteUnit (void); + virtual status_t ThreadShutdown (void); + + virtual void ThreadStartupFailed (status_t a_status); + virtual void ExecuteUnitFailed (status_t a_status); + virtual void ThreadShutdownFailed (status_t a_status); + + status_t ProcessRefs (BMessage * msg); + void MakeShellSafe (BString * a_string); + + thread_id PipeCommand (int argc, const char **argv, + int & in, int & out, int & err, + const char **envp = (const char **) environ); + + void SendMessageToWindow (uint32 a_msg_what, + const char * a_string_name = NULL, + const char * a_string_value = NULL); + + BWindow * m_window; + BMessenger * m_window_messenger; + + int32 m_zip_process_thread_id; + int m_std_in; + int m_std_out; + int m_std_err; + FILE * m_zip_output; + BString m_zip_output_string; + char * m_zip_output_buffer; +}; + +#endif // __ZIPOMATIC_ZIPPER_H__ +