Work in progress: Tiling window placement, screen-center-preferring with semi-fixed slots. Not sure I like it. (It looks nice as long as the windows stay equally sized, which they don't.) Settings weren't used anymore, and could be removed. Clean-ups. Changed archive creation to not update an existing archive, but instead create a new archive with a slightly altered filename along-side the existing file. Lock added to safe-guard pipe redirection. A window's Stop/Continue alert now shows the name of the archive in making. I added some code to show and select the archive in Tracker, post-creation, but it does not work reliably, so I've disabled it for now.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34044 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jonas Sundström 2009-11-14 21:49:35 +00:00
parent aece77090d
commit 714236b802
12 changed files with 471 additions and 497 deletions

View File

@ -6,8 +6,6 @@ Application ZipOMatic-Z :
GenericThread.cpp GenericThread.cpp
ZipOMatic.cpp ZipOMatic.cpp
ZipOMaticActivity.cpp ZipOMaticActivity.cpp
ZipOMaticMisc.cpp
ZipOMaticSettings.cpp
ZipOMaticWindow.cpp ZipOMaticWindow.cpp
ZipperThread.cpp ZipperThread.cpp

View File

@ -11,7 +11,6 @@
#include <Alert.h> #include <Alert.h>
#include <Roster.h> #include <Roster.h>
#include <Screen.h>
#include <TrackerAddOnAppLaunch.h> #include <TrackerAddOnAppLaunch.h>
#include "ZipOMaticMisc.h" #include "ZipOMaticMisc.h"
@ -31,45 +30,27 @@ main()
ZipOMatic::ZipOMatic() ZipOMatic::ZipOMatic()
: :
BApplication(ZIPOMATIC_APP_SIG), BApplication(ZIPOMATIC_APP_SIG),
fSettings(),
fGotRefs(false), fGotRefs(false),
fInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, this)), fInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, this))
fWindowFrame(200, 200, 430, 310)
{ {
status_t status = _ReadSettings();
if (status != B_OK)
ErrorMessage("_ReadSettings()", status);
} }
ZipOMatic::~ZipOMatic() ZipOMatic::~ZipOMatic()
{ {
status_t status = _WriteSettings();
if (status != B_OK)
ErrorMessage("_WriteSettings()", status);
} }
void void
ZipOMatic::RefsReceived(BMessage* message) ZipOMatic::RefsReceived(BMessage* message)
{ {
message->RemoveName("dir_ref");
entry_ref ref; entry_ref ref;
if (message->FindRef("refs", &ref) != B_OK) { if (message->FindRef("refs", &ref) == B_OK) {
if (!IsLaunching()) _UseExistingOrCreateNewWindow(message);
PostMessage(B_SILENT_RELAUNCH);
return;
}
if (IsLaunching())
fGotRefs = true; fGotRefs = true;
} else if (!IsLaunching()) {
BMessage* msg = new BMessage(*message); PostMessage(B_SILENT_RELAUNCH);
}
_UseExistingOrCreateNewWindow(msg);
} }
@ -87,9 +68,6 @@ ZipOMatic::MessageReceived(BMessage* message)
switch (message->what) { switch (message->what) {
case ZIPPO_WINDOW_QUIT: case ZIPPO_WINDOW_QUIT:
{ {
BRect frame;
if (message->FindRect("frame", &frame) == B_OK)
fWindowFrame = frame;
snooze(200000); snooze(200000);
if (CountWindows() == 0) if (CountWindows() == 0)
Quit(); Quit();
@ -120,7 +98,7 @@ ZipOMatic::MessageReceived(BMessage* message)
bool bool
ZipOMatic::QuitRequested (void) ZipOMatic::QuitRequested(void)
{ {
if (CountWindows() <= 0) if (CountWindows() <= 0)
return true; return true;
@ -208,43 +186,42 @@ void
ZipOMatic::_UseExistingOrCreateNewWindow(BMessage* message) ZipOMatic::_UseExistingOrCreateNewWindow(BMessage* message)
{ {
int32 windowCount = 0; int32 windowCount = 0;
ZippoWindow* window; BWindow* bWindow;
bool foundNonBusyWindow = false; ZippoWindow* zWindow;
BList list;
while (1) { while (1) {
window = dynamic_cast<ZippoWindow*>(WindowAt(windowCount++)); bWindow = WindowAt(windowCount++);
if (window == NULL) if (bWindow == NULL)
break; break;
if (window->Lock()) { zWindow = dynamic_cast<ZippoWindow*>(bWindow);
if (!window->IsZipping()) { if (zWindow == NULL)
foundNonBusyWindow = true; continue;
list.AddItem(zWindow);
if (zWindow->Lock()) {
if (!zWindow->IsZipping()) {
if (message != NULL) if (message != NULL)
window->PostMessage(message); zWindow->PostMessage(message);
window->SetWorkspaces(B_CURRENT_WORKSPACE); zWindow->SetWorkspaces(B_CURRENT_WORKSPACE);
window->Activate(); zWindow->Activate();
window->Unlock(); zWindow->Unlock();
break; return;
} }
window->Unlock(); zWindow->Unlock();
} }
} }
if (!foundNonBusyWindow) if (message) {
{ zWindow = new ZippoWindow(list);
BScreen screen; zWindow->PostMessage(message);
fWindowFrame.OffsetBy(screen.Frame().LeftTop()); } else {
zWindow = new ZippoWindow(list, true);
_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); zWindow->Show();
window->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<ZippoWindow*>(window);
if (zippo == NULL)
continue;
list.AddItem(zippo);
}
for (int32 i = 0;; i++) {
zippo = static_cast<ZippoWindow*>(list.ItemAt(i));
if (zippo == NULL)
break;
if (zippo->Lock()) {
if (frame->LeftTop() == zippo->Frame().LeftTop())
frame->OffsetBy(20, 20);
zippo->Unlock();
}
}
}

View File

@ -5,9 +5,6 @@
#include <Application.h> #include <Application.h>
#include <Invoker.h> #include <Invoker.h>
#include <Message.h> #include <Message.h>
#include <Rect.h>
#include "ZipOMaticSettings.h"
class ZipOMatic : public BApplication class ZipOMatic : public BApplication
@ -22,18 +19,13 @@ public:
virtual bool QuitRequested(); virtual bool QuitRequested();
private: private:
status_t _ReadSettings();
status_t _WriteSettings();
void _CascadeOnFrameCollision(BRect* frame);
void _SilentRelaunch(); void _SilentRelaunch();
void _UseExistingOrCreateNewWindow(BMessage* void _UseExistingOrCreateNewWindow(BMessage*
message = NULL); message = NULL);
void _StopZipping(); void _StopZipping();
ZippoSettings fSettings;
bool fGotRefs; bool fGotRefs;
BInvoker* fInvoker; BInvoker* fInvoker;
BRect fWindowFrame;
}; };
#endif // _ZIPOMATIC_H_ #endif // _ZIPOMATIC_H_

View File

@ -88,7 +88,7 @@ Activity::Pulse()
uchar tmp = fPattern.data[7]; uchar tmp = fPattern.data[7];
for (int j = 7; j > 0; --j) 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; fPattern.data[0] = tmp;
@ -103,10 +103,6 @@ Activity::Draw(BRect rect)
BRect bitmapRect = fBitmap->Bounds(); BRect bitmapRect = fBitmap->Bounds();
if (bitmapRect != viewRect) { if (bitmapRect != viewRect) {
printf("Activity::Draw(): bitmapRect != viewRect\n");
bitmapRect.PrintToStream();
viewRect.PrintToStream();
delete fBitmap; delete fBitmap;
_CreateBitmap(); _CreateBitmap();
} }
@ -138,7 +134,7 @@ Activity::_DrawOnBitmap(bool running)
fBitmapView->SetHighColor(color); fBitmapView->SetHighColor(color);
// draw the pole // draw the pole
rect.InsetBy(2,2); rect.InsetBy(2, 2);
fBitmapView->FillRect(rect, fPattern); fBitmapView->FillRect(rect, fPattern);
// draw frame // draw frame
@ -198,19 +194,19 @@ Activity::_DrawOnBitmap(bool running)
fBitmapView->SetDrawingMode(B_OP_SUBTRACT); fBitmapView->SetDrawingMode(B_OP_SUBTRACT);
fBitmapView->StrokeRect(rect); fBitmapView->StrokeRect(rect);
rect.InsetBy(1,1); rect.InsetBy(1, 1);
_LightenBitmapHighColor(& color); _LightenBitmapHighColor(& color);
fBitmapView->StrokeRect(rect); fBitmapView->StrokeRect(rect);
rect.InsetBy(1,1); rect.InsetBy(1, 1);
_LightenBitmapHighColor(& color); _LightenBitmapHighColor(& color);
fBitmapView->StrokeRect(rect); fBitmapView->StrokeRect(rect);
rect.InsetBy(1,1); rect.InsetBy(1, 1);
_LightenBitmapHighColor(& color); _LightenBitmapHighColor(& color);
fBitmapView->StrokeRect(rect); fBitmapView->StrokeRect(rect);
rect.InsetBy(1,1); rect.InsetBy(1, 1);
_LightenBitmapHighColor(& color); _LightenBitmapHighColor(& color);
fBitmapView->StrokeRect(rect); fBitmapView->StrokeRect(rect);

View File

@ -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 <string.h>
#include <Debug.h>
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)));
}

View File

@ -9,12 +9,6 @@
#define ZIPOMATIC_MISC_H #define ZIPOMATIC_MISC_H
#include <Directory.h>
#include <FindDirectory.h>
#include <Path.h>
#include <Volume.h>
#define ZIPOMATIC_APP_SIG "application/x-vnd.haiku.zip-o-matic" #define ZIPOMATIC_APP_SIG "application/x-vnd.haiku.zip-o-matic"
#define ZIPPO_WINDOW_QUIT 'winq' #define ZIPPO_WINDOW_QUIT 'winq'
@ -24,11 +18,6 @@
#define ZIPPO_TASK_DESCRIPTION 'strt' #define ZIPPO_TASK_DESCRIPTION 'strt'
#define ZIPPO_LINE_OF_STDOUT 'outp' #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 #endif // ZIPOMATIC_MISC_H

View File

@ -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 <Debug.h>
#include <Directory.h>
#include <File.h>
#include <Path.h>
#include <VolumeRoster.h>
#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);
}

