2 * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
3 * Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>.
4 * All rights reserved. Distributed under the terms of the MIT License.
16 #include <package/PackageInfo.h>
24 #include "FeaturedPackagesView.h"
26 #include "MainWindow.h"
27 #include "ServerSettings.h"
28 #include "ScreenshotWindow.h"
31 #undef B_TRANSLATION_CONTEXT
32 #define B_TRANSLATION_CONTEXT "App"
37 BApplication("application/x-vnd.Haiku-HaikuDepot"),
42 _CheckPackageDaemonRuns();
48 // We cannot let global destructors cleanup static BitmapRef objects,
49 // since calling BBitmap destructors needs a valid BApplication still
50 // around. That's why we do it here.
51 PackageInfo::CleanupDefaultIcon();
52 FeaturedPackagesView::CleanupIcons();
53 ScreenshotWindow::CleanupIcons();
60 if (fMainWindow
!= NULL
61 && fMainWindow
->LockLooperWithTimeout(1500000) == B_OK
) {
62 BMessage windowSettings
;
63 fMainWindow
->StoreSettings(windowSettings
);
65 fMainWindow
->UnlockLooper();
67 _StoreSettings(windowSettings
);
81 _LoadSettings(settings
);
83 fMainWindow
= new MainWindow(settings
);
84 _ShowWindow(fMainWindow
);
89 App::MessageReceived(BMessage
* message
)
91 switch (message
->what
) {
92 case MSG_MAIN_WINDOW_CLOSED
:
94 BMessage windowSettings
;
95 if (message
->FindMessage("window settings",
96 &windowSettings
) == B_OK
) {
97 _StoreSettings(windowSettings
);
101 if (fWindowCount
== 0)
107 BApplication::MessageReceived(message
);
114 App::RefsReceived(BMessage
* message
)
118 while (message
->FindRef("refs", index
++, &ref
) == B_OK
) {
119 BEntry
entry(&ref
, true);
129 WEB_APP_BASE_URL_SWITCH
,
131 FORCE_NO_NETWORKING_SWITCH
,
140 fprintf(stdout
, "HaikuDepot ");
141 fprintf(stdout
, "[-u|--webappbaseurl <web-app-base-url>]\n");
142 fprintf(stdout
, "[-v|--verbosity [off|info|debug|trace]\n");
143 fprintf(stdout
, "[--nonetworking]\n");
144 fprintf(stdout
, "[--prefercache]\n");
145 fprintf(stdout
, "[--dropcache]\n");
146 fprintf(stdout
, "[-h|--help]\n");
147 fprintf(stdout
, "\n");
148 fprintf(stdout
, "'-h' : causes this help text to be printed out.\n");
149 fprintf(stdout
, "'-v' : allows for the verbosity level to be set.\n");
150 fprintf(stdout
, "'-u' : allows for the haiku depot server url to be\n");
151 fprintf(stdout
, " configured.\n");
152 fprintf(stdout
, "'--nonetworking' : prevents network access.**\n");
153 fprintf(stdout
, "'--prefercache' : prefer to get data from cache rather\n");
154 fprintf(stdout
, " then obtain data from the network.**\n");
155 fprintf(stdout
, "'--dropcache' : drop cached data before performing\n");
156 fprintf(stdout
, " bulk operations.**\n");
157 fprintf(stdout
, "\n");
158 fprintf(stdout
, "** = only applies to bulk operations.\n");
163 app_resolve_switch(char *arg
)
165 int arglen
= strlen(arg
);
167 if (arglen
> 0 && arg
[0] == '-') {
169 if (arglen
> 3 && arg
[1] == '-') { // long form
170 if (0 == strcmp(&arg
[2], "webappbaseurl"))
171 return WEB_APP_BASE_URL_SWITCH
;
173 if (0 == strcmp(&arg
[2], "help"))
176 if (0 == strcmp(&arg
[2], "verbosity"))
177 return VERBOSITY_SWITCH
;
179 if (0 == strcmp(&arg
[2], "nonetworking"))
180 return FORCE_NO_NETWORKING_SWITCH
;
182 if (0 == strcmp(&arg
[2], "prefercache"))
183 return PREFER_CACHE_SWITCH
;
185 if (0 == strcmp(&arg
[2], "dropcache"))
186 return DROP_CACHE_SWITCH
;
188 if (arglen
== 2) { // short form
191 return WEB_APP_BASE_URL_SWITCH
;
197 return VERBOSITY_SWITCH
;
202 return UNKNOWN_SWITCH
;
210 App::ArgvReceived(int32 argc
, char* argv
[])
212 for (int i
= 1; i
< argc
;) {
214 // check to make sure that if there is a value for the switch,
215 // that the value is in fact supplied.
217 switch (app_resolve_switch(argv
[i
])) {
218 case VERBOSITY_SWITCH
:
219 case WEB_APP_BASE_URL_SWITCH
:
221 fprintf(stdout
, "unexpected end of arguments; missing "
222 "value for switch [%s]\n", argv
[i
]);
232 // now process each switch.
234 switch (app_resolve_switch(argv
[i
])) {
236 case VERBOSITY_SWITCH
:
237 if (!Logger::SetLevelByName(argv
[i
+1])) {
238 fprintf(stdout
, "unknown log level [%s]\n", argv
[i
+ 1]);
241 i
++; // also move past the log level value
249 case WEB_APP_BASE_URL_SWITCH
:
250 if (ServerSettings::SetBaseUrl(BUrl(argv
[i
+ 1])) != B_OK
) {
251 fprintf(stdout
, "malformed web app base url; %s\n",
256 fprintf(stdout
, "did configure the web base url; %s\n",
260 i
++; // also move past the url value
264 case FORCE_NO_NETWORKING_SWITCH
:
265 ServerSettings::SetForceNoNetwork(true);
268 case PREFER_CACHE_SWITCH
:
269 ServerSettings::SetPreferCache(true);
272 case DROP_CACHE_SWITCH
:
273 ServerSettings::SetDropCache(true);
278 BEntry
entry(argv
[i
], true);
284 fprintf(stdout
, "unknown switch; %s\n", argv
[i
]);
289 i
++; // move on at least one arg
294 // #pragma mark - private
298 App::_Open(const BEntry
& entry
)
301 if (!entry
.Exists() || entry
.GetPath(&path
) != B_OK
) {
302 fprintf(stderr
, "Package file not found: %s\n", path
.Path());
306 // Try to parse package file via Package Kit
307 BPackageKit::BPackageInfo info
;
308 status_t status
= info
.ReadFromPackageFile(path
.Path());
309 if (status
!= B_OK
) {
310 fprintf(stderr
, "Failed to parse package file: %s\n",
315 // Transfer information into PackageInfo
316 PackageInfoRef
package(new(std::nothrow
) PackageInfo(info
), true);
317 if (package
.Get() == NULL
) {
318 fprintf(stderr
, "Could not allocate PackageInfo\n");
322 package
->SetLocalFilePath(path
.Path());
325 _LoadSettings(settings
);
327 MainWindow
* window
= new MainWindow(settings
, package
);
333 App::_ShowWindow(MainWindow
* window
)
341 App::_LoadSettings(BMessage
& settings
)
343 if (!fSettingsRead
) {
345 if (load_settings(&fSettings
, "main_settings", "HaikuDepot") != B_OK
)
346 fSettings
.MakeEmpty();
348 settings
= fSettings
;
349 return !fSettings
.IsEmpty();
354 App::_StoreSettings(const BMessage
& settings
)
356 // Take what is in settings and replace data under the same name in
357 // fSettings, leaving anything in fSettings that is not contained in
365 while (settings
.GetInfo(B_ANY_TYPE
, i
++, &name
, &type
, &count
) == B_OK
) {
366 fSettings
.RemoveName(name
);
367 for (int32 j
= 0; j
< count
; j
++) {
370 if (settings
.FindData(name
, type
, j
, &data
, &size
) != B_OK
)
372 fSettings
.AddData(name
, type
, data
, size
);
376 save_settings(&fSettings
, "main_settings", "HaikuDepot");
383 static const char* kPackageDaemonSignature
384 = "application/x-vnd.haiku-package_daemon";
387 App::_CheckPackageDaemonRuns()
389 while (!be_roster
->IsRunning(kPackageDaemonSignature
)) {
390 BAlert
* alert
= new BAlert("start_package_daemon",
391 B_TRANSLATE("HaikuDepot needs the package daemon to function, "
392 "and it appears to be not running.\n"
393 "Would you like to start it now?"),
394 B_TRANSLATE("No, quit HaikuDepot"),
395 B_TRANSLATE("Start package daemon"), NULL
, B_WIDTH_AS_USUAL
,
397 alert
->SetShortcut(0, B_ESCAPE
);
399 if (alert
->Go() == 0)
402 if (!_LaunchPackageDaemon())
409 App::_LaunchPackageDaemon()
411 status_t ret
= be_roster
->Launch(kPackageDaemonSignature
);
414 = B_TRANSLATE("Starting the package daemon failed:\n\n%Error%");
415 errorMessage
.ReplaceAll("%Error%", strerror(ret
));
417 BAlert
* alert
= new BAlert("package_daemon_problem",
419 B_TRANSLATE("Quit HaikuDepot"),
420 B_TRANSLATE("Try again"), NULL
, B_WIDTH_AS_USUAL
,
422 alert
->SetShortcut(0, B_ESCAPE
);
424 if (alert
->Go() == 0)
427 // TODO: Would be nice to send a message to the package daemon instead
428 // and get a reply once it is ready.