source: src-qt4/pc-softwaremanager/mainUI.cpp @ 78fa8b2

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3
Last change on this file since 78fa8b2 was 78fa8b2, checked in by Ken Moore <ken@…>, 16 months ago

Merge the new AppCafe? into the src-qt4 tree from the projects directory

  • Property mode set to 100644
File size: 33.5 KB
Line 
1/***************************************************************************
2 *   Copyright (C) 2011 - iXsystems                                       *
3 *   kris@pcbsd.org  *
4 *   tim@pcbsd.org   *
5 *   ken@pcbsd.org   *
6 *                                                                         *
7 *   Permission is hereby granted, free of charge, to any person obtaining *
8 *   a copy of this software and associated documentation files (the       *
9 *   "Software"), to deal in the Software without restriction, including   *
10 *   without limitation the rights to use, copy, modify, merge, publish,   *
11 *   distribute, sublicense, and/or sell copies of the Software, and to    *
12 *   permit persons to whom the Software is furnished to do so, subject to *
13 *   the following conditions:                                             *
14 *                                                                         *
15 *   The above copyright notice and this permission notice shall be        *
16 *   included in all copies or substantial portions of the Software.       *
17 *                                                                         *
18 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
19 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
20 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
21 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
22 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
23 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
24 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
25 ***************************************************************************/
26#include "mainUI.h"
27#include "ui_mainUI.h"
28
29MainUI::MainUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainUI){
30  //initialization function
31  ui->setupUi(this); //load the Qt-Designer file
32  defaultIcon = ":/application.png";
33  statusLabel = new QLabel();
34  ui->statusbar->addWidget(statusLabel);
35}
36
37void MainUI::setWardenMode(QString dir, QString ip){
38  wardenDir = dir; wardenIP = ip;
39}
40
41void MainUI::ProgramInit()
42{ 
43   qDebug("Application starting...");
44   //Initial Checks
45     bool wardenMode = !wardenDir.isEmpty();
46     bool ok = Extras::checkUser(wardenMode);
47     if(!ok && wardenMode){  //Not root
48       QMessageBox::information( this, tr("Error!"), tr("The AppCafe must be run as root when in Warden compatibility mode") );
49       close();     
50     }else if( !ok && !wardenMode){
51       QMessageBox::information( this, tr("Error!"), tr("The AppCafe must be started with user permissions!")+"\n"+tr("The user must also be a part of the \"operator\" group") );
52       close();
53     }
54   
55   //Initialize the backend worker class
56   //qDebug() << "Initialize Backend";
57   PBI = new PBIBackend();
58     if(wardenMode){ PBI->setWardenMode(wardenDir, wardenIP); }
59     
60   //Initialize the Installed tab
61   //qDebug() << "Initialize Installed Tab";
62   initializeInstalledTab();
63   //Initialize the PBI Browser
64   //qDebug() << "Initialize Browser Tab";
65   initializeBrowserTab();
66   
67   //Now startup the backend
68   //qDebug() << "Startup Backend";
69     connect(PBI,SIGNAL(LocalPBIChanges()),this,SLOT(slotRefreshInstallTab()) );
70     connect(PBI,SIGNAL(PBIStatusChange(QString)),this,SLOT(slotPBIStatusUpdate(QString)) );
71     connect(PBI,SIGNAL(RepositoryInfoReady()),this,SLOT(slotEnableBrowser()) );
72     connect(PBI,SIGNAL(NoRepoAvailable()),this,SLOT(slotDisableBrowser()) );
73     connect(PBI,SIGNAL(SearchComplete(QStringList,QStringList)),this,SLOT(slotShowSearchResults(QStringList, QStringList)) );
74     connect(PBI,SIGNAL(SimilarFound(QStringList)),this,SLOT(slotShowSimilarApps(QStringList)) );
75     connect(PBI,SIGNAL(Error(QString,QString)),this,SLOT(slotDisplayError(QString,QString)) );
76     PBI->start();
77
78   //Make sure we start on the installed tab
79   ui->tabWidget->setCurrentWidget(ui->tab_installed);
80}
81
82void MainUI::slotSingleInstance(){
83  this->raise();
84  this->showNormal();
85  this->activateWindow();
86}
87
88void MainUI::closeEvent(QCloseEvent *event){
89  bool safe = PBI->safeToQuit();
90  if(!safe){
91    //Verify that they want to continue
92    QMessageBox::StandardButton button = QMessageBox::warning(this, tr("AppCafe Processes Running"), tr("The AppCafe currently has actions pending. Do you want to cancel all running processes and quit anyway?"), QMessageBox::Yes | QMessageBox::Cancel,QMessageBox::Cancel);
93    if(button == QMessageBox::Yes){ //close down
94      PBI->cancelActions( PBI->installedList() ); //close down safely
95    }else{
96      event->ignore();
97      return;
98    }
99  }
100  this->close();
101}
102// ========================
103// ===== MENU OPTIONS =====
104// ========================
105void MainUI::on_actionImport_PBI_List_triggered(){
106  QString file = QFileDialog::getOpenFileName( this, tr("Import PBI File List"), QDir::homePath(), tr("PBI List (*.pbilist)"));
107  if(file.isEmpty()){ return; } //action cancelled
108  bool ok = PBI->importPbiListFromFile(file);
109  if(!ok){ qDebug() << QMessageBox::warning(this,tr("Import Error"),tr("There was an error importing the PBI list")+"\n"+tr("Please make sure that the file has not been corrupted and try again")); }
110}
111
112void MainUI::on_actionExport_PBI_List_triggered(){
113  QString file = QFileDialog::getSaveFileName( this, tr("Export PBI File List"), QDir::homePath()+"/exportfile.pbilist", tr("PBI List (*.pbilist)"));
114  if(file.isEmpty()){ return; } //action cancelled
115  bool ok = PBI->exportPbiListToFile(file);
116  if(!ok){ qDebug() << QMessageBox::warning(this,tr("Export Error"),tr("There was an error exporting the PBI list")+"\n"+tr("Please make sure that you have the proper directory permissions and try again")); }
117}
118
119void MainUI::on_actionQuit_triggered(){
120  this->close();
121}
122
123void MainUI::on_actionAppCafe_Settings_triggered(){
124  PBI->openConfigurationDialog();
125}
126
127// =========================
128// ===== INSTALLED TAB =====
129// =========================
130void MainUI::initializeInstalledTab(){
131  //Setup the action menu for installed applications
132  actionMenu = new QMenu();
133    actionMenu->addAction( QIcon(":icons/view-refresh.png"), tr("Upgrade"), this, SLOT(slotActionUpdate()) );
134    actionMenu->addSeparator();
135    QMenu *dmenu = actionMenu->addMenu( QIcon(":icons/xdg_desktop.png"), tr("Desktop Icons"));
136      dmenu->addAction( QIcon(":icons/add.png"),tr("Add"),this,SLOT(slotActionAddDesktop()) );
137      dmenu->addAction( QIcon(":icons/remove.png"),tr("Remove"),this,SLOT(slotActionRemoveDesktop()) );
138    QMenu *mmenu = actionMenu->addMenu( QIcon(":icons/xdg_menu.png"), tr("Menu Icons"));
139      mmenu->addAction( QIcon(":icons/add.png"),tr("Add"),this,SLOT(slotActionAddMenu()) );
140      mmenu->addAction( QIcon(":icons/remove.png"),tr("Remove"),this,SLOT(slotActionRemoveMenu()) ); 
141      mmenu->addAction( QIcon(":icons/add-root.png"),tr("Add (All Users)"),this,SLOT(slotActionAddMenuAll()) );
142    QMenu *pmenu = actionMenu->addMenu( QIcon(":icons/xdg_paths.png"), tr("Path Links"));
143      pmenu->addAction( QIcon(":icons/add.png"),tr("Add"),this,SLOT(slotActionAddPath()) );
144      pmenu->addAction( QIcon(":icons/remove.png"),tr("Remove"),this,SLOT(slotActionRemovePath()) ); 
145      pmenu->addAction( QIcon(":icons/add-root.png"),tr("Add (All Users)"),this,SLOT(slotActionAddPathAll()) );
146    QMenu *fmenu = actionMenu->addMenu( QIcon(":icons/xdg_mime.png"), tr("File Associations"));
147      fmenu->addAction( QIcon(":icons/add.png"),tr("Add"),this,SLOT(slotActionAddMime()) );
148      fmenu->addAction( QIcon(":icons/remove.png"),tr("Remove"),this,SLOT(slotActionRemoveMime()) ); 
149      fmenu->addAction( QIcon(":icons/add-root.png"),tr("Add (All Users)"),this,SLOT(slotActionAddMimeAll()) );
150    actionMenu->addSeparator();
151    actionMenu->addAction( QIcon(":icons/remove.png"), tr("Uninstall"), this, SLOT(slotActionRemove()) );
152    actionMenu->addSeparator();
153    actionMenu->addAction( QIcon(":icons/dialog-cancel.png"), tr("Cancel Actions"), this, SLOT(slotActionCancel()) );
154    //Now setup the action button
155    ui->tool_install_performaction->setMenu(actionMenu);
156    ui->tool_install_performaction->setPopupMode(QToolButton::InstantPopup);
157    //Now setup any defaults for the installed tab
158    ui->tool_install_gotobrowserpage->setEnabled(FALSE); //disable it until the browser is ready
159    slotRefreshInstallTab();
160}
161
162void MainUI::formatInstalledItemDisplay(QTreeWidgetItem *item){
163  //simplification function for filling the tree widget item with the appropriate information about the PBI
164  QString ID = item->whatsThis(0);
165  if(item->text(0).isEmpty()){  //new entry - get everything
166    QStringList vals; vals <<"name"<<"version"<<"status"; //same as column order
167    if(!vals.isEmpty()){
168      vals = PBI->PBIInfo(ID, vals);
169      for(int i=0; i<vals.length(); i++){ item->setText(i,vals[i]); }
170      QString icon = PBI->PBIInfo(ID, QStringList("icon")).join("");
171        //Load a default icon if none found
172      if(icon.isEmpty()){ icon = defaultIcon; }
173      item->setIcon(0,QIcon(icon) );
174      item->setCheckState(0,Qt::Unchecked);
175    }
176  }else{ // Just update the necesary info
177    QStringList vals; vals << "version" << "status";
178    vals = PBI->PBIInfo(ID,vals);
179    if(!vals.isEmpty()){ item->setText(1,vals[0]); item->setText(2,vals[1]); }
180  }
181}
182
183QStringList MainUI::getCheckedItems(){
184  //Return the pbiID's of all the checked items
185  QStringList output;
186  for(int i=0; i<ui->tree_install_apps->topLevelItemCount(); i++){
187    if(ui->tree_install_apps->topLevelItem(i)->checkState(0) == Qt::Checked){
188      output << ui->tree_install_apps->topLevelItem(i)->whatsThis(0);
189      //ui->tree_install_apps->topLevelItem(i)->setCheckState(0,Qt::Unchecked);
190    }
191  }
192  return output;       
193}
194
195// === SLOTS ===
196void MainUI::slotRefreshInstallTab(){
197  //Update the list of installed PBI's w/o clearing the list (loses selections)
198  QStringList installList = PBI->installedList();
199  //Update the currently shown list
200  for(int i=0; i<ui->tree_install_apps->topLevelItemCount(); i++){
201    QString itemID = ui->tree_install_apps->topLevelItem(i)->whatsThis(0);
202    int index = installList.indexOf(itemID);
203    if( index != -1 ){ //item is still installed
204      //Update the widget item
205      formatInstalledItemDisplay( ui->tree_install_apps->topLevelItem(i) );
206      //Now remove the item from the installed list - already done with it
207      installList.removeAt(index);
208    }else{
209      //Remove the item from the UI list - no longer installed
210      ui->tree_install_apps->takeTopLevelItem(i);
211      i--; //Make sure we don't miss an item by changing the count
212    }
213  }
214  //Now Create new widget items as necessary (anything left on the installed list)
215  for(int i=0; i<installList.length();i++){
216    QTreeWidgetItem *item = new QTreeWidgetItem; //create the item
217      item->setWhatsThis(0,installList[i]);
218    //Now format the display
219    formatInstalledItemDisplay(item);
220    //Now add this item to the list
221    ui->tree_install_apps->addTopLevelItem(item);
222  }
223  //Now re-sort the items
224  if(ui->tree_install_apps->topLevelItemCount() > 0 ){
225    ui->tree_install_apps->sortItems(0,Qt::AscendingOrder);
226    //Make sure that there is an item selected
227    if( ui->tree_install_apps->selectedItems().isEmpty() ){
228      ui->tree_install_apps->setCurrentItem( ui->tree_install_apps->topLevelItem(0) );
229    }
230  }
231  //Now re-size the columns to the minimum required width
232  for(int i=0; i<3; i++){
233    ui->tree_install_apps->resizeColumnToContents(i);
234  }
235  on_tree_install_apps_itemSelectionChanged(); //Update the info boxes
236  slotDisplayStats();
237}
238void MainUI::slotPBIStatusUpdate(QString pbiID){
239  for(int i=0; i<ui->tree_install_apps->topLevelItemCount(); i++){
240    QString itemID = ui->tree_install_apps->topLevelItem(i)->whatsThis(0);
241    if(itemID == pbiID){
242      QString stat = PBI->PBIInfo(pbiID,QStringList()<<"status").join("");
243      ui->tree_install_apps->topLevelItem(i)->setText(2,stat);
244    }
245  }
246}
247
248void MainUI::on_group_install_showinfo_toggled(bool show){
249  if(ui->tree_install_apps->topLevelItemCount() > 0){
250    ui->group_install_info->setVisible(show);
251  }else{
252    ui->group_install_info->setVisible(FALSE);   
253  }
254}
255
256void MainUI::on_tool_install_gotobrowserpage_clicked(){
257  //When you want to open up the browser page for an application
258  QString appID = ui->tree_install_apps->currentItem()->text(0).toLower();
259  slotGoToApp(appID);
260}
261
262void MainUI::on_tool_install_toggleall_clicked(){
263  //Determine if the current item is checked or unchecked
264  bool checkall = (ui->tree_install_apps->currentItem()->checkState(0) == Qt::Unchecked);
265  for(int i=0; i<ui->tree_install_apps->topLevelItemCount(); i++){
266    if(checkall){ ui->tree_install_apps->topLevelItem(i)->setCheckState(0,Qt::Checked); }
267    else{ui->tree_install_apps->topLevelItem(i)->setCheckState(0,Qt::Unchecked); }
268  }
269}
270
271void MainUI::on_tree_install_apps_itemSelectionChanged(){
272  //When an installed PBI is clicked on
273  QString appID;
274  if(ui->tree_install_apps->topLevelItemCount() > 0){
275    appID = ui->tree_install_apps->currentItem()->whatsThis(0);
276  }
277  if(appID.isEmpty()){
278    ui->group_install_info->setVisible(FALSE);
279    return;
280  }else{
281    ui->group_install_info->setVisible( ui->group_install_showinfo->isChecked() );       
282  }
283  //Get the PBI info for that item
284  QStringList vals; 
285  vals << "name" << "icon" << "author" << "website" << "version" << "license";
286  QStringList bools;
287  bools << "autoupdate" << "hasdesktopicons" << "hasmenuicons";
288  vals = PBI->PBIInfo(appID,vals);
289  bools = PBI->PBIInfo(appID,bools);
290  //Make sure the info lists are not empty
291  if(vals.isEmpty() || bools.isEmpty()){
292    ui->group_install_info->setVisible(FALSE);
293    return; 
294  }
295  //Load a default icon if none found
296  if(vals[1].isEmpty()){ vals[1] = defaultIcon; }
297  //Now set the info on the UI
298  bool desktopSC = (bools[1] == "true"); // XDG desktop entries available
299  bool menuSC= (bools[2] == "true");     // XDG menu entries available
300  bool autoupdate = (bools[0] == "true"); 
301  //Create the shortcuts string
302  QString shortcuts;
303    if(desktopSC && menuSC){ shortcuts = tr("Desktop/Menu"); }
304    else if(desktopSC){ shortcuts = tr("Desktop"); }
305    else if(menuSC){ shortcuts = tr("Menu"); }
306    else{ shortcuts = tr("None"); }
307  //Now display that info on the UI
308  ui->label_install_app->setText(vals[0]);
309  ui->label_install_icon->setPixmap( QPixmap(vals[1]) );
310  if(vals[3].isEmpty()){ 
311    ui->label_install_author->setText(vals[2]); 
312    ui->label_install_author->setToolTip("");
313  }else{ 
314    ui->label_install_author->setText("<a href="+vals[3]+">"+vals[2]+"</a>"); 
315    ui->label_install_author->setToolTip(vals[3]); //show website URL as tooltip
316  }
317  ui->label_install_license->setText(vals[5]);
318  ui->label_install_version->setText(vals[4]);
319  ui->label_install_shortcuts->setText(shortcuts);
320  ui->check_install_autoupdate->setChecked(autoupdate);
321}
322
323void MainUI::on_check_install_autoupdate_clicked(){
324  //Get the current item
325  QString appID;
326  if(ui->tree_install_apps->topLevelItemCount() > 0){
327    appID = ui->tree_install_apps->currentItem()->whatsThis(0);
328  }
329  if(appID.isEmpty()){return;}
330  //Now determine the current state of the checkbox
331  bool enabled = ui->check_install_autoupdate->isChecked();
332  //Now have the backend make the change
333  PBI->enableAutoUpdate(appID, enabled);
334}
335
336// === SELECTED PBI ACTIONS ===
337void MainUI::slotActionAddDesktop(){
338  QStringList items = getCheckedItems();
339  PBI->addDesktopIcons(items,FALSE); //only for current user
340}
341
342void MainUI::slotActionRemoveDesktop(){
343  QStringList items = getCheckedItems();
344  PBI->rmDesktopIcons(items,FALSE);  //Only for current user
345}
346
347void MainUI::slotActionAddPath(){
348  QStringList items = getCheckedItems();
349  PBI->addPaths(items,FALSE);  //Only for current user 
350}
351
352void MainUI::slotActionRemovePath(){
353  QStringList items = getCheckedItems();
354  PBI->rmPaths(items,FALSE);  //Only for current user
355}
356
357void MainUI::slotActionAddPathAll(){
358  QStringList items = getCheckedItems();
359  PBI->addPaths(items,TRUE);  //For all users (root permissions required)
360}
361
362void MainUI::slotActionAddMenu(){
363  QStringList items = getCheckedItems();
364  PBI->addMenuIcons(items,FALSE);  //Only for current user
365}
366
367void MainUI::slotActionRemoveMenu(){
368  QStringList items = getCheckedItems();
369  PBI->rmMenuIcons(items,FALSE);  //Only for current user       
370}
371
372void MainUI::slotActionAddMenuAll(){
373  QStringList items = getCheckedItems();
374  PBI->addMenuIcons(items,TRUE);  //For all users (root permissions required)   
375}
376
377void MainUI::slotActionAddMime(){
378  QStringList items = getCheckedItems();
379  PBI->addMimeTypes(items,FALSE);  //Only for current user     
380}
381
382void MainUI::slotActionRemoveMime(){
383  QStringList items = getCheckedItems();
384  PBI->rmMimeTypes(items,FALSE);  //Only for current user       
385}
386
387void MainUI::slotActionAddMimeAll(){
388    QStringList items = getCheckedItems();
389  PBI->addMimeTypes(items,TRUE);  //For all users (root permissions required)   
390}
391
392void MainUI::slotActionUpdate(){
393  QStringList checkedID = getCheckedItems();
394  if(!checkedID.isEmpty()){
395    PBI->upgradePBI(checkedID); 
396  }
397}
398
399void MainUI::slotActionRemove(){
400  QStringList checkedID = getCheckedItems();
401  if(!checkedID.isEmpty()){
402    //Verify that the user really wants to remove these apps
403    if( QMessageBox::Yes == QMessageBox::question(this,tr("Verify PBI Removal"), tr("Are you sure you wish to remove these applications?")+"\n\n"+checkedID.join(", "),QMessageBox::Yes | QMessageBox::Cancel,QMessageBox::Cancel) ){
404      PBI->removePBI(checkedID);
405    }
406  }
407}
408
409void MainUI::slotActionCancel(){
410  QStringList checkedID = getCheckedItems();
411  if(!checkedID.isEmpty()){
412    PBI->cancelActions(checkedID); 
413  }
414}
415
416
417// ==========================
418// ====== BROWSER TAB =======
419// ==========================
420void MainUI::initializeBrowserTab(){
421  ui->tab_browse->setEnabled(FALSE);
422  //Always make sure that the browser starts off on the "home" page
423  ui->stacked_browser->setCurrentWidget(ui->page_home);
424  //With invisible shortcut buttons
425  ui->tool_browse_cat->setVisible(FALSE);
426  ui->tool_browse_app->setVisible(FALSE);
427  //Clear any items left over from the designer form
428  clearScrollArea(ui->scroll_br_home_newapps);
429  clearScrollArea(ui->scroll_br_home_cats);
430  //Search functionality
431  searchTimer = new QTimer();
432    searchTimer->setSingleShot(TRUE);
433    searchTimer->setInterval(300); // 0.3 sec wait before a search
434    connect(searchTimer,SIGNAL(timeout()),this,SLOT(slotGoToSearch()) );
435  connect(ui->tool_browse_search,SIGNAL(clicked()),this,SLOT(slotGoToSearch()) );
436  connect(ui->line_browse_searchbar,SIGNAL(returnPressed()),this,SLOT(slotGoToSearch()) );
437}
438
439// === SLOTS ===
440void MainUI::slotDisableBrowser(bool shownotification){
441  if(shownotification){ qDebug() << "No Repo Available: De-activating the Browser"; }
442  ui->tabWidget->setCurrentWidget(ui->tab_installed);
443  ui->tool_install_gotobrowserpage->setEnabled(FALSE);
444  ui->tab_browse->setEnabled(FALSE);
445  slotDisplayStats();
446}
447
448void MainUI::slotEnableBrowser(){
449  qDebug() << "Repo Ready: - generating browser home page";
450  //Now create the browser home page
451  slotUpdateBrowserHome();
452  //And allow the user to go there
453  ui->tool_install_gotobrowserpage->setEnabled(TRUE);
454  ui->tab_browse->setEnabled(TRUE);
455  slotDisplayStats();
456}
457
458void MainUI::slotUpdateBrowserHome(){
459  //Load the Categories
460  QStringList cats = PBI->browserCategories();
461  clearScrollArea(ui->scroll_br_home_cats);
462  QVBoxLayout *catlayout = new QVBoxLayout;
463  QStringList info; info << "name" << "description" << "icon";
464  cats.sort(); //sort them alphabetically
465  for(int i=0; i<cats.length(); i++){
466    QStringList data = PBI->CatInfo(cats[i],info);
467    if(!data.isEmpty()){
468      LargeItemWidget *item = new LargeItemWidget(cats[i],data[0],data[1],data[2]);
469      connect(item,SIGNAL(appClicked(QString)),this,SLOT(slotGoToCategory(QString)) );
470      catlayout->addWidget(item);
471    }
472  }
473  catlayout->addStretch(); //add a spacer to the end
474  ui->scroll_br_home_cats->widget()->setLayout(catlayout);
475  //Load the newest applications
476  clearScrollArea(ui->scroll_br_home_newapps);
477  QHBoxLayout *newapplayout = new QHBoxLayout;
478  QStringList newapps = PBI->getRecentApps();
479  for(int i=0; i<newapps.length(); i++){
480    QStringList appdata = PBI->AppInfo(newapps[i],QStringList() << "name" << "icon" << "latestversion");
481    if(!appdata.isEmpty()){
482      SmallItemWidget *item = new SmallItemWidget(newapps[i],appdata[0],appdata[1],appdata[2]);
483      connect(item,SIGNAL(appClicked(QString)),this,SLOT(slotGoToApp(QString)) );
484      newapplayout->addWidget(item);
485    }
486  }
487  newapplayout->addStretch(); //add a spacer to the end
488  newapplayout->setContentsMargins(0,0,0,0);
489  newapplayout->setSpacing(0);
490  ui->scroll_br_home_newapps->widget()->setLayout(newapplayout);
491  //Make sure that the newapps scrollarea is the proper fit vertically (no vertical scrolling)
492  ui->scroll_br_home_newapps->setMinimumHeight(ui->scroll_br_home_newapps->widget()->minimumSizeHint().height()+ui->scroll_br_home_newapps->horizontalScrollBar()->height());
493 
494  //Make sure the new apps area is invisible if no items available
495  if(newapps.isEmpty()){ ui->group_br_home_newapps->setVisible(FALSE); }
496  else{ ui->group_br_home_newapps->setVisible(TRUE); }
497  //make sure the home page is visible in the browser (slotGoToHome without changing tabs)
498  ui->stacked_browser->setCurrentWidget(ui->page_home); 
499  //Make sure the shortcut buttons are disabled
500  ui->tool_browse_cat->setVisible(FALSE);
501  ui->tool_browse_app->setVisible(FALSE); 
502 
503}
504
505void MainUI::slotGoToHome(){
506  ui->tabWidget->setCurrentWidget(ui->tab_browse);
507  ui->stacked_browser->setCurrentWidget(ui->page_home); 
508  //Make sure the shortcut buttons are disabled
509  ui->tool_browse_cat->setVisible(FALSE);
510  ui->tool_browse_app->setVisible(FALSE);
511}
512
513void MainUI::slotGoToCategory(QString cat){
514  qDebug() << "Show Category:" << cat;
515  //Get the apps in this category
516  QStringList apps = PBI->browserApps(cat);
517  if(apps.isEmpty()){
518    qDebug() << "Invalid category:" << cat;
519    return;
520  }
521  clearScrollArea(ui->scroll_br_cat_apps);
522  apps.sort();
523  QVBoxLayout *applayout = new QVBoxLayout;
524  QStringList info; info << "name" << "description" << "icon";
525  for(int i=0; i<apps.length(); i++){
526    QStringList data = PBI->AppInfo(apps[i],info);
527    if(!data.isEmpty()){
528      //Trim the description if necessary
529      if(data[1].size()>100){ data[1] = data[1].left(100).append("..."); }
530      LargeItemWidget *item = new LargeItemWidget(apps[i],data[0],data[1],data[2]);
531      connect(item,SIGNAL(appClicked(QString)),this,SLOT(slotGoToApp(QString)) );
532      applayout->addWidget(item); 
533    }
534  }
535  applayout->addStretch();
536  ui->scroll_br_cat_apps->widget()->setLayout(applayout);
537  //Now enable/disable the shortcut buttons
538  ui->tool_browse_app->setVisible(FALSE);
539  ui->tool_browse_cat->setVisible(TRUE);
540    QStringList catinfo = PBI->CatInfo(cat,QStringList() << "name" << "icon");
541    ui->tool_browse_cat->setText(catinfo[0]);
542    if(catinfo[1].isEmpty()){ catinfo[1] = defaultIcon; }
543    ui->tool_browse_cat->setIcon(QIcon(catinfo[1]));
544  ui->tabWidget->setCurrentWidget(ui->tab_browse);
545  ui->stacked_browser->setCurrentWidget(ui->page_cat);
546  //Now save that this category is currently displayed
547  cCat = cat;
548}
549
550void MainUI::slotGoToApp(QString appID){
551  qDebug() << "Show App:" << appID;
552  //Get the general application info
553  QStringList data; 
554  data << "name" << "icon" << "author" << "website" << "license" << "type" << "description" \
555       << "category" << "requiresroot" << "latestversion" << "latestarch" <<"latestsize" \
556       << "backupversion" << "backuparch" << "backupsize";
557  data = PBI->AppInfo(appID,data);
558  if(data.isEmpty()){
559    qDebug() << "Invalid App:" << appID;
560    return;
561  }
562  //Start the search for similar apps
563  PBI->searchSimilar = appID;
564  ui->group_bapp_similar->setVisible(FALSE);
565  QTimer::singleShot(0,PBI,SLOT(startSimilarSearch()));
566  //Now Check icon
567  if(data[1].isEmpty()){ data[1] = defaultIcon; }
568  //Now fill the UI with the data
569  ui->label_bapp_name->setText(data[0]);
570  ui->label_bapp_icon->setPixmap(QPixmap(data[1]));
571  if(data[3].isEmpty()){ ui->label_bapp_authorweb->setText(data[2]); }
572  else{ ui->label_bapp_authorweb->setText("<a href="+data[3]+">"+data[2]+"</a>"); }
573  ui->label_bapp_authorweb->setToolTip(data[3]);
574  ui->label_bapp_license->setText(data[4]);
575  ui->label_bapp_type->setText(data[5]);
576  ui->text_bapp_description->setText(data[6]);
577  //Now determine the appropriate version info
578  QString pbiID = PBI->isInstalled(appID); //get pbiID
579  QString cVer;
580  if(!pbiID.isEmpty()){ cVer = PBI->PBIInfo(pbiID,QStringList("version")).join(""); }
581  bool useLatest=FALSE;
582  bool nobackup = data[12].isEmpty();
583  if(cVer.isEmpty()){ useLatest=TRUE; } //not currently installed
584  else if(cVer != data[9]){ useLatest=TRUE;} //not the latest version
585  //Now put the proper version info on the UI
586  if(useLatest || nobackup){
587    ui->label_bapp_version->setText(data[9]);
588    ui->label_bapp_arch->setText(data[10]);
589    if(data[11].isEmpty()){ ui->label_bapp_size->setText(tr("Unknown")); }
590    else{ ui->label_bapp_size->setText( Extras::sizeKToDisplay(data[11]) ); }
591  }else{
592    ui->label_bapp_version->setText(data[12]);
593    ui->label_bapp_arch->setText(data[13]);
594    if(data[14].isEmpty()){ ui->label_bapp_size->setText(tr("Unknown")); }
595    else{ ui->label_bapp_size->setText( Extras::sizeKToDisplay(data[14]) ); }
596  }
597  //Now update the download button appropriately
598  QString ico;
599  QString working = PBI->currentAppStatus(appID);
600  if(!working.isEmpty()){ //app currently pending or actually doing something
601    ui->tool_bapp_download->setText(working);
602    ui->tool_bapp_download->setIcon(QIcon(":icons/working.png"));
603    ui->tool_bapp_download->setEnabled(FALSE);
604  }else if(useLatest && cVer.isEmpty()){ //new installation
605    ui->tool_bapp_download->setText(tr("Install Now!"));
606    ico = ":icons/app_download.png";
607    ui->tool_bapp_download->setEnabled(TRUE);
608  }else if(useLatest){ //Upgrade available
609    ui->tool_bapp_download->setText(tr("Upgrade"));
610    ico = ":icons/app_upgrade.png";
611    ui->tool_bapp_download->setEnabled(TRUE);
612  }else if(!nobackup){  //Downgrade available
613    ui->tool_bapp_download->setText(tr("Downgrade"));
614    ico = ":icons/app_downgrade.png";
615    ui->tool_bapp_download->setEnabled(TRUE);
616  }else{ //already installed (no downgrade available)
617    ui->tool_bapp_download->setText(tr("Installed"));
618    ui->tool_bapp_download->setIcon(QIcon(":icons/dialog-ok.png"));
619    ui->tool_bapp_download->setEnabled(FALSE);
620  }
621  //Now set the icon appropriately if it requires root permissions
622  if(!ico.isEmpty()){
623    if(data[8]=="true"){ //requires root permissions to install
624      ico.replace(".png","-root.png");
625    }
626    ui->tool_bapp_download->setIcon(QIcon(ico));
627  }
628  ui->tool_bapp_download->setWhatsThis(appID); //set for slot
629  //Now enable/disable the shortcut buttons
630  ui->tool_browse_app->setVisible(TRUE);
631    ui->tool_browse_app->setText(data[0]);
632    ui->tool_browse_app->setIcon(QIcon(data[1]));
633  QStringList catinfo = PBI->CatInfo(Extras::nameToID(data[7]),QStringList() << "name" << "icon");
634  if(!catinfo.isEmpty()){
635    ui->tool_browse_cat->setVisible(TRUE);
636    ui->tool_browse_cat->setText(catinfo[0]);
637    if(catinfo[1].isEmpty()){ catinfo[1] = defaultIcon; }
638    ui->tool_browse_cat->setIcon(QIcon(catinfo[1]));
639  }
640  ui->tabWidget->setCurrentWidget(ui->tab_browse);
641  ui->stacked_browser->setCurrentWidget(ui->page_app);
642       
643}
644
645void MainUI::slotGoToSearch(){
646  searchTimer->stop(); //just in case "return" was pressed to start the search
647  QString search = ui->line_browse_searchbar->text();
648  if(search.isEmpty()){ return; }
649  PBI->searchTerm = search;
650  QTimer::singleShot(1,PBI,SLOT(startAppSearch()));
651  ui->label_bsearch_info->setText( tr("Searching the application database. Please Wait....") );
652    ui->label_bsearch_info->setVisible(TRUE);
653    ui->group_bsearch_best->setVisible(FALSE);
654    ui->group_bsearch_other->setVisible(FALSE);
655 
656}
657       
658void MainUI::slotShowSimilarApps(QStringList apps){
659  qDebug() << " - Similar applications:" << apps;
660  if(apps.isEmpty()){ ui->group_bapp_similar->setVisible(FALSE); }
661  else{
662    clearScrollArea(ui->scroll_bapp_similar);
663    QHBoxLayout *layout = new QHBoxLayout;
664    for(int i=0; i<apps.length(); i++){
665      QStringList appdata = PBI->AppInfo(apps[i],QStringList() << "name" << "icon");
666      if(!appdata.isEmpty()){
667        SmallItemWidget *item = new SmallItemWidget(apps[i],appdata[0],appdata[1],"");
668        connect(item,SIGNAL(appClicked(QString)),this,SLOT(slotGoToApp(QString)) );
669        layout->addWidget(item);
670      }
671    }
672    layout->addStretch(); //add a spacer to the end
673    layout->setContentsMargins(1,1,1,1);
674    ui->scroll_bapp_similar->widget()->setLayout(layout);
675    //Make sure that the similar scrollarea is the proper fit vertically (no vertical scrolling)
676    ui->scroll_bapp_similar->setMinimumHeight(ui->scroll_bapp_similar->widget()->minimumSizeHint().height()+ui->scroll_bapp_similar->horizontalScrollBar()->height());
677    //Now make the group visible as appropriate
678    ui->group_bapp_similar->setVisible(TRUE);
679    if(ui->group_bapp_similar->isChecked()){ ui->scroll_bapp_similar->setVisible(TRUE); }
680    else{ ui->scroll_bapp_similar->setVisible(FALSE); }
681  }
682}
683
684void MainUI::slotShowSearchResults(QStringList best, QStringList rest){
685  //Now display the search results
686  if(best.isEmpty()){
687    ui->label_bsearch_info->setText( QString(tr("No Search Results Found for the term: %1")).arg(ui->line_browse_searchbar->text()) );
688    ui->label_bsearch_info->setVisible(TRUE);
689    ui->group_bsearch_best->setVisible(FALSE);
690    ui->group_bsearch_other->setVisible(FALSE);
691  }else{
692    ui->label_bsearch_info->setVisible(FALSE);
693    //Now fill the "best" section
694    clearScrollArea(ui->scroll_bsearch_best);
695    QVBoxLayout *layout = new QVBoxLayout;
696    QStringList info; info << "name" << "description" << "icon";
697    for(int i=0; i<best.length(); i++){
698      QStringList data = PBI->AppInfo(best[i],info);
699      if(!data.isEmpty()){
700        //Trim the description if necessary
701        if(data[1].size()>100){ data[1] = data[1].left(100).append("..."); }
702        LargeItemWidget *item = new LargeItemWidget(best[i],data[0],data[1],data[2]);
703        connect(item,SIGNAL(appClicked(QString)),this,SLOT(slotGoToApp(QString)) );
704        layout->addWidget(item); 
705      }
706    }
707    layout->addStretch();
708    ui->scroll_bsearch_best->widget()->setLayout(layout);
709    ui->group_bsearch_best->setVisible(TRUE);
710   
711    //Now fill the other results
712    if(rest.isEmpty()){ ui->group_bsearch_other->setVisible(FALSE); }
713    else{
714      ui->group_bsearch_other->setVisible(TRUE);
715      clearScrollArea(ui->scroll_bsearch_other);
716      QVBoxLayout *layout2 = new QVBoxLayout;
717      for(int i=0; i<rest.length(); i++){
718        QStringList data = PBI->AppInfo(rest[i],info);
719        if(!data.isEmpty()){
720          //Trim the description if necessary
721          if(data[1].size()>100){ data[1] = data[1].left(100).append("..."); }
722          LargeItemWidget *item = new LargeItemWidget(rest[i],data[0],data[1],data[2]);
723          connect(item,SIGNAL(appClicked(QString)),this,SLOT(slotGoToApp(QString)) );
724          layout2->addWidget(item); 
725        }
726      }
727      layout2->addStretch();
728      ui->scroll_bsearch_other->widget()->setLayout(layout2);
729    }
730  }
731       
732  //need to make sure the search bar still has keyboard focus (just in case)
733  ui->tabWidget->setCurrentWidget(ui->tab_browse);
734  ui->stacked_browser->setCurrentWidget(ui->page_search);
735 
736}
737
738void MainUI::on_tabWidget_currentChanged(){
739  if(ui->tabWidget->currentWidget() == ui->tab_browse){
740    //Refresh the app page if that is the one currently showing
741    if(ui->stacked_browser->currentWidget() == ui->page_app){ on_tool_browse_app_clicked(); }     
742  }
743}
744
745void MainUI::on_tool_browse_home_clicked(){
746  slotGoToHome();
747}
748
749void MainUI::on_tool_browse_cat_clicked(){
750  QString cat = Extras::nameToID(ui->tool_browse_cat->text());
751  if(cCat == cat){ //already loaded - just show it (prevents resetting scroll positions)
752    ui->stacked_browser->setCurrentWidget(ui->page_cat);
753  }else{ //load and show the category
754    slotGoToCategory(cat);
755  }
756}
757
758void MainUI::on_tool_browse_app_clicked(){
759  QString appID = Extras::nameToID(ui->tool_browse_app->text());
760  slotGoToApp(appID);
761}
762
763void MainUI::on_line_browse_searchbar_textChanged(){
764  //Connect this to a singleshot timer, so the search functionality is only
765  //  run once after a short wait rather than every time a new character is typed
766 
767  //Live search only after 3 characters have been typed
768  if(ui->line_browse_searchbar->text().length() > 2){
769    searchTimer->start();
770  }else{
771    searchTimer->stop();         
772  }
773}
774
775void MainUI::on_tool_bapp_download_clicked(){
776  QString appID = ui->tool_bapp_download->whatsThis();
777  PBI->installApp(QStringList() << appID);
778  ui->tool_bapp_download->setEnabled(FALSE); //make sure it cannot be clicked more than once before page refresh
779  //Now show the Installed tab
780  ui->tabWidget->setCurrentWidget(ui->tab_installed);
781}
782
783void MainUI::on_group_br_home_newapps_toggled(bool show){
784  ui->scroll_br_home_newapps->setVisible(show);
785}
786
787void MainUI::on_group_bapp_similar_toggled(bool show){
788  ui->scroll_bapp_similar->setVisible(show);
789}
790
791// ================================
792// ==========  OTHER ==============
793// ================================
794void MainUI::clearScrollArea(QScrollArea* area){
795  QWidget *wgt = area->takeWidget();
796  delete wgt; //delete the widget and all children
797  area->setWidget( new QWidget() ); //create a new widget in the scroll area
798  area->widget()->setContentsMargins(0,0,0,0);
799}
800
801void MainUI::slotDisplayError(QString title,QString err){
802  QMessageBox::warning(this,title,err);
803}
804
805void MainUI::slotDisplayStats(){
806  int avail = PBI->numAvailable;
807  int installed = PBI->numInstalled;
808  QString text;
809  if(avail == -1){
810    text = QString(tr("Installed: %1")).arg(QString::number(installed)); 
811  }else{
812    text = QString(tr("Installed: %1")+"\t"+tr("Available: %2")).arg(QString::number(installed), QString::number(avail)); 
813  }
814  //Get the number of installed/available applications and display it
815  statusLabel->setText(text);   
816}
Note: See TracBrowser for help on using the repository browser.