View File

@ -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 <FindDirectory.h>
#include <Message.h>
#include <String.h>
#include <Volume.h>
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

View File

@ -21,6 +21,7 @@
#include <LayoutBuilder.h> #include <LayoutBuilder.h>
#include <Path.h> #include <Path.h>
#include <Roster.h> #include <Roster.h>
#include <Screen.h>
#include <SeparatorView.h> #include <SeparatorView.h>
#include <String.h> #include <String.h>
@ -30,12 +31,13 @@
#include "ZipperThread.h" #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), B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_NOT_ZOOMABLE),
fWindowList(windowList),
fThread(NULL), fThread(NULL),
fWindowGotRefs(false), fKeepOpen(keepOpen),
fZippingWasStopped(false), fZippingWasStopped(false),
fFileCount(0), fFileCount(0),
fWindowInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL, fWindowInvoker(new BInvoker(new BMessage(ZIPPO_QUIT_OR_CONTINUE), NULL,
@ -70,10 +72,7 @@ ZippoWindow::ZippoWindow(BRect frame, BMessage* refs)
.End() .End()
.End(); .End();
if (refs != NULL) { _FindBestPlacement();
fWindowGotRefs = true;
_StartZipping(refs);
}
} }
@ -88,9 +87,6 @@ ZippoWindow::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case B_REFS_RECEIVED: case B_REFS_RECEIVED:
_StartZipping(message);
break;
case B_SIMPLE_DATA: case B_SIMPLE_DATA:
if (IsZipping()) { if (IsZipping()) {
message->what = B_REFS_RECEIVED; message->what = B_REFS_RECEIVED;
@ -125,8 +121,11 @@ ZippoWindow::MessageReceived(BMessage* message)
case ZIPPO_TASK_DESCRIPTION: case ZIPPO_TASK_DESCRIPTION:
{ {
BString string; 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()); fArchiveNameView->SetText(string.String());
}
break; break;
} }
@ -202,8 +201,11 @@ ZippoWindow::QuitRequested()
fThread->SuspendExternalZip(); fThread->SuspendExternalZip();
fActivityView->Pause(); fActivityView->Pause();
BAlert* alert = new BAlert("Stop or Continue", BString message;
"Are you sure you want to stop creating this archive?", "Stop", 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); "Continue", NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
alert->Go(fWindowInvoker); alert->Go(fWindowInvoker);
@ -261,7 +263,155 @@ ZippoWindow::IsZipping()
void void
ZippoWindow::_CloseWindowOrKeepOpen() ZippoWindow::_CloseWindowOrKeepOpen()
{ {
if (fWindowGotRefs) if (!fKeepOpen)
PostMessage(B_QUIT_REQUESTED); 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<BWindow*>(fWindowList.ItemAt(i));
if (win == NULL)
break;
ZippoWindow* window = dynamic_cast<ZippoWindow*>(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<BRect*>(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<BRect*>(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;
}

View File

@ -3,6 +3,8 @@
#include <Button.h> #include <Button.h>
#include <List.h>
#include <Rect.h>
#include <StringView.h> #include <StringView.h>
#include <Window.h> #include <Window.h>
@ -10,10 +12,19 @@
#include "ZipperThread.h" #include "ZipperThread.h"
enum direction {
up,
down,
left,
right
};
class ZippoWindow : public BWindow class ZippoWindow : public BWindow
{ {
public: public:
ZippoWindow(BRect frame, BMessage* refs = NULL); ZippoWindow(BList windowList,
bool keepOpen = false);
~ZippoWindow(); ~ZippoWindow();
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
@ -27,14 +38,24 @@ private:
void _StartZipping(BMessage* message); void _StartZipping(BMessage* message);
void _CloseWindowOrKeepOpen(); 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; Activity* fActivityView;
BStringView* fArchiveNameView; BStringView* fArchiveNameView;
BStringView* fZipOutputView; BStringView* fZipOutputView;
BButton* fStopButton; BButton* fStopButton;
ZipperThread* fThread; ZipperThread* fThread;
BString fArchiveName;
bool fWindowGotRefs; bool fKeepOpen;
bool fZippingWasStopped; bool fZippingWasStopped;
int32 fFileCount; int32 fFileCount;

View File

@ -12,9 +12,11 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <FindDirectory.h> #include <FindDirectory.h>
#include <Locker.h>
#include <Message.h> #include <Message.h>
#include <Path.h> #include <Path.h>
#include <Volume.h> #include <Volume.h>
@ -34,9 +36,6 @@ ZipperThread::ZipperThread(BMessage* refsMessage, BWindow* window)
fOutputFile(NULL) fOutputFile(NULL)
{ {
fThreadDataStore = new BMessage(*refsMessage); fThreadDataStore = new BMessage(*refsMessage);
// leak?
// prevents bug with B_SIMPLE_DATA
// (drag&drop messages)
} }
@ -48,9 +47,6 @@ ZipperThread::~ZipperThread()
status_t status_t
ZipperThread::ThreadStartup() ZipperThread::ThreadStartup()
{ {
BString archiveName = "Archive.zip";
// do all refs have the same parent dir?
type_code type = B_REF_TYPE; type_code type = B_REF_TYPE;
int32 refCount = 0; int32 refCount = 0;
entry_ref ref; entry_ref ref;
@ -58,23 +54,17 @@ ZipperThread::ThreadStartup()
bool sameFolder = true; bool sameFolder = true;
status_t status = fThreadDataStore->GetInfo("refs", &type, &refCount); status_t status = fThreadDataStore->GetInfo("refs", &type, &refCount);
if (status != B_OK) if (status != B_OK || refCount < 1) {
return status; _SendMessageToWindow(ZIPPO_THREAD_EXIT_ERROR);
Quit();
return B_ERROR;
}
for (int index = 0; index < refCount; index++) { for (int index = 0; index < refCount; index++) {
fThreadDataStore->FindRef("refs", index, &ref); fThreadDataStore->FindRef("refs", index, &ref);
if (index > 0) { if (index > 0) {
BEntry entry(&ref); if (lastRef.directory != ref.directory) {
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) {
sameFolder = false; sameFolder = false;
break; break;
} }
@ -82,8 +72,27 @@ ZipperThread::ThreadStartup()
lastRef = ref; lastRef = ref;
} }
// change active dir entry_ref dirRef;
if (sameFolder) { 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); BEntry entry(&lastRef);
BPath path; BPath path;
entry.GetParent(&entry); entry.GetParent(&entry);
@ -95,10 +104,28 @@ ZipperThread::ThreadStartup()
chdir(path.Path()); chdir(path.Path());
} }
// archive filename BString archiveName;
if (refCount == 1) {
if (refCount > 1)
archiveName = "Archive";
else
archiveName = lastRef.name; 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; int32 argc = refCount + 3;
@ -108,15 +135,12 @@ ZipperThread::ThreadStartup()
argv[1] = strdup("-ry"); argv[1] = strdup("-ry");
argv[2] = strdup(archiveName.String()); argv[2] = strdup(archiveName.String());
// files to zip
for (int index = 0; index < refCount; index++) { for (int index = 0; index < refCount; index++) {
fThreadDataStore->FindRef("refs", index, &ref); fThreadDataStore->FindRef("refs", index, &ref);
if (sameFolder) { if (gotDirRef || sameFolder) {
// just the file name
argv[3 + index] = strdup(ref.name); argv[3 + index] = strdup(ref.name);
} else { } else {
// full path
BPath path(&ref); BPath path(&ref);
BString file = path.Path(); BString file = path.Path();
argv[3 + index] = strdup(path.Path()); argv[3 + index] = strdup(path.Path());
@ -138,8 +162,6 @@ ZipperThread::ThreadStartup()
if (fOutputFile == NULL) if (fOutputFile == NULL)
return errno; return errno;
archiveName.Prepend("Creating archive: ");
_SendMessageToWindow(ZIPPO_TASK_DESCRIPTION, "archive_filename", _SendMessageToWindow(ZIPPO_TASK_DESCRIPTION, "archive_filename",
archiveName.String()); archiveName.String());
_SendMessageToWindow(ZIPPO_LINE_OF_STDOUT, "zip_output", _SendMessageToWindow(ZIPPO_LINE_OF_STDOUT, "zip_output",
@ -152,8 +174,6 @@ ZipperThread::ThreadStartup()
status_t status_t
ZipperThread::ExecuteUnit() ZipperThread::ExecuteUnit()
{ {
// read output from /bin/zip
// send it to window
char buffer[4096]; char buffer[4096];
char* output = fgets(buffer, sizeof(buffer) - 1, fOutputFile); char* output = fgets(buffer, sizeof(buffer) - 1, fOutputFile);
@ -185,6 +205,8 @@ ZipperThread::ThreadShutdown()
close(fStdOut); close(fStdOut);
close(fStdErr); close(fStdErr);
// _SelectInTracker();
return B_OK; return B_OK;
} }
@ -192,7 +214,6 @@ ZipperThread::ThreadShutdown()
void void
ZipperThread::ThreadStartupFailed(status_t status) ZipperThread::ThreadStartupFailed(status_t status)
{ {
ErrorMessage("ZipperThread::ThreadStartupFailed() \n", status);
Quit(); Quit();
} }
@ -200,8 +221,6 @@ ZipperThread::ThreadStartupFailed(status_t status)
void void
ZipperThread::ExecuteUnitFailed(status_t status) ZipperThread::ExecuteUnitFailed(status_t status)
{ {
ErrorMessage("ZipperThread::ExecuteUnitFailed() \n", status);
if (status == EOF) { if (status == EOF) {
// thread has finished, been quit or killed, we don't know // thread has finished, been quit or killed, we don't know
_SendMessageToWindow(ZIPPO_THREAD_EXIT); _SendMessageToWindow(ZIPPO_THREAD_EXIT);
@ -217,7 +236,8 @@ ZipperThread::ExecuteUnitFailed(status_t status)
void void
ZipperThread::ThreadShutdownFailed(status_t status) ZipperThread::ThreadShutdownFailed(status_t status)
{ {
ErrorMessage("ZipperThread::ThreadShutdownFailed() \n", status); fprintf(stderr, "ZipperThread::ThreadShutdownFailed(): %s\n",
strerror(status));
} }
@ -234,8 +254,11 @@ thread_id
ZipperThread::_PipeCommand(int argc, const char** argv, int& in, int& out, ZipperThread::_PipeCommand(int argc, const char** argv, int& in, int& out,
int& err, const char** envp) int& err, const char** envp)
{ {
// This function was originally written by Peter Folk <pfolk@uni.uiuc.edu> static BLocker lock;
// and published in the BeDevTalk FAQ
if (lock.Lock()) {
// This function was originally written by Peter Folk
// <pfolk@uni.uiuc.edu> and published in the BeDevTalk FAQ
// http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209 // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
thread_id thread; thread_id thread;
@ -283,19 +306,26 @@ ZipperThread::_PipeCommand(int argc, const char** argv, int& in, int& out,
close(oldOut); close(oldOut);
dup2(oldErr, STDERR_FILENO); dup2(oldErr, STDERR_FILENO);
close(oldErr); close(oldErr);
lock.Unlock();
return thread; return thread;
err3: err3:
close(outPipe[0]); close(outPipe[0]);
close(outPipe[1]); close(outPipe[1]);
err2: err2:
close(inPipe[0]); close(inPipe[0]);
close(inPipe[1]); close(inPipe[1]);
err1: err1:
close(oldIn); close(oldIn);
close(oldOut); close(oldOut);
close(oldErr); close(oldErr);
lock.Unlock();
return errno; return errno;
} else {
return B_ERROR;
}
} }
@ -366,3 +396,123 @@ ZipperThread::WaitOnExternalZip()
return status; 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;
}

View File

@ -12,6 +12,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <Entry.h>
#include <Message.h> #include <Message.h>
#include <Messenger.h> #include <Messenger.h>
#include <String.h> #include <String.h>
@ -51,12 +52,15 @@ private:
const char* name = NULL, const char* name = NULL,
const char* value = NULL); const char* value = NULL);
status_t _SelectInTracker(int32 tryNumber = 0);
BMessenger fWindowMessenger; BMessenger fWindowMessenger;
thread_id fZipProcess; thread_id fZipProcess;
int fStdIn; int fStdIn;
int fStdOut; int fStdOut;
int fStdErr; int fStdErr;
FILE* fOutputFile; FILE* fOutputFile;
entry_ref fOutputEntryRef;
}; };
#endif // _ZIPPER_THREAD_H #endif // _ZIPPER_THREAD_H