niedziela, 14 grudnia 2014

Hide GRUB menu in Linux Mint 17.1

I have recently update my laptop's OS to Linux Min 17.1. Everything went smooth. I have used mintUpdate applet. Very easy and good solution for lazy people like me.

I have noticed only one problem, after reboot GRUB menu was shown (which didn't happened in 17.0). The old method used for Mint 17.0 didn't work.
After some digging I have found solution.


In console just execute: 

 sudo -H gedit /etc/default/grub  

Find and edit below lines:

 GRUB_DEFAULT=0  
 GRUB_HIDDEN_TIMEOUT=10  
 GRUB_HIDDEN_TIMEOUT_QUIET=true  
 GRUB_TIMEOUT=10  

Change default values to this one:

 GRUB_HIDDEN_TIMEOUT=0.0
 GRUB_HIDDEN_TIMEOUT_QUIET=true  
 GRUB_TIMEOUT=0.0  

and at the end of line add:

 GRUB_TIMEOUT_STYLE=hidden  


After changes it should look like this:

 GRUB_HIDDEN_TIMEOUT=0.0  
 GRUB_HIDDEN_TIMEOUT_QUIET=true  
 GRUB_TIMEOUT=0.0  
 GRUB_TIMEOUT_STYLE=hidden   

To finish just save changes in file and execute:

 sudo update-grub2  

After reboot GRUB menu won't show.

Disable selected checkboxes in checkcolumn of ExtJSTreeGrid?

I have recenty faced interesting problem. I needed TreeGrid component with checkcolumn. Easy, just add tree with column config.

Problems occurred when I needed to disable checkboxes in certain rows. ExtJS doesn't allow this. You can only disable whole column. I needed a solution, that will disable selected items (block checkchange event and change look of this elements - so the look like rest disabled things in ExtJS) and won't break checkcolumn used in other places of application

Using own renderer for checkcolumn wasn't possible. It would break whole column and it wasn’t recommended by Sencha devs. On Internet I have found similar problems and a lot solution, but none of them suited me. So after few tries I managed to solve this problem. Below I describe fix for ExtJS 5.1 (soon I will prepare 4.2 version).

For start I have create override for Ext.grid.column.CheckColumn class. For  processEvent (event proccessing for checkbox element) and second for defaultRenderer.

Ext.grid.column.CheckColumn.override({  
           processEvent: function(type, view, cell, recordIndex, cellIndex, e, record, row) {  
                var me = this,  
                  key = type === 'keydown' && e.getKey(),  
                  mousedown = type == 'mousedown';  
                if (!me.disabled && (mousedown || (key == e.ENTER || key == e.SPACE))) {  
                  var checked = !me.isRecordChecked(record);  
                  if(record.get(me.dataIndex) === null){  
                      return false;  
                  }  
                  if (me.fireEvent('beforecheckchange', me, recordIndex, checked) !== false) {  
                     me.setRecordCheck(record, checked, cell, row, e);  
                     me.fireEvent('checkchange', me, recordIndex, checked);  
                     if (mousedown) {  
                       e.stopEvent();  
                     }  
                     if (!me.stopSelection) {  
                       view.selModel.selectByPosition({  
                          row: recordIndex,  
                          column: cellIndex  
                       });  
                     }  
                     return false;  
                  } else {  
                     return !me.stopSelection;  
                  }  
                } else {  
                  return me.callParent(arguments);  
                }  
           },  
           defaultRenderer : function(value, cellValues) {  
                var cssPrefix = Ext.baseCSSPrefix,  
                cls = cssPrefix + 'grid-checkcolumn';  
                if (this.disabled) {  
                     cellValues.tdCls += ' ' + this.disabledCls;  
                }  
                if (value === null) {  
                    cellValues.tdCls += ' ' + this.disabledCls;                     
                }  
                if (value) {  
                     cls += ' ' + cssPrefix + 'grid-checkcolumn-checked';  
                }  
                return '<img class="' + cls + '" src="' + Ext.BLANK_IMAGE_URL + '"/>';  
           }  
      });  

I have marked red colour changes. Condition in proccessEvent return false if field related to checkcolumn has null (so checkchange event is not fired and elemnt doesn't change look when user click on it). Change in defaultRenderer adds CSS class (class for disabled elemnts) if value of rendered cell is null.

Now all we need is to create store and Tree Panel.

 var store = Ext.create('Ext.data.TreeStore', {  
           root: {  
                expanded: true,  
                children: [  
                     { text: "Office", leaf: true, isWorking: true },  
                     { text: "Finances", expanded: true, isWorking: false, children: [  
                          { text: "Personal", leaf: true, isWorking: null},  
                          { text: "Corporate", leaf: true, isWorking: false}  
                          ] },  
                     { text: "Legal Department", leaf: true , isWorking: null}  
                ]  
           }  
      });  
      Ext.create('Ext.tree.Panel', {  
           title: 'CheckColumn Tree',  
           store: store,  
           height: 400,  
           rootVisible: false,  
           renderTo: Ext.getBody(),  
           columns: [{  
                xtype: 'treecolumn',  
                text: 'Name',  
                flex: 2,  
                sortable: true,  
                dataIndex: 'text'  
           },{  
                xtype: 'checkcolumn',  
                text: 'Working',  
                flex: 1,  
                sortable: true,  
                dataIndex: 'isWorking',  
                align: 'center',  
                listeners: {  
                     checkchange: {  
                       fn: function(checkcolumn, rowIndex, checked, eOpts ){ console.log('Row %s checked change', rowIndex); }  
                     }  
                }  
           }]  
      });  


In this example checkcolunm is bind to isWorking field from root config from store. If I need to disable selected checkbox, I just to assign null value to certain field.

Normaly for Tree I would use store with model defintion (I'm lazy). So for tree with configured model there must be one change. 'isWOrking' field's config must have useNull set tu true (so null won't be converted to false).

 Ext.define('MyExampleApp.model.tree.exampleTreeModel', {  
   extend: 'Ext.data.Model',  
   requires: [  
     'Ext.data.Field'  
   ],  
   fields: [  
     {  
       name: 'text',  
       type: 'string'  
     },  
     {  
       name: 'leaf',  
       type: 'boolean'  
     },  
     {  
       name: 'expanded',  
       type: 'boolean'  
     },  
     {  
       name: 'isWorking',  
       type: 'boolean',  
       useNull: true  
     },  
   ]  
 });  


Below screenshoot with disabled checkboxes of selected rows.


















Source files for this example: disable-tree-checkcolumn.zip

Wyłączenie wybranych wierwszy kolumny Checkcolumn w drzewie (ExtJS TreeGrid)

Niedawno spotkałem się z ciekawym problem. Potrzebowałem komponent TreeGird z kolumną typu checkcolumn. Prosta sprawa - wystarczy w polu column dla drzewa dodać definicję kolumny i po sprawie.

Schody zaczęły się, gdy dla wybranych wierszy checkbox miał być wyłączony (disabled = true). Biblioteka ExtJS nie przewiduje takiej sytuacji. Można wyłączyć tylko całą kolumnę (wszystkie checkboxy). Potrzebowałem rozwiązania, które sprawi, że dla części wierszy nie będzie można kliknąć na checkbox w kolumnie oraz nie popsuje to kolumny checkcolumn w innych gridach i drzewach.

Konfiguracja własnego renderera dla kolumny nie wchodziła w grę - psuje to wyświetlanie całej kolumny. Nie jest też to zalecane przez programistów Sencha.
W sieci można odszukać mnóstwo tego typu problemów. Żadne z przedstawionych rozwiązań nie spełniało jednak moich potrzeb. Pominę tutaj wszystkie próby, który podjąłem i przedstawię działające rozwiązanie (na razie dla ExtJS 5.1 - wkrótce też dla wersji 4.2).

Rozwiązaniem okazało się przygotowanie overrida dla klasy Ext.grid.column.CheckColumn, dokładnie do dwóch metod: processEvent (odpowiada ona za obsługę zdarzeń dla checkboxa) oraz defaultRenderer (odpowiada za tworzenie elementu w kolumnie - konkretnego checkboxa).

Ext.grid.column.CheckColumn.override({  
           processEvent: function(type, view, cell, recordIndex, cellIndex, e, record, row) {  
                var me = this,  
                  key = type === 'keydown' && e.getKey(),  
                  mousedown = type == 'mousedown';  
                if (!me.disabled && (mousedown || (key == e.ENTER || key == e.SPACE))) {  
                  var checked = !me.isRecordChecked(record);  
                  if(record.get(me.dataIndex) === null){  
                      return false;  
                  }  
                  if (me.fireEvent('beforecheckchange', me, recordIndex, checked) !== false) {  
                     me.setRecordCheck(record, checked, cell, row, e);  
                     me.fireEvent('checkchange', me, recordIndex, checked);  
                     if (mousedown) {  
                       e.stopEvent();  
                     }  
                     if (!me.stopSelection) {  
                       view.selModel.selectByPosition({  
                          row: recordIndex,  
                          column: cellIndex  
                       });  
                     }  
                     return false;  
                  } else {  
                     return !me.stopSelection;  
                  }  
                } else {  
                  return me.callParent(arguments);  
                }  
           },  
           defaultRenderer : function(value, cellValues) {  
                var cssPrefix = Ext.baseCSSPrefix,  
                cls = cssPrefix + 'grid-checkcolumn';  
                if (this.disabled) {  
                     cellValues.tdCls += ' ' + this.disabledCls;  
                }  
                if (value === null) {  
                    cellValues.tdCls += ' ' + this.disabledCls;                     
                }  
                if (value) {  
                     cls += ' ' + cssPrefix + 'grid-checkcolumn-checked';  
                }  
                return '<img class="' + cls + '" src="' + Ext.BLANK_IMAGE_URL + '"/>';  
           }  
      });  

Na czerwono oznaczyłam kod, który został dodany. W metodzie processEvent został dodany warunek, który sprawdza, czy pole powiązane z kolumną ma wartość null. Dzięki temu po kliknięciu w komórkę z checkboxem, nic się nie dzieje. Zmiana w metodzie defaultRenderer odpowiada wyłączenie konkretnego elementu. Jeżeli wartość zmiennej value jest nullem, to do stylu CSS komórki zostaje dodana klasa CSS, która wyszarza element.

Ostatnim etapem jest utworzenie stora i komponentu Tree.

 var store = Ext.create('Ext.data.TreeStore', {  
           root: {  
                expanded: true,  
                children: [  
                     { text: "Office", leaf: true, isWorking: true },  
                     { text: "Finances", expanded: true, isWorking: false, children: [  
                          { text: "Personal", leaf: true, isWorking: null},  
                          { text: "Corporate", leaf: true, isWorking: false}  
                          ] },  
                     { text: "Legal Department", leaf: true , isWorking: null}  
                ]  
           }  
      });  
      Ext.create('Ext.tree.Panel', {  
           title: 'CheckColumn Tree',  
           store: store,  
           height: 400,  
           rootVisible: false,  
           renderTo: Ext.getBody(),  
           columns: [{  
                xtype: 'treecolumn',  
                text: 'Name',  
                flex: 2,  
                sortable: true,  
                dataIndex: 'text'  
           },{  
                xtype: 'checkcolumn',  
                text: 'Working',  
                flex: 1,  
                sortable: true,  
                dataIndex: 'isWorking',  
                align: 'center',  
                listeners: {  
                     checkchange: {  
                       fn: function(checkcolumn, rowIndex, checked, eOpts ){ console.log('Row %s checked change', rowIndex); }  
                     }  
                }  
           }]  
      });  

W konfiguracji kolumny "checkolumn" w polu dataIndex wpisujemy 'isWorking' (lub inną nazwę pola z konfiguracji modelu dla TreePanel).
Teraz wystarczy, aby serwer w metodzie do wypełniania drzewa zwracał null w wartości konkretnego pola.

Załączonym przykładzie odbywa się to przez ustawienie pola root dla stora.
W produkcyjnej aplikacji oczywiście do stora przypisany byłby konkretny model.
Ważne jest, aby model został skonfigurowany, tak aby przyjmował wartość null (domyślnie, jeżeli serwer zwróci w polu wartość null, zostanie ona zastąpiona przez false). W tym celu w modelu, w konfiguracji pola ustawiamy useNull na true.


 Ext.define('MyExampleApp.model.tree.exampleTreeModel', {  
   extend: 'Ext.data.Model',  
   requires: [  
     'Ext.data.Field'  
   ],  
   fields: [  
     {  
       name: 'text',  
       type: 'string'  
     },  
     {  
       name: 'leaf',  
       type: 'boolean'  
     },  
     {  
       name: 'expanded',  
       type: 'boolean'  
     },  
     {  
       name: 'isWorking',  
       type: 'boolean',  
       useNull: true  
     },  
   ]  
 });  


Od teraz wybrane checkboxy w drzewie lub gridzie będą nieaktywne (tak, jak na załączonym zrzucie). 


















Link do pobrania plików z działającym przykładem: disable-tree-checkcolumn.zip

piątek, 12 grudnia 2014

Ukrycie menu GRUB w systemie Linux Mint 17.1

Wczoraj stałem się szczęśliwym użytkownikiem systemu Linux Mint 17.1 Cinnamon. Aktualizacja odbyła się za pomocą apletu mintUpdate i przebiegła szybko i sprawnie.

Po restarcie zauważyłam jeden problem. System w wersji 17.0 nie pokazywał menu GRUB (po ekranie BIOSu ładował się system). Po aktualizacji nastąpiła zmiana i menu pojawia się za każdym razem. Jest ono zbędne jeżeli korzysta się tylko z systemu Linux.


W konsoli wykonujemy polecenie:

 sudo -H gedit /etc/default/grub  

W edytorze tekstu, na samej górze, odszukujemy poniższe zmienne:

 GRUB_DEFAULT=0  
 GRUB_HIDDEN_TIMEOUT=10  
 GRUB_HIDDEN_TIMEOUT_QUIET=true  
 GRUB_TIMEOUT=10  

Ustawiamy ich wartości w następujący sposób:

 GRUB_HIDDEN_TIMEOUT=0.0
 GRUB_HIDDEN_TIMEOUT_QUIET=true  
 GRUB_TIMEOUT=0.0  

Na końcu dodajemy linię:

 GRUB_TIMEOUT_STYLE=hidden  


Po zmianach wszystko powinno wyglądać tak:

 GRUB_HIDDEN_TIMEOUT=0.0  
 GRUB_HIDDEN_TIMEOUT_QUIET=true  
 GRUB_TIMEOUT=0.0  
 GRUB_TIMEOUT_STYLE=hidden   

Zmiany w pliku zapisujemy . Na koniec wykonujemy polecenie:

 sudo update-grub2  

Zmiany zostaną zapisane na dysku. Po restarcie menu GRUB nie będzie się już pojawiać.

Początek

Najlepiej zacząć od Bacha, czyli wyjaśnić, dlaczego ten blog powstał.

Zawodowo zajmuję się komputerami - grafiką, programowaniem oraz tworzeniem stron. W ciągu kilku lat  mojej przygody z informatyką nazbierała się cała masa problemów, których rozwiązania nie udało mi się znaleźć w sieci czy książkach. Większość z nich udało się pokonać uporem - siedziałem nad nimi tak długo, aż w końcu spływało na mnie olśnienie i jednym ciosem kładem błąd/problem na deski. Uzbierało się tego trochę i doszedłem do wniosku, że pora przekazać tę wiedzę dalej i zaoszczędzić innym czasu na szukaniu rozwiązania tych problemów.

Dlaczego malkontent i maruda? Ponieważ taki mam charakter, lubię sobie ponarzekać. Po muzyce i byciu złośliwym to moja trzecia pasja.
Muzyka i złośliwość jest jak tlen, trudno bez nich żyć