diff --git a/src/add-ons/tracker/zipomatic/Jamfile b/src/add-ons/tracker/zipomatic/Jamfile index 14e9457b0e..c30c169fe8 100644 --- a/src/add-ons/tracker/zipomatic/Jamfile +++ b/src/add-ons/tracker/zipomatic/Jamfile @@ -6,8 +6,6 @@ Application ZipOMatic-Z : GenericThread.cpp ZipOMatic.cpp ZipOMaticActivity.cpp - ZipOMaticMisc.cpp - ZipOMaticSettings.cpp ZipOMaticWindow.cpp ZipperThread.cpp diff --git a/src/add-ons/tracker/zipomatic/ZipOMatic.cpp b/src/add-ons/tracker/zipomatic/ZipOMatic.cpp index 16112d40b4..117537bde9 100644 --- a/src/add-ons/tracker/zipomatic/ZipOMatic.cpp +++ b/src/add-ons/tracker/zipomatic/ZipOMatic.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include "ZipOMaticMisc.h" @@ -31,45 +30,27 @@ main() ZipOMatic::ZipOMatic() : BApplication(ZIPOMATIC_APP_SIG), - fSettings(), fGotRefs(false), - fInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, this)), - fWindowFrame(200, 200, 430, 310) + fInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, this)) { - status_t status = _ReadSettings(); - - if (status != B_OK) - ErrorMessage("_ReadSettings()", status); } ZipOMatic::~ZipOMatic() { - status_t status = _WriteSettings(); - - if (status != B_OK) - ErrorMessage("_WriteSettings()", status); } void ZipOMatic::RefsReceived(BMessage* message) { - message->RemoveName("dir_ref"); - entry_ref ref; - if (message->FindRef("refs", &ref) != B_OK) { - if (!IsLaunching()) - PostMessage(B_SILENT_RELAUNCH); - return; - } - - if (IsLaunching()) + if (message->FindRef("refs", &ref) == B_OK) { + _UseExistingOrCreateNewWindow(message); fGotRefs = true; - - BMessage* msg = new BMessage(*message); - - _UseExistingOrCreateNewWindow(msg); + } else if (!IsLaunching()) { + PostMessage(B_SILENT_RELAUNCH); + } } @@ -87,9 +68,6 @@ ZipOMatic::MessageReceived(BMessage* message) switch (message->what) { case ZIPPO_WINDOW_QUIT: { - BRect frame; - if (message->FindRect("frame", &frame) == B_OK) - fWindowFrame = frame; snooze(200000); if (CountWindows() == 0) Quit(); @@ -105,7 +83,7 @@ ZipOMatic::MessageReceived(BMessage* message) if (message->FindInt32("which", &button) == B_OK) if (button == 0) { _StopZipping(); - } else { + } else { if (CountWindows() == 0) Quit(); } @@ -120,7 +98,7 @@ ZipOMatic::MessageReceived(BMessage* message) bool -ZipOMatic::QuitRequested (void) +ZipOMatic::QuitRequested(void) { if (CountWindows() <= 0) return true; @@ -208,43 +186,42 @@ void ZipOMatic::_UseExistingOrCreateNewWindow(BMessage* message) { int32 windowCount = 0; - ZippoWindow* window; - bool foundNonBusyWindow = false; + BWindow* bWindow; + ZippoWindow* zWindow; + BList list; while (1) { - window = dynamic_cast(WindowAt(windowCount++)); - if (window == NULL) + bWindow = WindowAt(windowCount++); + if (bWindow == NULL) break; + + zWindow = dynamic_cast(bWindow); + if (zWindow == NULL) + continue; + + list.AddItem(zWindow); - if (window->Lock()) { - if (!window->IsZipping()) { - foundNonBusyWindow = true; + if (zWindow->Lock()) { + if (!zWindow->IsZipping()) { if (message != NULL) - window->PostMessage(message); - window->SetWorkspaces(B_CURRENT_WORKSPACE); - window->Activate(); - window->Unlock(); - break; + zWindow->PostMessage(message); + zWindow->SetWorkspaces(B_CURRENT_WORKSPACE); + zWindow->Activate(); + zWindow->Unlock(); + return; } - window->Unlock(); + zWindow->Unlock(); } } - - if (!foundNonBusyWindow) - { - BScreen screen; - fWindowFrame.OffsetBy(screen.Frame().LeftTop()); - - _CascadeOnFrameCollision(&fWindowFrame); - if(!screen.Frame().Contains(fWindowFrame)) { - fWindowFrame.OffsetTo(screen.Frame().LeftTop()); - fWindowFrame.OffsetBy(20,45); - // TODO: replace with CenterOnScreen() - } - - ZippoWindow * window = new ZippoWindow(fWindowFrame, message); - window->Show(); + + if (message) { + zWindow = new ZippoWindow(list); + zWindow->PostMessage(message); + } else { + zWindow = new ZippoWindow(list, true); } + + zWindow->Show(); } @@ -282,93 +259,3 @@ ZipOMatic::_StopZipping() } } - -status_t -ZipOMatic::_ReadSettings() -{ - status_t status = B_OK; - - status = fSettings.SetTo("zipomatic.msg"); - if (status != B_OK) - return status; - - status = fSettings.InitCheck(); - if (status != B_OK) - return status; - - status = fSettings.InitCheck(); - if (status != B_OK) - return status; - - status = fSettings.ReadSettings(); - if (status != B_OK) - return status; - - BRect frame; - status = fSettings.FindRect("frame", &frame); - if (status != B_OK) - return status; - - fWindowFrame = frame; - - return B_OK; -} - - -status_t -ZipOMatic::_WriteSettings() -{ - status_t status = B_OK; - - status = fSettings.InitCheck(); - if (status != B_OK) - return status; - - status = fSettings.MakeEmpty(); - if (status != B_OK) - return status; - - status = fSettings.AddRect("frame", fWindowFrame); - if (status != B_OK) - return status; - - status = fSettings.WriteSettings(); - if (status != B_OK) - return status; - - return B_OK; -} - - -void -ZipOMatic::_CascadeOnFrameCollision(BRect* frame) -{ - BWindow* window; - ZippoWindow* zippo; - BList list; - - for (int32 i = 0;; i++) { - window = WindowAt(i); - if (window == NULL) - break; - - zippo = dynamic_cast(window); - if (zippo == NULL) - continue; - - list.AddItem(zippo); - } - - for (int32 i = 0;; i++) { - zippo = static_cast(list.ItemAt(i)); - if (zippo == NULL) - break; - - if (zippo->Lock()) { - if (frame->LeftTop() == zippo->Frame().LeftTop()) - frame->OffsetBy(20, 20); - zippo->Unlock(); - } - } -} - diff --git a/src/add-ons/tracker/zipomatic/ZipOMatic.h b/src/add-ons/tracker/zipomatic/ZipOMatic.h index 70a36b8563..de201fd7f4 100644 --- a/src/add-ons/tracker/zipomatic/ZipOMatic.h +++ b/src/add-ons/tracker/zipomatic/ZipOMatic.h @@ -5,9 +5,6 @@ #include #include #include -#include - -#include "ZipOMaticSettings.h" class ZipOMatic : public BApplication @@ -22,18 +19,13 @@ public: virtual bool QuitRequested(); private: - status_t _ReadSettings(); - status_t _WriteSettings(); - void _CascadeOnFrameCollision(BRect* frame); void _SilentRelaunch(); void _UseExistingOrCreateNewWindow(BMessage* message = NULL); void _StopZipping(); - ZippoSettings fSettings; bool fGotRefs; BInvoker* fInvoker; - BRect fWindowFrame; }; #endif // _ZIPOMATIC_H_ diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp index c3af8040e7..e087c8e350 100644 --- a/src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp +++ b/src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp @@ -88,7 +88,7 @@ Activity::Pulse() uchar tmp = fPattern.data[7]; for (int j = 7; j > 0; --j) - fPattern.data[j] = fPattern.data[j-1]; + fPattern.data[j] = fPattern.data[j - 1]; fPattern.data[0] = tmp; @@ -103,10 +103,6 @@ Activity::Draw(BRect rect) BRect bitmapRect = fBitmap->Bounds(); if (bitmapRect != viewRect) { - printf("Activity::Draw(): bitmapRect != viewRect\n"); - bitmapRect.PrintToStream(); - viewRect.PrintToStream(); - delete fBitmap; _CreateBitmap(); } @@ -138,7 +134,7 @@ Activity::_DrawOnBitmap(bool running) fBitmapView->SetHighColor(color); // draw the pole - rect.InsetBy(2,2); + rect.InsetBy(2, 2); fBitmapView->FillRect(rect, fPattern); // draw frame @@ -198,19 +194,19 @@ Activity::_DrawOnBitmap(bool running) fBitmapView->SetDrawingMode(B_OP_SUBTRACT); fBitmapView->StrokeRect(rect); - rect.InsetBy(1,1); + rect.InsetBy(1, 1); _LightenBitmapHighColor(& color); fBitmapView->StrokeRect(rect); - rect.InsetBy(1,1); + rect.InsetBy(1, 1); _LightenBitmapHighColor(& color); fBitmapView->StrokeRect(rect); - rect.InsetBy(1,1); + rect.InsetBy(1, 1); _LightenBitmapHighColor(& color); fBitmapView->StrokeRect(rect); - rect.InsetBy(1,1); + rect.InsetBy(1, 1); _LightenBitmapHighColor(& color); fBitmapView->StrokeRect(rect); diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticMisc.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticMisc.cpp deleted file mode 100644 index 197fa14af3..0000000000 --- a/src/add-ons/tracker/zipomatic/ZipOMaticMisc.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2003-2009, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Jonas Sundström, jonas@kirilla.com - */ - - -#include "ZipOMaticMisc.h" - -#include - -#include - - -status_t -FindAndCreateDirectory(directory_which which, BVolume* volume, - const char* relativePath, BPath* fullPath) -{ - BPath path; - status_t status = find_directory(which, &path, true, volume); - if (status != B_OK) - return status; - - if (relativePath != NULL) { - path.Append(relativePath); - - mode_t mask = umask(0); - umask(mask); - - status = create_directory(path.Path(), mask); - if (status != B_OK) - return status; - } - - if (fullPath != NULL) { - status = fullPath->SetTo(path.Path()); - if (status != B_OK) - return status; - } - - return B_OK; -} - - -void -ErrorMessage(const char* text, int32 status) -{ - PRINT(("%s: %s\n", text, strerror(status))); -} - diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticMisc.h b/src/add-ons/tracker/zipomatic/ZipOMaticMisc.h index 4f08c3e49f..b8249ccdf7 100644 --- a/src/add-ons/tracker/zipomatic/ZipOMaticMisc.h +++ b/src/add-ons/tracker/zipomatic/ZipOMaticMisc.h @@ -9,12 +9,6 @@ #define ZIPOMATIC_MISC_H -#include -#include -#include -#include - - #define ZIPOMATIC_APP_SIG "application/x-vnd.haiku.zip-o-matic" #define ZIPPO_WINDOW_QUIT 'winq' @@ -24,11 +18,6 @@ #define ZIPPO_TASK_DESCRIPTION 'strt' #define ZIPPO_LINE_OF_STDOUT 'outp' -status_t FindAndCreateDirectory(directory_which which, - BVolume* volume = NULL, const char* relativePath = NULL, - BPath* fullPath = NULL); - -void ErrorMessage(const char* text, int32 status); #endif // ZIPOMATIC_MISC_H diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticSettings.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticSettings.cpp deleted file mode 100644 index 37b1ef56ce..0000000000 --- a/src/add-ons/tracker/zipomatic/ZipOMaticSettings.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2003-2009, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Jonas Sundström, jonas@kirilla.com - */ - -// TODO: proper locking <<--------- - - -#include "ZipOMaticSettings.h" - -#include -#include -#include -#include -#include - -#include "ZipOMaticMisc.h" - - -ZippoSettings::ZippoSettings() - : - fBaseDir(B_USER_SETTINGS_DIRECTORY) -{ - -} - - -ZippoSettings::ZippoSettings(BMessage& message) - : - BMessage(message), - fBaseDir(B_USER_SETTINGS_DIRECTORY) -{ - -} - - -ZippoSettings::~ZippoSettings() -{ - -} - - -status_t -ZippoSettings::SetTo(const char* filename, BVolume* volume, - directory_which baseDir, const char* relativePath) -{ - status_t status = B_OK; - - fBaseDir = baseDir; - fRelativePath = relativePath; - fFilename = filename; - - if (volume == NULL) { - BVolumeRoster volumeRoster; - volumeRoster.GetBootVolume(&fVolume); - } else { - fVolume = *volume; - } - - status = fVolume.InitCheck(); - if (status != B_OK) - return status; - - return InitCheck(); -} - - -status_t -ZippoSettings::InitCheck() -{ - BFile file; - return _GetSettingsFile(&file, B_READ_ONLY | B_CREATE_FILE); -} - - -status_t -ZippoSettings::ReadSettings() -{ - BFile file; - status_t status = _GetSettingsFile(&file, B_READ_ONLY); - if (status != B_OK) - return status; - - return Unflatten(&file); -} - - -status_t -ZippoSettings::WriteSettings() -{ - BFile file; - status_t status = _GetSettingsFile(&file, B_WRITE_ONLY | B_ERASE_FILE); - if (status != B_OK) - return status; - - return Flatten(&file); -} - - -status_t -ZippoSettings::_GetSettingsFile(BFile* file, uint32 openMode) -{ - BPath path; - status_t status = FindAndCreateDirectory(fBaseDir, &fVolume, - fRelativePath.String(), &path); - if (status != B_OK) - return status; - - status = path.Append(fFilename.String()); - if (status != B_OK) - return status; - - return file->SetTo(path.Path(), openMode); -} - diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticSettings.h b/src/add-ons/tracker/zipomatic/ZipOMaticSettings.h deleted file mode 100644 index c3825dcaa7..0000000000 --- a/src/add-ons/tracker/zipomatic/ZipOMaticSettings.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2003-2009, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Jonas Sundström, jonas@kirilla.com - */ -#ifndef _ZIPOMATIC_SETTINGS_H -#define _ZIPOMATIC_SETTINGS_H - - -#include -#include -#include -#include - - -class ZippoSettings : public BMessage { -public: - ZippoSettings(); - ZippoSettings(BMessage& message); - ~ZippoSettings(); - - status_t SetTo(const char* filename, BVolume* volume = NULL, - directory_which baseDir = - B_USER_SETTINGS_DIRECTORY, - const char* relativePath = NULL); - status_t InitCheck(); - - status_t ReadSettings(); - status_t WriteSettings(); - -private: - status_t _GetSettingsFile(BFile* file, uint32 openMode); - - BVolume fVolume; - directory_which fBaseDir; - BString fRelativePath; - BString fFilename; -}; - -#endif // _ZIPOMATIC_SETTINGS_H - diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp b/src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp index 407d2ec338..f78cba9e8f 100644 --- a/src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp +++ b/src/add-ons/tracker/zipomatic/ZipOMaticWindow.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -30,12 +31,13 @@ #include "ZipperThread.h" -ZippoWindow::ZippoWindow(BRect frame, BMessage* refs) +ZippoWindow::ZippoWindow(BList windowList, bool keepOpen) : - BWindow(frame, "Zip-O-Matic", B_TITLED_WINDOW, + BWindow(BRect(0, 0, 0, 0), "Zip-O-Matic", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE), + fWindowList(windowList), fThread(NULL), - fWindowGotRefs(false), + fKeepOpen(keepOpen), fZippingWasStopped(false), fFileCount(0), fWindowInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, @@ -70,10 +72,7 @@ ZippoWindow::ZippoWindow(BRect frame, BMessage* refs) .End() .End(); - if (refs != NULL) { - fWindowGotRefs = true; - _StartZipping(refs); - } + _FindBestPlacement(); } @@ -88,9 +87,6 @@ ZippoWindow::MessageReceived(BMessage* message) { switch (message->what) { case B_REFS_RECEIVED: - _StartZipping(message); - break; - case B_SIMPLE_DATA: if (IsZipping()) { message->what = B_REFS_RECEIVED; @@ -125,8 +121,11 @@ ZippoWindow::MessageReceived(BMessage* message) case ZIPPO_TASK_DESCRIPTION: { BString string; - if (message->FindString("archive_filename", &string) == B_OK) + if (message->FindString("archive_filename", &string) == B_OK) { + fArchiveName = string; + string.Prepend("Creating archive: "); fArchiveNameView->SetText(string.String()); + } break; } @@ -202,11 +201,14 @@ ZippoWindow::QuitRequested() fThread->SuspendExternalZip(); fActivityView->Pause(); - BAlert* alert = new BAlert("Stop or Continue", - "Are you sure you want to stop creating this archive?", "Stop", + BString message; + message << "Are you sure you want to stop creating this archive?\n\n"; + message << "Filename: " << fArchiveName.String() << "\n"; + + BAlert* alert = new BAlert(NULL, message.String(), "Stop", "Continue", NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); alert->Go(fWindowInvoker); - + return false; } } @@ -261,7 +263,155 @@ ZippoWindow::IsZipping() void ZippoWindow::_CloseWindowOrKeepOpen() { - if (fWindowGotRefs) + if (!fKeepOpen) PostMessage(B_QUIT_REQUESTED); } + +void +ZippoWindow::_FindBestPlacement() +{ + CenterOnScreen(); + + BScreen screen; + BRect centeredRect = Frame(); + BRect tryRect = centeredRect; + BList tryRectList; + + if (!screen.Frame().Contains(centeredRect)) + return; + + // build a list of possible locations + tryRectList.AddItem(new BRect(centeredRect)); + + // up and left + direction primaryDirection = up; + while (true) { + _OffsetRect(&tryRect, primaryDirection); + + if (!screen.Frame().Contains(tryRect)) + _OffscreenBounceBack(&tryRect, &primaryDirection, left); + + if (!screen.Frame().Contains(tryRect)) + break; + + tryRectList.AddItem(new BRect(tryRect)); + } + + // down and right + primaryDirection = down; + tryRect = centeredRect; + while (true) { + _OffsetRect(&tryRect, primaryDirection); + + if (!screen.Frame().Contains(tryRect)) + _OffscreenBounceBack(&tryRect, &primaryDirection, right); + + if (!screen.Frame().Contains(tryRect)) + break; + + tryRectList.AddItem(new BRect(tryRect)); + } + + // remove rects that overlap an existing window + for (int32 i = 0;; i++) { + BWindow* win = static_cast(fWindowList.ItemAt(i)); + if (win == NULL) + break; + + ZippoWindow* window = dynamic_cast(win); + if (window == NULL) + continue; + + if (window == this) + continue; + + if (window->Lock()) { + BRect frame = window->Frame(); + for (int32 m = 0;; m++) { + BRect* rect = static_cast(tryRectList.ItemAt(m)); + if (rect == NULL) + break; + + if (frame.Intersects(*rect)) { + tryRectList.RemoveItem(m); + delete rect; + m--; + } + } + window->Unlock(); + } + } + + // find nearest rect + bool gotRect = false; + BRect nearestRect(0, 0, 0, 0); + + while (true) { + BRect* rect = static_cast(tryRectList.RemoveItem((int32)0)); + if (rect == NULL) + break; + + nearestRect = _NearestRect(centeredRect, nearestRect, *rect); + gotRect = true; + delete rect; + } + + if (gotRect) + MoveTo(nearestRect.LeftTop()); +} + + +void +ZippoWindow::_OffsetRect(BRect* rect, direction whereTo) +{ + float width = rect->Width(); + float height = rect->Height(); + + switch (whereTo) { + case up: + rect->OffsetBy(0, -(height * 1.5)); + break; + + case down: + rect->OffsetBy(0, height * 1.5); + break; + + case left: + rect->OffsetBy(-(width * 1.5), 0); + break; + + case right: + rect->OffsetBy(width * 1.5, 0); + break; + } +} + + +void +ZippoWindow::_OffscreenBounceBack(BRect* rect, direction* primaryDirection, + direction secondaryDirection) +{ + if (*primaryDirection == up) { + *primaryDirection = down; + } else { + *primaryDirection = up; + } + + _OffsetRect(rect, *primaryDirection); + _OffsetRect(rect, secondaryDirection); +} + + +BRect +ZippoWindow::_NearestRect(BRect goalRect, BRect a, BRect b) +{ + double aSum = fabs(goalRect.left - a.left) + fabs(goalRect.top - a.top); + double bSum = fabs(goalRect.left - b.left) + fabs(goalRect.top - b.top); + + if (aSum < bSum) + return a; + else + return b; +} + diff --git a/src/add-ons/tracker/zipomatic/ZipOMaticWindow.h b/src/add-ons/tracker/zipomatic/ZipOMaticWindow.h index 0917e731e3..785f434122 100644 --- a/src/add-ons/tracker/zipomatic/ZipOMaticWindow.h +++ b/src/add-ons/tracker/zipomatic/ZipOMaticWindow.h @@ -3,6 +3,8 @@ #include +#include +#include #include #include @@ -10,10 +12,19 @@ #include "ZipperThread.h" +enum direction { + up, + down, + left, + right +}; + + class ZippoWindow : public BWindow { public: - ZippoWindow(BRect frame, BMessage* refs = NULL); + ZippoWindow(BList windowList, + bool keepOpen = false); ~ZippoWindow(); virtual void MessageReceived(BMessage* message); @@ -27,14 +38,24 @@ private: void _StartZipping(BMessage* message); void _CloseWindowOrKeepOpen(); + void _FindBestPlacement(); + void _OffsetRect(BRect* rect, direction whereTo); + void _OffscreenBounceBack(BRect* rect, + direction* primaryDirection, + direction secondaryDirection); + BRect _NearestRect(BRect goalRect, BRect a, BRect b); + + BList fWindowList; + Activity* fActivityView; BStringView* fArchiveNameView; BStringView* fZipOutputView; BButton* fStopButton; ZipperThread* fThread; + BString fArchiveName; - bool fWindowGotRefs; + bool fKeepOpen; bool fZippingWasStopped; int32 fFileCount; diff --git a/src/add-ons/tracker/zipomatic/ZipperThread.cpp b/src/add-ons/tracker/zipomatic/ZipperThread.cpp index a9e50a0901..5468174725 100644 --- a/src/add-ons/tracker/zipomatic/ZipperThread.cpp +++ b/src/add-ons/tracker/zipomatic/ZipperThread.cpp @@ -12,9 +12,11 @@ #include #include +#include #include #include +#include #include #include #include @@ -34,9 +36,6 @@ ZipperThread::ZipperThread(BMessage* refsMessage, BWindow* window) fOutputFile(NULL) { fThreadDataStore = new BMessage(*refsMessage); - // leak? - // prevents bug with B_SIMPLE_DATA - // (drag&drop messages) } @@ -48,9 +47,6 @@ ZipperThread::~ZipperThread() status_t ZipperThread::ThreadStartup() { - BString archiveName = "Archive.zip"; - - // do all refs have the same parent dir? type_code type = B_REF_TYPE; int32 refCount = 0; entry_ref ref; @@ -58,23 +54,17 @@ ZipperThread::ThreadStartup() bool sameFolder = true; status_t status = fThreadDataStore->GetInfo("refs", &type, &refCount); - if (status != B_OK) - return status; + if (status != B_OK || refCount < 1) { + _SendMessageToWindow(ZIPPO_THREAD_EXIT_ERROR); + Quit(); + return B_ERROR; + } for (int index = 0; index < refCount; index++) { fThreadDataStore->FindRef("refs", index, &ref); if (index > 0) { - BEntry entry(&ref); - if (entry.IsSymLink()) { - entry.SetTo(&ref, true); - entry_ref target; - entry.GetRef(&target); - if (lastRef.directory != target.directory) { - sameFolder = false; - break; - } - } else if (lastRef.directory != ref.directory) { + if (lastRef.directory != ref.directory) { sameFolder = false; break; } @@ -82,8 +72,27 @@ ZipperThread::ThreadStartup() lastRef = ref; } - // change active dir - if (sameFolder) { + entry_ref dirRef; + bool gotDirRef = false; + + status = fThreadDataStore->FindRef("dir_ref", 0, &dirRef); + if (status == B_OK) { + BEntry dirEntry(&dirRef); + BNode dirNode(&dirRef); + + if (dirEntry.InitCheck() == B_OK + && dirEntry.Exists() + && dirNode.InitCheck() == B_OK + && dirNode.IsDirectory()) + gotDirRef = true; + } + + if (gotDirRef) { + BEntry entry(&dirRef); + BPath path; + entry.GetPath(&path); + chdir(path.Path()); + } else if (sameFolder) { BEntry entry(&lastRef); BPath path; entry.GetParent(&entry); @@ -95,10 +104,28 @@ ZipperThread::ThreadStartup() chdir(path.Path()); } - // archive filename - if (refCount == 1) { + BString archiveName; + + if (refCount > 1) + archiveName = "Archive"; + else archiveName = lastRef.name; - archiveName += ".zip"; + + int index = 1; + for (;; index++) { + BString tryName = archiveName; + + if (index != 1) + tryName << " " << index; + + tryName << ".zip"; + + BEntry entry(tryName.String()); + if (!entry.Exists()) { + archiveName = tryName; + entry.GetRef(&fOutputEntryRef); + break; + } } int32 argc = refCount + 3; @@ -108,15 +135,12 @@ ZipperThread::ThreadStartup() argv[1] = strdup("-ry"); argv[2] = strdup(archiveName.String()); - // files to zip for (int index = 0; index < refCount; index++) { fThreadDataStore->FindRef("refs", index, &ref); - if (sameFolder) { - // just the file name + if (gotDirRef || sameFolder) { argv[3 + index] = strdup(ref.name); } else { - // full path BPath path(&ref); BString file = path.Path(); argv[3 + index] = strdup(path.Path()); @@ -138,8 +162,6 @@ ZipperThread::ThreadStartup() if (fOutputFile == NULL) return errno; - archiveName.Prepend("Creating archive: "); - _SendMessageToWindow(ZIPPO_TASK_DESCRIPTION, "archive_filename", archiveName.String()); _SendMessageToWindow(ZIPPO_LINE_OF_STDOUT, "zip_output", @@ -152,8 +174,6 @@ ZipperThread::ThreadStartup() status_t ZipperThread::ExecuteUnit() { - // read output from /bin/zip - // send it to window char buffer[4096]; char* output = fgets(buffer, sizeof(buffer) - 1, fOutputFile); @@ -185,6 +205,8 @@ ZipperThread::ThreadShutdown() close(fStdOut); close(fStdErr); + // _SelectInTracker(); + return B_OK; } @@ -192,7 +214,6 @@ ZipperThread::ThreadShutdown() void ZipperThread::ThreadStartupFailed(status_t status) { - ErrorMessage("ZipperThread::ThreadStartupFailed() \n", status); Quit(); } @@ -200,8 +221,6 @@ ZipperThread::ThreadStartupFailed(status_t status) void ZipperThread::ExecuteUnitFailed(status_t status) { - ErrorMessage("ZipperThread::ExecuteUnitFailed() \n", status); - if (status == EOF) { // thread has finished, been quit or killed, we don't know _SendMessageToWindow(ZIPPO_THREAD_EXIT); @@ -217,7 +236,8 @@ ZipperThread::ExecuteUnitFailed(status_t status) void ZipperThread::ThreadShutdownFailed(status_t status) { - ErrorMessage("ZipperThread::ThreadShutdownFailed() \n", status); + fprintf(stderr, "ZipperThread::ThreadShutdownFailed(): %s\n", + strerror(status)); } @@ -234,68 +254,78 @@ thread_id ZipperThread::_PipeCommand(int argc, const char** argv, int& in, int& out, int& err, const char** envp) { - // This function was originally written by Peter Folk - // and published in the BeDevTalk FAQ - // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209 + static BLocker lock; - thread_id thread; + if (lock.Lock()) { + // This function was originally written by Peter Folk + // and published in the BeDevTalk FAQ + // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209 - // Save current FDs - int oldIn = dup(STDIN_FILENO); - int oldOut = dup(STDOUT_FILENO); - int oldErr = dup(STDERR_FILENO); + thread_id thread; - int inPipe[2], outPipe[2], errPipe[2]; + // Save current FDs + int oldIn = dup(STDIN_FILENO); + int oldOut = dup(STDOUT_FILENO); + int oldErr = dup(STDERR_FILENO); - // Create new pipe FDs as stdin, stdout, stderr - if (pipe(inPipe) < 0) - goto err1; - if (pipe(outPipe) < 0) - goto err2; - if (pipe(errPipe) < 0) - goto err3; + int inPipe[2], outPipe[2], errPipe[2]; - errno = 0; + // Create new pipe FDs as stdin, stdout, stderr + if (pipe(inPipe) < 0) + goto err1; + if (pipe(outPipe) < 0) + goto err2; + if (pipe(errPipe) < 0) + goto err3; - // replace old stdin/stderr/stdout - dup2(inPipe[0], STDIN_FILENO); - close(inPipe[0]); - dup2(outPipe[1], STDOUT_FILENO); - close(outPipe[1]); - dup2(errPipe[1], STDERR_FILENO); - close(errPipe[1]); + errno = 0; - if (errno == 0) { - in = inPipe[1]; // Write to in, appears on cmd's stdin - out = outPipe[0]; // Read from out, taken from cmd's stdout - err = errPipe[0]; // Read from err, taken from cmd's stderr + // replace old stdin/stderr/stdout + dup2(inPipe[0], STDIN_FILENO); + close(inPipe[0]); + dup2(outPipe[1], STDOUT_FILENO); + close(outPipe[1]); + dup2(errPipe[1], STDERR_FILENO); + close(errPipe[1]); - // execute command - thread = load_image(argc, argv, envp); + if (errno == 0) { + in = inPipe[1]; // Write to in, appears on cmd's stdin + out = outPipe[0]; // Read from out, taken from cmd's stdout + err = errPipe[0]; // Read from err, taken from cmd's stderr + + // execute command + thread = load_image(argc, argv, envp); + } else { + thread = errno; + } + + // Restore old FDs + dup2(oldIn, STDIN_FILENO); + close(oldIn); + dup2(oldOut, STDOUT_FILENO); + close(oldOut); + dup2(oldErr, STDERR_FILENO); + close(oldErr); + + lock.Unlock(); + return thread; + + err3: + close(outPipe[0]); + close(outPipe[1]); + err2: + close(inPipe[0]); + close(inPipe[1]); + err1: + close(oldIn); + close(oldOut); + close(oldErr); + + lock.Unlock(); + return errno; } else { - thread = errno; + return B_ERROR; } - - // Restore old FDs - dup2(oldIn, STDIN_FILENO); - close(oldIn); - dup2(oldOut, STDOUT_FILENO); - close(oldOut); - dup2(oldErr, STDERR_FILENO); - close(oldErr); - return thread; - -err3: - close(outPipe[0]); - close(outPipe[1]); -err2: - close(inPipe[0]); - close(inPipe[1]); -err1: - close(oldIn); - close(oldOut); - close(oldErr); - return errno; } @@ -366,3 +396,123 @@ ZipperThread::WaitOnExternalZip() return status; } + +status_t +ZipperThread::_SelectInTracker(int32 tryNumber) +{ + // work in progress - unreliable - not ready to be used + + entry_ref parentRef; + BEntry entry(&fOutputEntryRef); + + if (!entry.Exists()) + return B_FILE_NOT_FOUND; + + entry.GetParent(&entry); + entry.GetRef(&parentRef); + + BMessenger trackerMessenger("application/x-vnd.Be-TRAK"); + if (!trackerMessenger.IsValid()) + return B_ERROR; + + BMessage request; + BMessage reply; + status_t status; + + if (tryNumber == 0) { + request.MakeEmpty(); + request.what = B_REFS_RECEIVED; + request.AddRef("refs", &parentRef); + trackerMessenger.SendMessage(&request, &reply); + } + + if (tryNumber > 20) + return B_ERROR; + + snooze(200000); + + // find out the number of Tracker windows + request.MakeEmpty(); + request.what = B_COUNT_PROPERTIES; + request.AddSpecifier("Window"); + reply.MakeEmpty(); + + status = trackerMessenger.SendMessage(&request, &reply); + if (status != B_OK) + return status; + + int32 windowCount; + status = reply.FindInt32("result", &windowCount); + if (status != B_OK) + return status; + + // find a likely parent window + bool foundWindow = false; + int32 index = 0; + for (; index < windowCount; index++) { + request.MakeEmpty(); + request.what = B_GET_PROPERTY; + request.AddSpecifier("Path"); + request.AddSpecifier("Poses"); + request.AddSpecifier("Window", index); + reply.MakeEmpty(); + + status = trackerMessenger.SendMessage(&request, &reply); + if (status != B_OK) + continue; + + entry_ref windowRef; + status = reply.FindRef("result", &windowRef); + if (status != B_OK) + continue; + + if (windowRef == parentRef) { + foundWindow = true; + break; + } + } + + if (!foundWindow) + return _SelectInTracker(tryNumber + 1); + + // find entry_ref in window - a newly opened window might + // be filling and the entry_ref perhaps not there yet? + request.MakeEmpty(); + request.what = B_GET_PROPERTY; + request.AddSpecifier("Entry"); + request.AddSpecifier("Poses"); + request.AddSpecifier("Window", index); + reply.MakeEmpty(); + + status = trackerMessenger.SendMessage(&request, &reply); + if (status != B_OK) + return _SelectInTracker(tryNumber + 1); + + bool foundRef = false; + entry_ref ref; + for (int32 m = 0;; m++) { + status = reply.FindRef("result", m, &ref); + if (status != B_OK) + break; + if (ref == fOutputEntryRef) + foundRef = true; + } + + // if entry_ref not found in window, start over + if (!foundRef) + return _SelectInTracker(tryNumber + 1); + + // select archive file in Tracker window + request.MakeEmpty(); + request.what = B_SET_PROPERTY; + request.AddRef("data", &fOutputEntryRef); + request.AddSpecifier("Selection"); + request.AddSpecifier("Poses"); + request.AddSpecifier("Window", index); + reply.MakeEmpty(); + + status = trackerMessenger.SendMessage(&request, &reply); + + return status; +} + diff --git a/src/add-ons/tracker/zipomatic/ZipperThread.h b/src/add-ons/tracker/zipomatic/ZipperThread.h index d6476cc4c4..aab3aab7a7 100644 --- a/src/add-ons/tracker/zipomatic/ZipperThread.h +++ b/src/add-ons/tracker/zipomatic/ZipperThread.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -48,15 +49,18 @@ private: const char** envp = (const char**)environ); void _SendMessageToWindow(uint32 what, - const char* name = NULL, + const char* name = NULL, const char* value = NULL); + status_t _SelectInTracker(int32 tryNumber = 0); + BMessenger fWindowMessenger; thread_id fZipProcess; int fStdIn; int fStdOut; int fStdErr; FILE* fOutputFile; + entry_ref fOutputEntryRef; }; #endif // _ZIPPER_THREAD_H