1 /*
2  * LXImage-Qt - a simple and fast image viewer
3  * Copyright (C) 2013  PCMan <pcman.tw@gmail.com>
4  * Copyright (C) 2018  Nathan Osman <nathan@quickmediasolutions.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  */
21 
22 #include <QMutableListIterator>
23 
24 #include "application.h"
25 #include "mrumenu.h"
26 #include "settings.h"
27 
28 using namespace LxImage;
29 
MruMenu(QWidget * parent)30 MruMenu::MruMenu(QWidget *parent)
31     : QMenu(parent)
32 {
33     auto settings = static_cast<Application*>(qApp)->settings();
34     mMaxItems = qMin(qMax(settings.maxRecentFiles(), 0), 100);
35     mFilenames = settings.recentlyOpenedFiles();
36     while (mFilenames.count() > mMaxItems) { // the config file may have been incorrectly edited
37         mFilenames.removeLast();
38     }
39     for (QStringList::const_iterator i = mFilenames.constBegin(); i != mFilenames.constEnd(); ++i) {
40         addAction(createAction(*i));
41     }
42     setEnabled(mMaxItems != 0);
43 
44     // Add a separator and hide it if there are no items in the list
45     mSeparator = addSeparator();
46     mSeparator->setVisible(!mFilenames.empty());
47 
48     // Add the clear action and disable it if there are no items in the list
49     mClearAction = new QAction(tr("&Clear"));
50     mClearAction->setEnabled(!mFilenames.empty());
51     connect(mClearAction, &QAction::triggered, this, &MruMenu::onClearTriggered);
52     addAction(mClearAction);
53 }
54 
addItem(const QString & filename)55 void MruMenu::addItem(const QString &filename)
56 {
57     if (mMaxItems == 0) {
58         return;
59     }
60 
61     if (mFilenames.isEmpty()) {
62         mSeparator->setVisible(true);
63         mClearAction->setEnabled(true);
64     }
65 
66     // If the filename is already in the list, remove it
67     int index = mFilenames.indexOf(filename);
68     if (index != -1) {
69         mFilenames.removeAt(index);
70         destroyAction(index);
71     }
72 
73     // Insert the action at the beginning of the list
74     mFilenames.push_front(filename);
75     insertAction(actions().constFirst(), createAction(filename));
76 
77     // If the list contains more than mMaxItems, remove the last one
78     while (mFilenames.count() > mMaxItems) {
79         destroyAction(mFilenames.count() - 1);
80         mFilenames.removeLast();
81     }
82 
83     updateSettings();
84 }
85 
setMaxItems(int m)86 void MruMenu::setMaxItems(int m) {
87     m = qMin(qMax(m, 0), 100);
88     if (m == mMaxItems) {
89         return;
90     }
91     while (mFilenames.count() > m) {
92         destroyAction(mFilenames.count() - 1);
93         mFilenames.removeLast();
94     }
95     setEnabled(m != 0);
96     mMaxItems = m;
97 
98     updateSettings();
99 }
100 
onItemTriggered()101 void MruMenu::onItemTriggered()
102 {
103     Q_EMIT itemClicked(qobject_cast<QAction*>(sender())->text());
104 }
105 
onClearTriggered()106 void MruMenu::onClearTriggered()
107 {
108     while (!mFilenames.empty()) {
109         mFilenames.removeFirst();
110         destroyAction(0);
111     }
112 
113     // Hide the separator and disable the clear action
114     mSeparator->setVisible(false);
115     mClearAction->setEnabled(false);
116 
117     updateSettings();
118 }
119 
createAction(const QString & filename)120 QAction *MruMenu::createAction(const QString &filename)
121 {
122     QAction *action = new QAction(filename, this);
123     connect(action, &QAction::triggered, this, &MruMenu::onItemTriggered);
124     return action;
125 }
126 
destroyAction(int index)127 void MruMenu::destroyAction(int index)
128 {
129     QAction *action = actions().at(index);
130     removeAction(action);
131     delete action;
132 }
133 
updateSettings()134 void MruMenu::updateSettings()
135 {
136     static_cast<Application*>(qApp)->settings().setRecentlyOpenedFiles(mFilenames);
137 }
138