1 #include "applicationdialog.h"
2 #include "fileutils.h"
3 
4 #include <QVBoxLayout>
5 #include <QDialogButtonBox>
6 #include <QFormLayout>
7 #include <QCompleter>
8 #include <QApplication>
9 
10 /**
11  * @brief Constructor
12  * @param parent
13  */
14 
ApplicationDialog(bool enable_launcher,QWidget * parent)15 ApplicationDialog::ApplicationDialog(bool enable_launcher,
16                                      QWidget *parent) :
17     QDialog(parent)
18   , appList(Q_NULLPTR)
19   , edtCommand(Q_NULLPTR)
20 {
21     // Title and size
22     setWindowTitle(tr("Select application"));
23     setMinimumSize(320, 320);
24 
25     // Creates app list view
26     appList = new QTreeWidget(this);
27     appList->setIconSize(QSize(24, 24));
28     appList->setAlternatingRowColors(true);
29     appList->headerItem()->setText(0, tr("Application"));
30 
31     // Creates buttons
32     QDialogButtonBox *buttons = new QDialogButtonBox(this);
33     buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
34     connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
35     connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
36 
37     // Command bar
38     edtCommand = new QLineEdit(this);
39     edtCommand->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
40     QFormLayout* layoutCommand = new QFormLayout();
41     if (enable_launcher) {
42         layoutCommand->addRow(tr("Launcher: "), edtCommand);
43     }
44 
45     // Layout
46     QVBoxLayout* layout = new QVBoxLayout(this);
47     layout->addWidget(appList);
48     layout->addLayout(layoutCommand);
49     layout->addWidget(buttons);
50 
51     // Synonyms for category names
52     catNames.clear();
53     catNames.insert("Development", QStringList() << "Programming");
54     catNames.insert("Games", QStringList() << "Game");
55     catNames.insert("Graphics", QStringList());
56     catNames.insert("Internet", QStringList() << "Network" << "WebBrowser");
57     catNames.insert("Multimedia", QStringList() << "AudioVideo" << "Video");
58     catNames.insert("Office", QStringList());
59     catNames.insert("Other", QStringList());
60     catNames.insert("Settings", QStringList() << "System");
61     catNames.insert("Utilities", QStringList() << "Utility");
62 
63     // Load default icon
64     defaultIcon = QIcon::fromTheme("application-x-executable");
65 
66     // Create completer and its model for editation of command
67     QStringListModel* model = new QStringListModel(this);
68     model->setStringList(applications.keys());
69     QCompleter* completer = new QCompleter(this);
70     completer->setModel(model);
71     edtCommand->setCompleter(completer);
72     if (!enable_launcher) { edtCommand->hide(); }
73 
74     // Signals
75     connect(appList,
76            SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
77            SLOT(updateCommand(QTreeWidgetItem*,QTreeWidgetItem*)));
78 
79     // populate
80     QTimer::singleShot(100, this, SLOT(populate()));
81 }
82 
83 /**
84  * @brief Returns currently selected launcher
85  * @return currently selected launcher
86  */
87 
getCurrentLauncher() const88 QString ApplicationDialog::getCurrentLauncher() const
89 {
90     return edtCommand->text();
91 }
92 
populate()93 void ApplicationDialog::populate()
94 {
95     // Create default application categories
96     categories.clear();
97     createCategories();
98 
99     // Load applications and create category tree list
100     QList<DesktopFile> apps = FileUtils::getApplications();
101     foreach (DesktopFile app, apps) {
102         // Check for name
103         if (app.getName().compare("") == 0 || app.noDisplay()) { continue; }
104 
105         // Find category
106         QTreeWidgetItem* category = findCategory(app);
107 
108         // Create item from current mime
109         QTreeWidgetItem *item = new QTreeWidgetItem(category);
110         item->setIcon(0, FileUtils::searchAppIcon(app, defaultIcon));
111         item->setText(0, app.getName());
112         item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
113 
114         // Register application
115         QApplication::processEvents();
116         applications.insert(app.getPureFileName(), item);
117     }
118 }
119 
120 /**
121  * @brief Creates default application categories
122  * @param names names of cathegories with synonyms
123  */
124 
createCategories()125 void ApplicationDialog::createCategories()
126 {
127     // Create categories
128     foreach (QString name, catNames.keys()) {
129         // Find icon
130         QIcon icon = QIcon::fromTheme("applications-" + name.toLower());
131 
132         // If icon not found, check synonyms
133         if (icon.isNull()) {
134             foreach (QString synonym, catNames.value(name)) {
135                 icon = QIcon::fromTheme("applications-" + synonym.toLower());
136                 break;
137             }
138         }
139 
140         // If icon still not found, retrieve default icon
141         if (icon.isNull()) { icon = defaultIcon; }
142 
143         // Create category
144         QTreeWidgetItem* category = new QTreeWidgetItem(appList);
145         category->setText(0, name);
146         category->setIcon(0, icon);
147         category->setFlags(Qt::ItemIsEnabled);
148         categories.insert(name, category);
149     }
150 }
151 
152 /**
153  * @brief Searches the most suitable category for application
154  * @param app
155  * @return cathegory
156  */
157 
findCategory(const DesktopFile & app)158 QTreeWidgetItem* ApplicationDialog::findCategory(const DesktopFile &app)
159 {
160     // Default category is 'Other'
161     QTreeWidgetItem* category = categories.value("Other");
162 
163     // Try to find more suitable category
164     foreach (QString name, catNames.keys()) {
165         // Try cathegory name
166         if (app.getCategories().contains(name)) {
167             category = categories.value(name);
168             break;
169         }
170         // Try synonyms
171         bool found = false;
172         foreach (QString synonym, catNames.value(name)) {
173             if (app.getCategories().contains(synonym)) {
174                 found = true;
175                 break;
176             }
177         }
178         if (found) {
179             category = categories.value(name);
180             break;
181         }
182     }
183     return category;
184 }
185 
186 /**
187  * @brief Updates launcher command
188  * @param current
189  * @param previous
190  */
191 
updateCommand(QTreeWidgetItem * current,QTreeWidgetItem * previous)192 void ApplicationDialog::updateCommand(QTreeWidgetItem *current,
193                                       QTreeWidgetItem *previous)
194 {
195     Q_UNUSED(previous)
196     edtCommand->setText(applications.key(current));
197 }
198